Office 2013 c# 加载项 - 空工作簿对象 HRESULT:0x800A03EC 错误

Office 2013 c# add-in - Null workbook object HRESULT: 0x800A03EC error

使用 Visual Studio Enterprise 2015 和 office 2013 pro,我创建了一个 Excel 2013 插件,当我调试它时,我无法引用 Application.Workbook 对象!这是一个最小的例子:

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
    }
}

在尝试分配 wb 时,我收到错误消息:

"An exception of type 'System.Runtime.InteropServices.COMException' occurred in ExcelAddIn1.dll but was not handled in user code".

在检查(快速观察)应用程序对象时,许多属性具有以下值:

{System.Reflection.TargetInvocationException:调用目标抛出异常。 ---> System.Runtime.InteropServices.COMException: 旧格式或无效类型库。 (HRESULT 异常:0x80028018(TYPE_E_INVDATAREAD))“

应用程序对象似乎没有工作簿,还有其他问题。 我确定代码没问题,但也许我的 .Net 框架或办公版本或构建设置有问题? 任何人都可以对此有所了解吗?

** 编辑 1 **

因此,根据 Richard Morgan 的建议,我尝试了以下操作,发现原始代码运行时可能没有活动工作簿:

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
    }
}

因此,当执行 WorkWithWorkbook() 时,我希望有一个 ActiveWorkbook 可供参考。不幸的是,我仍然得到 COMException:

"Exception from HRESULT: 0x800A03EC".

进一步检查应用程序对象表明工作簿集合已部分填充,但许多属性仍引用:

System.Runtime.InteropServices.COMException - 旧格式或无效类型库

进一步搜索发现这可能是由于 Excel 和 VS code 之间的区域设置不匹配造成的,但我已经检查过在这种情况下区域是否匹配。

编辑 2

所以也许我在这里很愚蠢!进一步阅读表明,应用程序的 .ThisWorkbook 属性 returns 是对包含代码的工作簿的引用。由于这是一个加载项,因此代码包含在 .dll 中。因此,我使用了 .ActiveWorkbook,它返回了一个引用而没有抛出异常!

由于工作簿中不包含加载项代码,因此未设置 Application.ThisWorkbook 属性。 Application.ThisWorkbook 属性 用于return 对包含代码的工作簿的引用,并且不存在这样的工作簿!

为了获得对当前打开的工作簿的引用并导致代码被执行,应该改用 Application.ActiveWorkbook 引用。

奇怪的代码:

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;
}

因此,Excel 为您提供刚刚激活的确切 Workbook,然后您 运行 自己编写代码?!

对此要非常小心。

我们的 VSTO Excel 插件中的 ActiveWorkbookThisWorkbook 有问题,特别是当用户 "do something" 启动我们的 VSTO 代码时,但他们有其他问题Excel 个文件打开,或者我们的 VSTO 任务需要一些时间,同时它们切换到另一个工作簿。

确保代码处理正确文件的最佳(唯一?)方法是始终使用传递给 OnActivate 函数的 Workbook

private void WorkWithWorkbook(Microsoft.Office.Interop.Excel.Workbook workbook)
{
    //  Do some stuff directly with "workbook" 
    //  
}

至于 0x800A03EC 错误,它似乎是 Excel 的通用 "this could mean anything" COM 错误之一。

我们在尝试计算我们应该使用哪个ExcelWorkbook对象时也看到了它。