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!