在 Excel /automation 中强制加载插件

Posted

技术标签:

【中文标题】在 Excel /automation 中强制加载插件【英文标题】:Force addin load in Excel /automation 【发布时间】:2019-10-28 14:37:11 【问题描述】:

我有一个提供一组 UDF 的 Excel 自动化插件。即使通过互操作 API 打开 Excel,我也想让这些 UDF 正常工作。我知道当通过互操作 API 打开 Excel 时,Excel 以参数 /automation 启动,这使得 Excel not load addins。为了解决这个问题,我添加了以下Workbook_Open() 事件:

Private Sub Workbook_Open()
    Application.AddIns("SomeApp.DemoAddin").Installed = False
    Application.AddIns("SomeApp.DemoAddin").Installed = True
End Sub

此代码成功加载插件。我验证了在插件中使用了一些日志记录。

我整理了一个名为 UDF =myDemoFunction() 的测试工作簿。 通过"C:\path\to\EXCEL.exe" /automation C:\path\to\workbook.xlsm 打开该工作簿时,我观察到以下行为。 首先,带有 UDF 的单元格显示正确的结果(在本例中为“15.0”)。该公式显示为=SomeApp.DemoAddin.myDemoFunction(),但通常仅在未加载插件时才会出现这种情况。 当使用CTRL+ALT+F9 重新计算或在VBA 中执行Application.CalculationFullRebuild 或什至使用ThisWorkbook.Worksheets(1).UsedRange.Dirty 将所有填充的单元格标记为脏时,所有这些都会导致具有UDF 的单元格显示#NAME?。编辑其中一个 UDF 单元格(选择、F2Return)时,该一张纸上的所有 UDF(不在其他也使用该 UDF 的纸上)突然再次返回正确的结果,并且公式再次更改为 =myDemoFunction() .

所以我的问题是,如何触发 Excel 以编程方式识别插件?


我的代码库要大得多,但下面是显示此行为的自动化插件的精简版本(在 VB.net 中):

Imports Extensibility
Imports System.Runtime.InteropServices
Imports Excel = Microsoft.Office.Interop.Excel

<GuidAttribute("352B1C10-DC5A-4BF8-9D31-DB9913B07364"),
ProgIdAttribute("SomeApp.DemoAddin"),
ClassInterface(ClassInterfaceType.AutoDual)>
Public Class DemoAddin
    Implements IDTExtensibility2

    Private excelApp As Excel.Application

    Public Sub OnBeginShutdown(ByRef custom As Array) Implements IDTExtensibility2.OnBeginShutdown
    End Sub
    Public Sub OnAddInsUpdate(ByRef custom As Array) Implements IDTExtensibility2.OnAddInsUpdate
    End Sub
    Public Sub OnStartupComplete(ByRef custom As Array) Implements IDTExtensibility2.OnStartupComplete
    End Sub

    Public Sub OnDisconnection(RemoveMode As ext_DisconnectMode, ByRef custom As Array) Implements IDTExtensibility2.OnDisconnection
        Marshal.ReleaseComObject(excelApp)
        excelApp = Nothing
    End Sub

    Public Sub OnConnection(application As Object, connectMode As ext_ConnectMode, addInInst As Object, ByRef custom As Array) Implements IDTExtensibility2.OnConnection
        excelApp = CType(application, Excel.Application)
    End Sub

    Public Function myDemoFunction() As String
        Return excelApp.Version
    End Function
End Class

【问题讨论】:

【参考方案1】:

调用从 VBA 中断的所有 UDF 就足够了。所以更新的Workbook_Open() 可以解决问题。下面的代码还进行了一些探索,以免不必要地重新加载插件,但这是不是必要的。真正的魔力在倒数第二行Application.Run "myDemoFunction"

Private Sub Workbook_Open()
    ensureAddinLoaded
End Sub

Public Sub ensureAddinLoaded()
    Debug.Print "Probing for addin"
    On Error GoTo NotLoaded
    Application.Run "myDemoFunction"
    Exit Sub
NotLoaded:
    Debug.Print "Addin not loaded. Reloading."
    Application.AddIns("SomeApp.DemoAddin").Installed = False
    Application.AddIns("SomeApp.DemoAddin").Installed = True
    Application.Run "myDemoFunction"
End Sub

这个解决方案需要知道有哪些确切的 UDF,所以它不是最理想的。

【讨论】:

以上是关于在 Excel /automation 中强制加载插件的主要内容,如果未能解决你的问题,请参考以下文章

使用存储过程中的数据创建 Excel 文件,以将其附加到 Power Automate 中的电子邮件中

登录 Revit Design Automation 加载项

Snow Leopard Automator:尝试创建用于转换 Excel 文件的工作流程

如何使用SAP Intelligent Robotic Process Automation自动操作Excel

如何使用power automate将excel中的数据导入SharePoint list?

导出到excel失败,错误(控件加载失败)