xlwings: Unable to import functions (UDFs) via xlwings ribbon - python-3.x

I'm trying to import a user-defined function(UDF) via xlwings but am encountering an issue. Upon pressing the import functions button in the xlwings ribbon, I receive the following run time error:
`Run_time error '1004
`Method of 'VBProject' of object '_Workbook' failed.'
According to the VBA debugger, the below module contains the problem:
Sub ImportXlwingsUdfsModule(tf As String)
' Fallback: This is called from Python as direct pywin32 calls were
' sometimes failing, see comments in the Python code
On Error Resume Next
ActiveWorkbook.VBProject.VBComponents.Remove
ActiveWorkbook.VBProject.VBComponents("xlwings_udfs")
On Error GoTo 0
**ActiveWorkbook.VBProject.VBComponents.Import tf**
End Sub
The .py file containing the UDF is saved in the same folder as the calling .xlsm workbook.
How do I rectify this so I can utilize UDFs?

Thanks to the xlwings team for providing a link that helped me resolve the issue.
One needs to ensure that Trust Access to VBA object model is enabled.
See: https://docs.xlwings.org/en/stable/udfs.html#one-time-excel-preparations

If you have trusted access to the VBA object model and you are getting a TypeError, there is an additional answer that applies to both versions 0.22.2 and 0.22.3 and maybe earlier.
In file Lib>Site-Packages>xlwings>udfs.py on line 651 or 652 (depending on the version) insert ".Item" where shown in the following:
xl_workbook.VBProject.VBComponents.Remove(xl_workbook.VBProject.VBComponents.Item("xlwings_udfs"))
I do not know why this works but it does. The original line does work in VBA with only modifications that apply to VBA syntax and the workbook reference. (i.e. see the VBA code in the question for an example.

Related

Python - process ended with exit code 3221225477

I've searched on this forum for a possible workaround, and tried my best, but none is working. below is the issue. I've a function which process websocket data and dump into an excel
I tried to use a wrapper/loop around the function, but still its failing.
I am utilizing, xlwings to copy data to the excel as below
def websocket_data_process():
xw.Book(xcelfile).sheets[shets1].range('A40').options(index=False).value = futDf
----where futDf is pandas datafrme
The issue is whenever, I am editing the excel at 'A40' Range manually (while the funcion is running), I am getting error like process ended with exit 3221225477. (I googled and came to its a access denied issue). Is there any way that I can workaround this crash and again resume the function, once editing is down..
Not sure if this is what you want. You can ask for a pause. The solution below will only work with windows.
import os
os.system("pause")
or this will work with any system.
input('Press <ENTER> to continue')
Of course you need an statement such as
for i in range(50):
rng = f'A{i+1}'
if rng == 'A40':
input('Press <ENTER> to continue')
# Do your things here ...
thanks for the response, but I resolved it,
The issue happens because the xlwings trying to access the existing excel which is either locked or not available to access it.
solution: I've created an instance of Excel with xlwings context manager and provided full permissions to the account which is running the excel and it's been resolved.

Check for compilation error in Excel via COM

I am connected to an Excel application and can execute the "Debug"->"Compile VBAProject" from my Python code using win32com like so (inspired by code from here):
from win32com import client
def compile(self):
self.__excel = client.GetActiveObject("Excel.Application")
compile_button = self.__excel.VBE.CommandBars.FindControl(1, 578)
compile_button.Execute()
If there is a compilation error in the Excel VBA code I get a popup message in Excel telling me the error just fine.
Now I would like to check from the Python code if there was a compilation error and raise an exception if there was. I don't necessarily need the compilation error to be part of the exception but if that were possible I would of course gladly take that, too.
Can this be done somehow?
I've been experimenting with all kinds of window counts before and after the compilation etc. but so far have not found a property of any object that would indicate that there was a popup or a compilation error.
Ok, I found a somewhat ugly but doable way - that I would like to document for others having the same issue:
You need to import a code file into the opened Excel file that has (at least) one function defined. Then you can call this function from your Python code and catch any exception. If there was an exception your code - including the imported file - did not compile, if there is none the compilation was pass.
Here's my code:
compile_code.bas
Public Sub compileCode()
' doesn't need to do anything, it just needs to be available!
End Sub
Python file
from win32com import client
def compile(self) -> bool:
self.__excel = client.GetActiveObject("Excel.Application")
self.__book = self.__excel.ActiveWorkbook
self.__book.VBProject.VBComponents.Import(<Path_to_compile_code.bas>)
try:
self.__excel.Application.Run("compileCode")
# if you reach here the code compiled
return True
except Exception:
return False

Code executes sometimes and gives error for the other times

I am trying to automate a process in excel. I have called two macros from Python. The code executes successfully sometimes and sometimes gives an error. I have saved the macros and the python file in the same location.
import os,os.path
import win32com.client
Path = 'xyz'
if os.path.exists(r'D:\Code\ABC.xlsx'):
xl = win32com.client.Dispatch("Excel.Application")
xl.Workbooks.Open(os.path.abspath('D:\Code\ABC.xlsx'))
xl.Application.Run(Macro.xlsm!Module1.Macro1, Path)
xl.Application.Run(Macro.xlsm!Module2.Macro2)
xl.Application.ActiveWorkbook.Save()
del xl
The error that it gives at times is:
(-2147352567, 'Exception occured.',(0,''Microsoft Excel','Cannot run
macro 'D:\Code\Macro.xlsm!Module1.Macro1'. The macro may not be
available in this workbook or all macros may be disabled',
'xlmain11.chm, 0, -2146827284'), None)
I am getting a new error, which is constant:
//winp-oaf-118/FldrRedir_3$/Data/Macro.xlsm' cannot be found.Check your spelling, or try a different path.

Xlwings addin works but fails to update as I change underlying code

I have downloaded xlwings addin to launch some python scripts from a VBA macro. My python version is 3.7 , 64-bit and I work in a sublime environment.
I've defined:
HelloWorld24 VBA macro on a Example.xlsm workbook which runs a
working_test.py script that changes the workbook
Note that the workbook and the script are in the same folder. If I run HelloWorld24, working_test.py runs as expected and Example.xlsm is changed correspondingly. So far so good. However, if I change working_test.py, save it and run HelloWorld24 again, Example.xlsm does not change. I've cleared Example.xlsm, ran the macro again and get the same result as in the first run.
1.I don' think this is a problem with VBA as if I change the non-run python part of HelloWorld24, Example.xlsm is changed correspondingly (for example below if I change 912 to 1000 in the second line of the macro).
2.Also, if I create a new python script and a new macro, the addin works as expected as it takes into accoutn the changes in the underlying python file.
3.It seems to me that once run, the addin freezes the python script to its first version and I can't find a way to refresh it short of creating a new python file with a different name.
4.Even if I introduce errors in the working_test.py file, the VBA macro runs fine.
5.Conversely, if I create a macro on a file that has python errors, I will always receive the error message from VBA even if I correct the underlying errors in the python file.
#working_test.py
def world():
wb = xw.Book.caller()
wb.sheets[0].range('A1').value = 'Hello World!'
#VBA macro
Sub HelloWorld24()
RunPython ("import working_test; working_test.world()")
Range("B2").Value = Range("B2").Value + 912
End Sub

xlwings : Object Required

I'm a newbie into both python and xlwings. So the story is,
I need a custom function needs to be used in Excel. Since I have no clue about VB scripts, I decided to write a function in python and import it in excel using xlwings.
I installed xlwings using the pip command. I added the addin to excel
by the procedure given in xlwings support forum.
I created an excel file, say " Test.xlsm". I created a python file in
the same name "Test.py" (File is in same folder only)
I wrote my function in the python
import xlwings as xl
#xl.func
def exponent(x,y):
#the function is an example only. I tried this for practicing and it is also not working
z=x**y
return z
I opened excel, imported the functions using import function in
xlwings addin. I found no errors in importing the functions
I called the functions from the excel cell,
"=exponent(A1,B1)"
Instead of getting a result, I'm getting "Object Required"
I don't know what went wrong?
Any ideas what I'm missing? Forgive me for the basic question.
You need to add the Reference in VBA.
Open up the Developer console (Alt-F11)
Click on Tools -> References and select xlwings

Resources