3

我正在使用 C#、Visual Studio 2012 开发 Excel 插件。我正在尝试获取 Excel 的 Application 对象的实例,以便跟踪当前活动的工作簿和工作表(ActiveWorkbook、ActiveWorksheet)。

我看到关于 SO 的大多数其他相关问题都有回复建议使用以下内容:

(Excel.Application)Marshal.GetActiveObject("Excel.Application");

我也试过用这个:

(Excel.Application)Globals.ThisAddIn.Application;

在这两种情况下,我都会得到 NullReferenceException。查看此处建议的解决方法后:http: //support.microsoft.com/kb/316125/en-us,我尝试了以下方法来测试这两种方法。

public CurrentSpreadSheet()
    {
        try
        {
            this.CurrentApplication = (Excel.Application)Globals.ThisAddIn.Application;

        }
        catch (NullReferenceException)
        {
            MessageBox.Show("Excel application object not registered. Trying plan B..");

            //Getting Excel's application object instance
            int iSection = 0, iTries = 0;

        tryAgain:
            try
            {
                iSection = 1; //Attempting GetActiveObject
                this.CurrentApplication = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
                iSection = 0; //GetActiveObject succeeded so resume or go for normal error handling if needed
                this.CurrentApplication.Visible = true;
            }
            catch (Exception err)
            {
                System.Console.WriteLine("Visual C# .NET Error Attaching to Running Instance of Office Application .. yet.");
                if (iSection == 1)
                {
                    //GetObject may have failed because the
                    //Shell function is asynchronous; enough time has not elapsed
                    //for GetObject to find the running Office application. Wait
                    //1/2 seconds and retry the GetObject. If we try 20 times
                    //and GetObject still fails, we assume some other reason
                    //for GetObject failing and exit the procedure.
                    iTries++;
                    if (iTries < 20)
                    {
                        System.Threading.Thread.Sleep(500); // Wait 1/2 seconds.
                        goto tryAgain; //resume code at the GetObject line
                    }
                    else
                    {
                        MessageBox.Show("GetObject still failing.  Process ended.");
                    }

                }
                else
                {
                    //iSection == 0 so normal error handling
                    MessageBox.Show(err.Message);
                }
            }
        }


    }

输出是:

Excel application object not registered. Trying plan B..
GetObject still failing.  Process ended.

在极少数情况下,“B 计划”确实有效;我没有看到第二个消息框。CurrentSpreadSheet 是一个单例,我打算在启动期间从提供的类 ThisAddIn 更新它。

在 ThisAddIn 我有类似的东西:

private CurrentSpreadSheet css = CurrentSpreadSheet.Instance;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        ///...Some code
        css.updateCurrentSpreadSheet();
}

有没有更好的方法来获取 Application 对象?如果这在启动期间不可能,是否有更好的方法可以让我从 excel/我的加载项启动时跟踪当前活动的工作表/工作簿?目前,我依靠 Application 对象(例如(Excel.Workbook)this.CurrentApplication.ActiveWorkbook;)和一些事件处理程序来跟踪当前的工作簿和工作表。

我尝试使用 ExcelDNA:

this.CurrentApplication = (Excel.Application)ExcelDna.Integration.ExcelDnaUtil.Application;

这在某些时候有效,但大多数情况下会出现此错误:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> ExcelDna.Integration.XlCallException: Exception of type 'ExcelDna.Integration.XlCallException' was thrown.
4

2 回答 2

3

请记住,Office 加载项在Office进程中运行。所以你永远不想找到一个外部进程。当您使用 Office 项目模板时获得的样板ThisAddIn类将您在银盘上寻找的 Application 对象交给您,使用它的Application属性。您第一次可以在 Startup 事件中使用它,请确保您不要提前尝试。所以不要在你的构造函数中做任何激烈的事情,不要用初始化表达式初始化类成员,等到 Startup 触发。

相关的 MSDN 页面在这里,“访问主机应用程序的对象模型”部分。

于 2013-07-17T12:50:44.353 回答
0

您可以仔细查看http://netoffice.codeplex.com/在那里您可以找到更多关于 Word/Excel/Powerpoint 插件的内容。加载加载项时还要记住 GuidAttribute,因为根据您的 Office 版本,它不会再工作了,并且检查以保持您的项目是否为 32/64 位,最好是任何 CPU。此外,请记住将您的加载项注册到注册表中以供进一步使用。如果您想了解更多信息,请随时给我写邮件。

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.guidattribute.aspx

于 2013-07-17T13:05:53.097 回答