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)

Question:

Problem summary

I am having problem with a Python code that is trying to execute a VBA Macro inside a Excel Workbook. Whenever it tries to use excel_instance.Application.Run() it raises an error:

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

VBA Error

So, apparently the Script is not recognizing the functions SAPLogon and SAPExecuteCommand (that belongs to SAP VSTO Plug-in. I believe it is happening because the SAP Plugin is not loading (more information about that in the section: Why do I think the problem is related to load Plugins?) into the Excel instance I have created. At least that’s what I think it is.

Does anyone know how to solve it?


Detailed Problem

My intention with this project is to automate the refresh of Excel Workbooks that uses SAP Analysis for Office AddIn. This Plug-In connects with SAP to extract information from Business Warehouses. As much as I could understand it is made with VSTO programing and it has a Macro API to use it inside Excel with the help of VBA Codes (more info here)

I want to integrate this with Python so that I can embed this code with another projects to automatically get pieces of data from SAP. So, with the help of this blog (that implements a solution with VBA) I started to look for my own solution with Python.

Bellow you can see the flow I want to do:
Macro-Process of the routine I want to script

Here you can see the detailed process I want to cover with the Python Script:
– Green: Represent processes that I managed to implement
– Red: Process that currently is not working

Detailed process


Python code that I am currently using

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


Why do I think the problem is related to load Plugins?

I was really trying to figure out one solution to this problem. I realized that if I open the Excel Workbook by myself the SAPLogon function works well when called by a VBA Macro. It only does not work if I call it from a Python Script. So I went to VBA Studio and saw that the instance initiated by Python apparently do not load plugins.

Workbook opened by mylself: with the Plugins loaded in the explorer

Workbook opened by mylself

Workbook opened with Python statement: without the plugins
The statement used in Python to open up the instance was win32.gencache.EnsureDispatch('Excel.Application')

Workbook opened by Python

So I decided to make a test. What if I call another plugin, like Data Analysis will it work?
The answer is: No. It raises the same error as SAP Plugin.

Also raise a error same like SAPLogon

That made me happy. At least I think it is a problem related to the COM interface and not related to restrictions in the access of SAP Plugin through Python. After few research I found that you can load certain types of Plugins with the method RegisterXLL. So I added the lines bellow to my code:

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

It worked!
The code executed the function from Data Analysis Plugin.

It worked

So obviously I tried to load the SAP Plugin the same way. But it wasn’t successful. This method only works for XLL, not VSTO Plugins. Also, I couldn’t found a solution to load properly VSTO Plugins.

excel_instance.RegisterXLL(r'C:Program Files (x86)SAP BusinessObjectsOffice AddInSapExcelAddIn.vsto')

It raises an error. =(


Alternatives that I have tried without success

  • Tentative 1: Call VSTO Functions from Other Solutions (Link)
    • Notes: I tryed to call the SAPLogon function using the statement bellow
      excel_instance.Application.COMAddIns['SapExcelAddIn'].Object.SAPLogon("DS_1", bwclient, bwuser, bwpassword)
    • What happened: Error

AttributeError: .SAPLogon

  • Tentative 2: Tried to initiate the Excel Instance dynamically
    • Notes: Changed the statement in the code
      excel_instance = win32.dynamic.Dispatch('Excel.Application')
    • What happened: Nothing different happened
  • Tentative 3: Tried to specify the location where the Plugin is
    • Notes: Tried two paths to the place where the plugin is
# Need to load the add ins before opening the workbook
#addin_path = r'C:Program Files (x86)SAP BusinessObjectsOffice AddInSapExcelAddIn.vsto'
addin_path = r'C:Program Files (x86)SAP BusinessObjectsOffice AddInSapExcelAddIn.dll'
excel_instance.AddIns.Add(addin_path).Installed = True
  • What happened: Error

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

  • Tentative 4: Tried exautivelly to call the Function with absulute paths
    • Notes: Lots of tetatives
test0 = "SAPLogon"
test1 = r'C:Program Files (x86)SAP BusinessObjectsOffice AddInSapExcelAddIn.vsto!SAPLogon'
test2 = r'C:Program Files (x86)SAP BusinessObjectsOffice AddInSapExcelAddIn.vsto|vstolocal!SAPLogon'

test3 = r"'C:Program Files (x86)SAP BusinessObjectsOffice AddInSapExcelAddIn.vsto'!SAPLogon"
test4 = r"'C:Program Files (x86)SAP BusinessObjectsOffice AddInSapExcelAddIn.vsto|vstolocal'!SAPLogon"

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

lResult = excel_instance.Application.Run(testn, "DS_1", bwclient, bwuser, bwpassword)
  • What happened: Error

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)


Asked By: Arnold Souza

||

Answers:

In your VSTO addin, if you create a macro for running some background code without any ui then I suggest to create XLL instead of VSTO addin so that you can register it with RegisterXLL function as you mention in your question.

You can create XLL with Excel-DNA framework. You dont need to write too much code,
just copy paste VSTO code and changes some reference.

Or you can try to add VSTO addin using excel_instance.AddIns.Add(addin_path) and later on make installed=true.
But before doing this, check your addin is register in your user/machine registry.

Answered By: YUVRAJ
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.