【问题标题】:starting excel application with addins from c# application使用来自 c# 应用程序的插件启动 excel 应用程序
【发布时间】:2016-01-29 16:11:58
【问题描述】:

我有一个 c# 应用程序,它需要创建一个 excel 应用程序然后打开一个工作簿。问题是我需要在打开 excel 时加载 Bloomberg 插件。我发现的唯一方法是在这篇文章中working example

这确实启动了 excel 并且能够使用 Bloomberg 功能。但是我想知道是否有办法将 myXl 转换为 xlApp,其中 xlApp 的类型为 Microsoft.Office.Interop.Excel.Application?

var myXl = Process.Start("excel.exe");

原因是我有一个库,它有一些我希望使用的有用功能,但它需要一个 Microsoft.Office.Interop.Excel.Application 类型的参数。我该怎么做?

【问题讨论】:

  • 添加对 Excel 库的引用,而不是 var myXL 您可以实例化工作簿对象 Excel.Application myXl = New Excel.Application();
  • 这个问题是Bloomberg插件无法使用该方法加载
  • 你看过这个帖子吗:stackoverflow.com/questions/213375/…
  • 你有时间检查我的答案吗?

标签: c# .net office-interop excel-interop


【解决方案1】:

您可以从外部应用程序自动化 Excel。请参阅How to automate Microsoft Excel from Microsoft Visual C#.NETC# app automates Excel (CSAutomateExcel) 了解更多信息。

Application 类提供了以下用于访问加载项的属性:

  • AddIns - 返回一个 AddIns 集合,该集合代表“加载项”对话框中列出的所有加载项(“开发人员”选项卡上的“加载项”命令); XLL 加载项。
  • COMAddIns - 返回 Microsoft Excel 的 COMAddIns 集合,代表当前安装的 COM 加载项。

因此,如果您需要确保启用了 COM 加载项,则需要使用 Application 类的 ComAddins 属性。

【讨论】:

    【解决方案2】:

    您可以使用以下代码:

    这将启动 Excel,然后遍历在运行对象表中注册的所有工作簿,以找到在刚刚启动的进程中运行的工作簿。为此,它获取工作簿窗口句柄的进程 ID,并将其与刚刚启动的进程的 ID 进行比较。

    这种在运行对象表中的查找重复了几次,中间有等待时间,因为 Excel 在启动后可能需要一些时间来向 ROT 注册。在速度较慢的计算机上,您可能需要增加 maxAttemptswaitTimeMS

    如果找到正确的工作簿,则将其返回。在示例中,我将在 Excel 应用程序实例的第一个单元格中写入“hello world”。

    private void button1_Click(object sender, EventArgs e)
    {
         Microsoft.Office.Interop.Excel.Application excelApplication = StartExcel();
    
        if (excelApplication != null)
        {
            excelApplication.ActiveCell.Value = "Hello World";
        }
    }
    
    [DllImport("user32.dll", SetLastError = true)]
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
    
    [DllImport("ole32.dll")]
    private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
    
    private Microsoft.Office.Interop.Excel.Application StartExcel()
    {
        // Maximum number of attempts to look for started Excel Application
        const int maxAttempts = 3;
        // Number of milliseconds to wait between attempts to look for started Excel Application
        const int waitTimeMS = 200;
    
        Microsoft.Office.Interop.Excel.Application result = null;
    
        // Start Excel
        var process = Process.Start("Excel.exe");
        process.WaitForInputIdle();
    
        // Try to find started Excel Application
    
        int currentAttempt = 1;
    
        while ((result == null) && (currentAttempt <= maxAttempts))
        {
            // Wait between attempts 
            if(currentAttempt != 1)
            {
                Thread.Sleep(waitTimeMS);
            }
    
            // List all running Excel automation objects and find the one with the same process id
            IRunningObjectTable lRunningObjectTable = null;
            IEnumMoniker lMonikerList = null;
    
            try
            {
                // Query Running Object Table 
                if (GetRunningObjectTable(0, out lRunningObjectTable) == 0 && lRunningObjectTable != null)
                {
    
                    // List Monikers
                    lRunningObjectTable.EnumRunning(out lMonikerList);
    
                    // Start Enumeration
                    lMonikerList.Reset();
    
                    // Array used for enumerating Monikers
                    IMoniker[] lMonikerContainer = new IMoniker[1];
    
                    IntPtr lPointerFetchedMonikers = IntPtr.Zero;
    
                    // foreach Moniker
                    while (lMonikerList.Next(1, lMonikerContainer, lPointerFetchedMonikers) == 0)
                    {
                        object lComObject;
                        lRunningObjectTable.GetObject(lMonikerContainer[0], out lComObject);
    
                        // Check the object is an Excel workbook
                        if (lComObject is Microsoft.Office.Interop.Excel.Workbook)
                        {
                            Microsoft.Office.Interop.Excel.Workbook lExcelWorkbook = (Microsoft.Office.Interop.Excel.Workbook)lComObject;
    
                            // Get the Process ID for the Window Handle 
                            uint processId;
                            GetWindowThreadProcessId(new IntPtr(lExcelWorkbook.Application.Hwnd), out processId);
    
                            if (processId == process.Id)
                            {
                                // Correct automation object found, return Application
                                result = lExcelWorkbook.Application;
                                break;
                            }
                        }
                    }
                }
            }
            finally
            {
                // Release ressources
                if (lRunningObjectTable != null) Marshal.ReleaseComObject(lRunningObjectTable);
                if (lMonikerList != null) Marshal.ReleaseComObject(lMonikerList);
            }
    
            currentAttempt++;
        }
    
    
        return result;
    }
    

    【讨论】:

      【解决方案3】:

      添加对 Excel 库的引用,您可以实例化一个工作簿对象,而不是 var myXL

      Excel.Application myXl = New Excel.Application();  
      

      然后你只需要手动加载加载项。

              foreach (Excel.AddIn item in myXl.AddIns)
              {
                  if (item.Name.Equals("BLOOMBERG ADDIN NAME"))
                  {
                      item.Installed = true;
                  }
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-26
        相关资源
        最近更新 更多