現在アクティブなワークブックとワークシート (ActiveWorkbook、ActiveWorksheet) を追跡するために、Excel の Application オブジェクトのインスタンスを取得しようとしています。
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」が機能する場合があります。2 番目のメッセージ ボックスが表示されません。CurrentSpreadSheet はシングルトンであり、提供されたクラス ThisAddIn から起動時に更新する予定です。
ThisAddIn には次のようなものがあります。
private CurrentSpreadSheet css = CurrentSpreadSheet.Instance;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
///...Some code
css.updateCurrentSpreadSheet();
}
Application オブジェクトを取得するより良い方法はありますか? 起動時にこれが不可能な場合、Excel/アドインの起動時から現在アクティブなワークシート/ワークブックを追跡できるより良い方法はありますか? (Excel.Workbook)this.CurrentApplication.ActiveWorkbook;
現在、現在のワークブックとワークシートを追跡するために、Application オブジェクト (例: ) といくつかのイベント ハンドラーに依存しています。
私は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.