2009-07-20 15 views
6

Ho un AddIn che voglio richiamare tramite l'interoperabilità di Excel da un'applicazione winforms C#.Come caricare un componente aggiuntivo di Excel utilizzando Interop

Impossibile caricare l'addin ecc. A meno che non lo disinstallo e lo reinstalli ogni volta (questo è apparentemente qualcosa a che fare con Excel not loading addins when you use interop - btw, non è possibile ottenere il loro esempio per lavorare in C#). Purtroppo questo è lento e fastidioso per l'utente, quindi ho bisogno di semplificarlo.

Voglio avere un'istanza di Excel ma caricare un addin già installato senza forzare questo problema di installazione/reinstallazione.

Ho cercato e cercato ma tutto quello che trovo su google fornisce la soluzione per installare/reinstallare. C'è un altro modo? Il componente aggiuntivo è installato, voglio solo Excel per caricarlo.

Questo è quello che sto facendo in questo momento (presa dal consiglio google'd):

// loop over the add-ins and if you find it uninstall it. 
foreach (AddIn addIn in excel.AddIns) 
    if (addIn.Name.Contains("My Addin")) 
     addin.Installed = false; 

    // install the addin 
    var addin = excel.AddIns.Add("my_addin.xll", false); 
     addin.Installed = true; 
+0

Potrebbe spiegare il motivo per cui è necessario fare Installa/Rimuovi? Sto cercando di capire il modo in cui Excel carica addin, una volta che lo imposti per caricarlo ogni volta. Perché richiede l'installazione/disinstallazione? – shahkalpesh

+0

da dove viene chiamato questo codice? presumo un altro AddIn Excel? o solo un'app C# winform? –

+0

Ho aggiornato la domanda con i punti che hai sollevato ma rapidamente: Excel non carica addin tramite l'interoperabilità, tutto quello che ho trovato in rete dice che la disinstallazione/installazione è la soluzione. Il codice viene chiamato da una C# winforms app – user35149

risposta

7

Dopo un po 'ho trovato la risposta nascosta in luoghi strani nella MS help: e this blog post.

Queste non sono tutte le informazioni necessarie. Cose da notare: è necessario avere almeno una cartella di lavoro aperta o in alternativa Excel barfs. Ecco qualche codice rudementry per iniziare:

var excel = new Application(); 
var workbook = excel.workbooks.Add(Type.Missing); 
excel.RegisterXLL(pathToXll); 
excel.ShowExcel(); 

Se si vuole si può chiudere la cartella di lavoro temporaneo (se si è a corto alcune macro etc.) e ricordarsi di riordinare tutto con un sacco di chiamate a Marshal.ReleaseComObject!

0

Sembra che sia necessario ottenere il corretto processo di Excel con cui lavorare. Utilizzare questa classe per aprire il documento di Excel:

class ExcelInteropService 
{ 
    private const string EXCEL_CLASS_NAME = "EXCEL7"; 

    private const uint DW_OBJECTID = 0xFFFFFFF0; 

    private static Guid rrid = new Guid("{00020400-0000-0000-C000-000000000046}"); 

    public delegate bool EnumChildCallback(int hwnd, ref int lParam); 

    [DllImport("Oleacc.dll")] 
    public static extern int AccessibleObjectFromWindow(int hwnd, uint dwObjectID, byte[] riid, ref Window ptr); 

    [DllImport("User32.dll")] 
    public static extern bool EnumChildWindows(int hWndParent, EnumChildCallback lpEnumFunc, ref int lParam); 

    [DllImport("User32.dll")] 
    public static extern int GetClassName(int hWnd, StringBuilder lpClassName, int nMaxCount); 

    public static Application GetExcelInterop(int? processId = null) 
    { 
     var p = processId.HasValue ? Process.GetProcessById(processId.Value) : Process.Start("excel.exe"); 
     try 
     { 
      Thread.Sleep(5000); 
      return new ExcelInteropService().SearchExcelInterop(p); 
     } 
     catch (Exception) 
     { 
      Debug.Assert(p != null, "p != null"); 
      return GetExcelInterop(p.Id); 
     } 
    } 

    private bool EnumChildFunc(int hwndChild, ref int lParam) 
    { 
     var buf = new StringBuilder(128); 
     GetClassName(hwndChild, buf, 128); 
     if (buf.ToString() == EXCEL_CLASS_NAME) { lParam = hwndChild; return false; } 
     return true; 
    } 

    private Application SearchExcelInterop(Process p) 
    { 
     Window ptr = null; 
     int hwnd = 0; 

     int hWndParent = (int)p.MainWindowHandle; 
     if (hWndParent == 0) throw new Exception(); 

     EnumChildWindows(hWndParent, EnumChildFunc, ref hwnd); 
     if (hwnd == 0) throw new Exception(); 

     int hr = AccessibleObjectFromWindow(hwnd, DW_OBJECTID, rrid.ToByteArray(), ref ptr); 
     if (hr < 0) throw new Exception(); 

     return ptr.Application; 
    } 
} 

utilizzare la classe nell'applicazione in questo modo:

static void Main(string[] args) 
{ 
    Microsoft.Office.Interop.Excel.Application oExcel = ExcelInteropService.GetExcelInterop(); 
    foreach (AddIn addIn in oExcel.AddIns) 
     { 
      addIn.Installed = true; 
     } 
} 
Problemi correlati