Я работаю над Excel Addin с помощью C#, Visual Studio 2012. Я пытаюсь получить экземпляр объекта приложения Excel, чтобы отслеживать текущую рабочую книгу и рабочий лист (ActiveWorkbook, ActiveWorksheet).Ошибка C# .NET при запуске экземпляра приложения Office
Я вижу, что большинство других связанных с этим вопросов на 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.
В некоторых редких случаях "план Б" делает работу; Я не вижу второго окна сообщения. CurrentSpreadSheet - это singleton, и я намерен обновить его во время запуска из предоставленного класса 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.
Я имел такую же проблему, даже когда я поставил 'CurrentSpreadSheet CSS = CurrentSpreadSheet.Instance;' часть внутри 'ThisAddIn_Startup' метода. Является ли это другой проблемой или я все еще пытаюсь получить доступ к объекту раньше, чем доступно? –
Это другая проблема. Имейте в виду, что при запуске Excel пользователь еще не выбрал расширенный лист. Используйте события в WorkBooks и т. Д., Поэтому см., Когда электронные таблицы загружаются и выбираются. –