从 Python(SAP 分析插件 VBA 宏)调用 Excel VSTO 加载项中的函数(运行-时间错误 1004:宏可能不可用)

Call Function in Excel VSTO Add-in from Python (SAP Analysis Plug-in VBA macros) (Run-time error 1004: The macro may not be available)

问题总结

我遇到 Python 代码的问题,该代码试图在 Excel 工作簿中执行 VBA 宏。每当它尝试使用 excel_instance.Application.Run() 时都会引发错误:

Run-time error '1004': Cant run the macro 'SAPLogon'. The macro may not be available in this workbook or all macros may be disabled.

所以,显然脚本没有识别函数 SAPLogonSAPExecuteCommand(属于 SAP VSTO 插件。我相信它正在发生,因为 SAP 插件没有加载(更多有关该部分的信息:为什么我认为问题与加载插件有关?)到我创建的 Excel 实例中。至少我是这么认为的。

有谁知道怎么解决吗?


详细问题

我对这个项目的意图是自动刷新 Excel 使用 SAP Analysis for Office 加载项的工作簿。此插件与 SAP 连接以从 Business Warehouses 中提取信息。据我所知,它是用 VSTO 编程制作的,它有一个宏 API 可以在 Excel 内部使用它,借助 VBA 代码(更多信息 here

我想将其与 Python 集成,以便我可以将此代码嵌入到其他项目中以自动从 SAP 获取数据片段。因此,在这个 blog 的帮助下(用 VBA 实现了一个解决方案)我开始用 Python.

寻找我自己的解决方案

下面你可以看到我想要做的流程:

在这里你可以看到我想用Python脚本覆盖的详细过程:
- 绿色: 代表我设法实施的流程
- 红色: 当前不工作的进程


Python 我目前使用的代码

import win32com.client as win32  # allow easy access to Window’s Component Object Model (COM) and control Microsoft applications
from pathlib import Path  # Module to handle file paths

# Path of excel file to import
sap_aof_excel_file = Path.cwd().joinpath('Test_Data.xlsm')

# Declaring variables
bwclient = "999"
bwuser = "USERNAME"
bwpassword = "PASSWORD"

# Launch Excel: Create an Exel object and store it into a variable named 'excel_instance'
excel_instance = win32.gencache.EnsureDispatch('excel_instance.Application')

# Make it visible otherwise it doesn’t work
excel_instance.Visible = True
excel_instance.DisplayAlerts = False

# Open the file in the new Excel instance,
#     The 1st false: don't update the links 
#     The 2nd false: and don't open it read-only
workbook_sap = excel_instance.Workbooks.Open(sap_aof_excel_file, False, False)

# Force the plugin to be enabled in the instance of Excel
for addin in excel_instance.Application.COMAddIns:
    if addin.progID == 'SapExcelAddIn':
        if addin.Connect == False:
            addin.Connect = True
        elif addin.Connect == True:
            addin.Connect = False
            addin.Connect = True

# logs in to Business Warehouse
lResult = excel_instance.Application.Run("SAPLogon", "DS_1", bwclient, bwuser, bwpassword)

# execute a command to refresh the data
lResult = excel_instance.Application.Run("SAPExecuteCommand", "RefreshData", "DS_1")

# Save the file and close it
workbook_sap.Save
workbook_sap.Close()

# force the application to close
excel_instance.DisplayAlerts = True
excel_instance.Application.Quit()

# Clear out the memory 
excel_instance = None
workbook_sap = None


为什么我认为问题与加载插件有关?

我真的很想找出解决这个问题的方法。我意识到,如果我自己打开 Excel 工作簿,SAPLogon 函数在被 VBA 宏调用时运行良好。只有当我从 Python 脚本中调用它时它才会起作用。所以我去了VBA工作室,看到Python启动的实例显然没有加载插件。

我自己打开的工作簿:在资源管理器中加载了插件

使用 Python 语句打开的工作簿:没有插件
Python中用于打开实例的语句是win32.gencache.EnsureDispatch('Excel.Application')

所以我决定做一个测试。如果我调用另一个插件,比如 Data Analysis 会怎样?
答案是:不会。它会引发与 SAP 插件相同的错误。

这让我很开心。至少我认为这是一个与 COM 接口相关的问题,与通过 Python 访问 SAP 插件的限制无关。经过一些研究,我发现您可以使用 RegisterXLL 方法加载某些类型的插件。所以我将下面的行添加到我的代码中:

# Register (or loads) XLL Excel Plugin called Data Analysis
excel_instance.RegisterXLL(r'C:\Program Files (x86)\Microsoft Office\root\Office16\Library\Analysis\ANALYS32.XLL')
# Call "Moveavg" Analysis ToolPack Function after execution of RegisterXLL
lResult = excel_instance.Application.Run("Moveavg", 'arnols', 'souza', False, True, False)

成功了!
代码执行数据分析插件的功能。

很明显,我尝试以相同的方式加载 SAP 插件。但它没有成功。此方法仅适用于 XLL,不适用于 VSTO 插件。另外,我找不到正确加载 VSTO 插件的解决方案。

excel_instance.RegisterXLL(r'C:\Program Files (x86)\SAP BusinessObjects\Office AddIn\SapExcelAddIn.vsto')

它引发了一个错误。 =(


我尝试过但没有成功的备选方案

AttributeError: .SAPLogon

# Need to load the add ins before opening the workbook
#addin_path = r'C:\Program Files (x86)\SAP BusinessObjects\Office AddIn\SapExcelAddIn.vsto'
addin_path = r'C:\Program Files (x86)\SAP BusinessObjects\Office AddIn\SapExcelAddIn.dll'
excel_instance.AddIns.Add(addin_path).Installed = True

com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', 'Add method of AddIns class failed', 'xlmain11.chm', 0, -2146827284), None)

test0 = "SAPLogon"
test1 = r'C:\Program Files (x86)\SAP BusinessObjects\Office AddIn\SapExcelAddIn.vsto!SAPLogon'
test2 = r'C:\Program Files (x86)\SAP BusinessObjects\Office AddIn\SapExcelAddIn.vsto|vstolocal!SAPLogon'

test3 = r"'C:\Program Files (x86)\SAP BusinessObjects\Office AddIn\SapExcelAddIn.vsto'!SAPLogon"
test4 = r"'C:\Program Files (x86)\SAP BusinessObjects\Office AddIn\SapExcelAddIn.vsto|vstolocal'!SAPLogon"

test5 = 'SapExcelAddIn.vsto!SAPLogon'
test6 = 'SapExcelAddIn.vsto|vstolocal!SAPLogon'

lResult = excel_instance.Application.Run(testn, "DS_1", bwclient, bwuser, bwpassword)

com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', "Cannot run the macro 'SAPLogon'. The macro may not be available in this workbook or all macros may be disabled.", 'xlmain11.chm', 0, -2146827284), None)


在您的 VSTO 插件中,如果您为 运行 一些没有任何 ui 的后台代码创建宏,那么我建议创建 XLL 而不是 VSTO 插件,以便您可以使用 RegisterXLL 函数注册它正如你在问题中提到的。

您可以使用 Excel-DNA 框架 创建 XLL。你不需要写太多代码, 只需复制粘贴 VSTO 代码并更改一些参考。

或者您可以尝试使用 excel_instance.AddIns.Add(addin_path) 添加 VSTO 插件,然后在 make installed=true 上添加。 但在执行此操作之前,请检查您的插件是否已在 user/machine 注册表中注册。