在 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 单元格(选择、F2
、Return
)时,该一张纸上的所有 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