Using Visual Studio Enterprise 2015 and office 2013 pro, I have created an Excel 2013 addin and when I debug it, I am unable to reference the Application.Workbook object! Here is a minimal example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
namespace ExcelAddIn1
{
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
var app = Globals.ThisAddIn.Application;
var wb = app.ThisWorkbook;
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
On attempting to assign wb, I receive the error:
"An exception of type 'System.Runtime.InteropServices.COMException' occurred in ExcelAddIn1.dll but was not handled in user code".
On inspection (quick watch) of the application object many of the properties have the value:
{System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Runtime.InteropServices.COMException: Old format or invalid type library. (Exception from HRESULT: 0x80028018 (TYPE_E_INVDATAREAD))"
It seems the application object has no workbook, amongst other problems. I'm sure that the code is ok, but perhaps there is something wrong with my .Net framework or office versions or build settings? Can anyone shed any light on this please?
** Edit 1 **
So based on Richard Morgan's suggestion I tried the following, having seen that there may be no active workbook when the original code runs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
namespace ExcelAddIn1
{
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.WorkbookActivate += new Excel.AppEvents_WorkbookActivateEventHandler(WorkWithWorkbook);
}
private void WorkWithWorkbook(Microsoft.Office.Interop.Excel.Workbook workbook)
{
// Workbook has been opened. Do stuff here.
var app = Globals.ThisAddIn.Application;
Excel.Workbook wb = app.ThisWorkbook;
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
So when WorkWithWorkbook() is executed, I expect that there is an ActiveWorkbook to get a reference to. Unfortunately, I still get the COMException with:
"Exception from HRESULT: 0x800A03EC".
Further checking of the application object shows that the workbooks collection is partially populated but many properties still refer to:
System.Runtime.InteropServices.COMException - Old Format or Invalid Type Library
Further searching has revealed that this can be caused by mismatching region settings between Excel and VS code, but I've checked that the regions match in this case.
Edit 2
So perhaps I'm being very foolish here! Further reading shows that the application's .ThisWorkbook property returns a reference to the workbook in which the code is contained. As this is an add-in, the code is contained in .dll. So instead, I used .ActiveWorkbook, which returned a reference without throwing an exception!
That is strange code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.WorkbookActivate += new Excel.AppEvents_WorkbookActivateEventHandler(WorkWithWorkbook);
}
private void WorkWithWorkbook(Microsoft.Office.Interop.Excel.Workbook workbook)
{
// Workbook has been opened. Do stuff here.
var app = Globals.ThisAddIn.Application;
Excel.Workbook wb = app.ThisWorkbook;
}
So, Excel provides you with the exact Workbook
which has just been Activated, then you run code to work it out yourself ?!
Be very careful with this.
We have had issues with ActiveWorkbook
and ThisWorkbook
in our VSTO Excel Addin, particularly when users "do something" to kick off our VSTO code, but they have other Excel files open, or our VSTO task takes some time, and they switch to another workbook in the meantime.
The best (only?) way to make sure that your code is dealing with the right file is to always use the Workbook
which is passed to your OnActivate
function.
private void WorkWithWorkbook(Microsoft.Office.Interop.Excel.Workbook workbook)
{
// Do some stuff directly with "workbook"
//
}
As for the 0x800A03EC error, it seems to be one of Excel's generic "this could mean anything" COM errors.
We've also seen it when attempting to work out which Excel Workbook
object we should be using.
Because the add-in code was not contained in a workbook, the Application.ThisWorkbook
property is not set. The Application.ThisWorkbook
property is used to return a reference to the workbook containing the code, and no such workbook exists!
In order to get a reference to the workbook currently open and causing the code to be executed, the Application.ActiveWorkbook
reference should be used instead.
User contributions licensed under CC BY-SA 3.0