2009-07-20 62 views
6

我有一個AddIn,我想通過Excel Interop從C#winforms應用程序調用。如何使用Interop加載Excel加載項

我不能得到插件等加載,除非我每次卸載和resinstall它(這是顯然是Excel not loading addins when you use interop - 順便說一句,無法讓他們的例子在C#中工作)。不幸的是,這對用戶來說很慢並且很煩人,所以我需要簡化它。

我想有一個Excel實例,但加載已安裝的插件而不強制安裝/重新安裝問題。

我搜索和搜索,但我發現在谷歌上的一切都給出了安裝/重新安裝的解決方案。有沒有其他方法?加載項已安裝,我只是想要加載它。

這就是我目前做的(從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

你能,爲什麼你需要做的安裝/卸載解釋一下嗎?我試圖瞭解Excel加載插件的方式,一旦您將其設置爲每次加載。爲什麼需要安裝/卸載? – shahkalpesh 2009-07-20 16:48:59

回答

7

過了一會兒,我發現隱藏在陌生的地方在MS help了答案:和this blog post

這不是你需要的所有信息。注意事項:您必須至少打開一個工作簿或Excel barfs。這裏的一些rudementry代碼開始:

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

如果你願意,你可以關閉該工作簿臨時(如果你運行一些宏等),並記住一切都收拾起來,用大量調用Marshal.ReleaseComObject的了!

0

看來你必須得到正確的Excel過程才能使用。使用此類打開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; 
    } 
} 

使用類應用程序是這樣的:

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