C# 如何使用互操作加载Excel加载项

C# 如何使用互操作加载Excel加载项,c#,excel,interop,C#,Excel,Interop,我有一个加载项,我想通过Excel互操作从C#winforms应用程序调用它 我无法加载加载项等,除非每次都卸载并重新安装它(这显然与-btw有关,无法让他们的示例在C#中工作)。不幸的是,这是缓慢和烦人的用户,所以我需要精简它 我希望有一个Excel实例,但加载一个已安装的加载项,而不强制执行此安装/重新安装问题 我搜索了又搜索,但我在谷歌上找到的所有东西都提供了安装/重新安装的解决方案。还有别的办法吗?加载项已安装,我只希望excel加载它 这就是我目前正在做的事情(摘自谷歌的建议): 过了

我有一个加载项,我想通过Excel互操作从C#winforms应用程序调用它

我无法加载加载项等,除非每次都卸载并重新安装它(这显然与-btw有关,无法让他们的示例在C#中工作)。不幸的是,这是缓慢和烦人的用户,所以我需要精简它

我希望有一个Excel实例,但加载一个已安装的加载项,而不强制执行此安装/重新安装问题

我搜索了又搜索,但我在谷歌上找到的所有东西都提供了安装/重新安装的解决方案。还有别的办法吗?加载项已安装,我只希望excel加载它

这就是我目前正在做的事情(摘自谷歌的建议):


过了一会儿,我发现答案就藏在了一个陌生的地方:和

但这并不是你所需要的全部信息。注意事项:您必须至少打开一个工作簿或Excel barfs。下面是一些入门的基本代码:

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

如果需要,您可以关闭临时工作簿(如果您运行了一些宏等),并记住通过大量调用Marshal.ReleaseComObject来整理一切

看来您必须使用正确的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;
    }
}

我有一个类似的问题,上面的解决方案似乎都不适合我。因此,我最终想到了将“.xla”文件作为工作簿打开的想法:

//I first get the path to file, in my case it was in the same dir as the .exe
var XLA_NAME = Path.Combine(Directory.GetCurrentDirectory(), ".xla");

Excel.Application xlRep = new Excel.Application();
xlRep.visible = true;
xlRep.Workbooks.Open("XLA_NAME");

您能解释一下为什么需要安装/卸载吗?我试图了解Excel加载加载插件的方式,只要您每次将其设置为加载。为什么需要安装/取消安装?从何处调用此代码?我想是另一个Excel AddIn?或者只是一个winform C#应用程序?我已经用您提出的要点更新了这个问题,但很快:Excel不会通过互操作加载加载项,我在网上找到的所有东西都表明卸载/安装是解决方案。正在从c#winforms调用代码app@shahkalpesh请注意,
Installed
的意思更像是“enabled”。将Installed属性设置为false然后设置为true不会“安装”和“卸载”,只会打开和关闭加载项。
static void Main(string[] args)
{
    Microsoft.Office.Interop.Excel.Application oExcel = ExcelInteropService.GetExcelInterop();
    foreach (AddIn addIn in oExcel.AddIns)
        {
            addIn.Installed = true;
        }
}
//I first get the path to file, in my case it was in the same dir as the .exe
var XLA_NAME = Path.Combine(Directory.GetCurrentDirectory(), ".xla");

Excel.Application xlRep = new Excel.Application();
xlRep.visible = true;
xlRep.Workbooks.Open("XLA_NAME");