我正在使用 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.