What is the best way to run an Excel macro with Python3? - python

I am trying to write to a macro enabled excel file (xlsm) and then run a macro that is dependent on the cell my script is writing to. For clarity I am on a windows machine, I am not the admin and I am working with python3.8.0
I have a file called write.py, in this file it writes yesterdays date to the A1 cell unless it is Monday then it writes Fridays date. After it writes the date I would like to run a macro that uses that cell/date to do something.
So far I can write yesterdays date and I can run a macro but I cannot do them in the same file. I tried separating the files and executing the macro from the write.py file but that gave me the same error.
Here is my code for the write.py file that writes yesterdays date to the A1 cell of an xlsm file:
from datetime import date
from datetime import timedelta
import openpyxl
path = "C:/Users/project/file.xlsm"
# loads the workbook into a var
book = openpyxl.load_workbook(path)
sheet = book["Sheet2"] # loads a specific sheet by name into a var
a1 = sheet['A1'] # loads a cell into a var
# testing
print(book.sheetnames)
print(a1.value)
# Get yesterdays date unless its a Monday then get Fridays date
today = date.today()
if date.today().weekday() == 0:
yesterday = today - timedelta(days=today.weekday()) + timedelta(days=4, weeks=-1)
else:
yesterday = today - timedelta(days = 1)
yestFormat = (yesterday.strftime("%x")) # formatting the date
# setting the value of the A1 cell to the yesterFormat var
sheet.cell(row=1,column=1,value=yestFormat)
book.save(path)
# This file is supposed to run the macro
exec(open('runMacro.py').read())
Here is the code for the second file that is supposed to run the macro, I have also had this code in the write.py file and I run into the same problems
import xlwings as xw
# loads the workbook into workbook var then loads a specific sheet into worksheet var
wb = xw.Book(r'C:/Users/project/file.xlsm')
wb.macro('test_macro')()
wb.save(r'C:/Users/project/file.xlsm')
When I run the write.py file with the exec command commented out it works and writes the date to the cell. So there is something wrong with the way I am executing the macro. Something I have noticed is if the excel file is open then the write.py file will not work, and the runMacro.py file opens the excel doc when I run it. I think it has something to do with how it is saving or opening but I have read through xlwings documentation and I am doing what it says on how to save, so I am not sure. Hoping there is a better way, thanks for any feedback.
Edit:
Sorry I forgot to add the error I am getting. I have changed the file paths for privacy reasons so there might be some inconsistencies there.
Traceback (most recent call last):
File "C:\Users\project\venv\lib\site-packages\xlwings\_xlwindows.py", line 466, in __call__
return Book(xl=self.xl(name_or_index))
File "C:\Users\project\lib\site-packages\xlwings\_xlwindows.py", line 156, in __call__
v = self._inner(*args, **kwargs)
File "C:\Users\username\AppData\Local\Temp\gen_py\3.8\00020813-0000-0000-C000-000000000046x0x1x8.py", line
39136, in __call__
ret = self._oleobj_.InvokeTypes(0, LCID, 2, (13, 0), ((12, 1),),Index
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2147352565), None)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\project\code\venv\lib\site-packages\xlwings\main.py", line 3873, in open
impl = self.impl(name)
File "C:\Users\project\venv\lib\site-packages\xlwings\_xlwindows.py", line 468, in __call__
raise KeyError(name_or_index)
KeyError: 'sample.xlsm'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:/Users/project/test.py", line 35, in <module>
exec(open('test2.py').read())
File "<string>", line 4, in <module>
File "C:\Users\username\venv\lib\site-packages\xlwings\main.py", line 547, in __init__
impl = app.books.open(fullname, update_links, read_only, format, password, write_res_password,
File "C:\Users\username\venv\lib\site-packages\xlwings\main.py", line 3879, in open
impl = self.impl.open(fullname, update_links, read_only, format, password, write_res_password,
File "C:\Users\username\venv\lib\site-packages\xlwings\_xlwindows.py", line 484, in open
return Book(xl=self.xl.Open(fullname, update_links, read_only, format, password, write_res_password,
File "C:\Users\username\venv\lib\site-packages\xlwings\_xlwindows.py", line 66, in __call__
v = self.__method(*args, **kwargs)
File "C:\Users\username\AppData\Local\Temp\gen_py\3.8\00020813-0000-0000-C000-000000000046x0x1x8.py", line
39013, in Open
ret = self._oleobj_.InvokeTypes(1923, LCID, 1, (13, 0), ((8, 1), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17)),Filename
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', "Excel cannot open the file 'sample.xlsm' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.", 'xlmain11.chm', 0, -2146827284), None)

Related

acquire function in MachinePool not working

I have an issue by acquiring a VirtualBox Virtual Machine, here's the error code I am getting with the code bellow :
Traceback (most recent call last):
File "C:\Users\ROULLE Diego\AppData\Local\Programs\Python\Python310\lib\site-packages\virtualbox\library_base.py", line 209, in _call_method
ret = method(*in_params)
File "C:\Users\ROULLE~1\AppData\Local\Temp\gen_py\3.10\D7569351-1750-46F0-936E-BD127D5BC264x0x1x3.py", line 12824, in CreateMachine
ret = self._oleobj_.InvokeTypes(1610743849, LCID, 1, (9, 0), ((8, 1), (8, 1), (8200, 1), (8, 1), (8, 1), (8, 1), (8, 1), (8, 1)),aSettingsFile
pywintypes.com_error: (-2147352561, 'Paramètre non facultatif.', None, None)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\Users\ROULLE Diego\Desktop\run_vms.py", line 22, in <module>
pool_web1.acquire("jouca", "troll"),
File "C:\Users\ROULLE Diego\AppData\Local\Programs\Python\Python310\lib\site-packages\virtualbox\pool.py", line 158, in acquire
clone = machine.clone(name="%s Pool" % self.machine_name)
File "C:\Users\ROULLE Diego\AppData\Local\Programs\Python\Python310\lib\site-packages\virtualbox\library_ext\machine.py", line 139, in clone
vm_clone = vbox.create_machine(settings_file, name, groups, "", create_flags)
File "C:\Users\ROULLE Diego\AppData\Local\Programs\Python\Python310\lib\site-packages\virtualbox\library.py", line 10462, in create_machine
machine = self._call(
File "C:\Users\ROULLE Diego\AppData\Local\Programs\Python\Python310\lib\site-packages\virtualbox\library_base.py", line 200, in _call
return self._call_method(method, in_p=in_p)
File "C:\Users\ROULLE Diego\AppData\Local\Programs\Python\Python310\lib\site-packages\virtualbox\library_base.py", line 222, in _call_method
errobj.msg = exc.args[2][2]
TypeError: 'NoneType' object is not subscriptable
The code :
from virtualbox import VirtualBox, pool
vbox = VirtualBox()
pool_web1 = pool.MachinePool("Web1")
pool_web2 = pool.MachinePool("Web2")
pool_sql1 = pool.MachinePool("SQL1")
sessions = []
while True:
print("1 : create run")
print("2 : release last run")
print("3 : clear all runs")
print("4 : show all ips")
print()
command = input("Command : ")
match command:
case "1":
sessions.append([
pool_web1.acquire("jouca", "troll"),
pool_web2.acquire("jouca", "troll"),
pool_sql1.acquire("jouca", "troll")
])
break
I tried to acquire the VM machine by the MachinePool and it resulted to an error.

Error with xlwings Book.save(): SaveAs Method of Workbook class failed

I am opening an Excel-file wb with xlwings, doing some operations, and then trying to save it to a directory. The problem is that a normal xw.Book.save() throws me an occasional error.
For me to continue with this code, it is crucial that I can trust it not throwing the error.
The following code gives me the following error:
The code:
Some_data = r"C:\Users\FrodeWilkensen\OneDrive - Norfund\Frode Wilkensen\Some_data.xlsx" #filepath to some data
Original = r"C:\Users\FrodeWilkensen\OneDrive - Norfund\Frode Wilkensen\Original.xlsx" #filepath to another file
df = pd.read_excel(Some_data, engine = "openpyxl") #reading some_data, assigning as df
wb = xw.Book(Original) #assigning original workbook as xlwings wb
ws = wb.sheets["dump"] #the sheet called "dump" assigned as ws
ws["B2"].options(pd.DataFrame, index=False, header=False, expand="table").value = df #some operations
wb.save(r"C:\Users\FrodeWilkensen\OneDrive - Norfund\Frode Wilkensen\dumped.xlsx") #want to save it in same directoy
#gets thrown an error, shown below.
The error:
---------------------------------------------------------------------------
com_error Traceback (most recent call last)
Input In [49], in <cell line: 11>()
7 ws = wb.sheets["dump"] #the sheet called "dump" assigned as ws
8 ws["B2"].options(pd.DataFrame, index=False, header=False, expand="table").value = df #some operations
---> 11 wb.save(r"C:\Users\FrodeWilkensen\OneDrive - Norfund\Frode Wilkensen\dumped.xlsx") #want to save it in same directoy
12 #gets thrown an error, shown below.
13 wb.app.kill()
File ~\anaconda3\lib\site-packages\xlwings\main.py:874, in Book.save(self, path)
872 path = utils.fspath(path)
873 with self.app.properties(display_alerts=False):
--> 874 self.impl.save(path)
File ~\anaconda3\lib\site-packages\xlwings\_xlwindows.py:582, in Book.save(self, path)
580 alerts_state = self.xl.Application.DisplayAlerts
581 self.xl.Application.DisplayAlerts = False
--> 582 self.xl.SaveAs(os.path.realpath(path), FileFormat=file_format)
583 self.xl.Application.DisplayAlerts = alerts_state
File ~\anaconda3\lib\site-packages\xlwings\_xlwindows.py:70, in COMRetryMethodWrapper.__call__(self, *args, **kwargs)
68 while True:
69 try:
---> 70 v = self.__method(*args, **kwargs)
71 if isinstance(v, (CDispatch, CoClassBaseClass, DispatchBaseClass)):
72 return COMRetryObjectWrapper(v)
File C:\Users\FRODEW~1\AppData\Local\Temp\gen_py\3.9\00020813-0000-0000-C000-000000000046x0x1x9.py:46807, in _Workbook.SaveAs(self, Filename, FileFormat, Password, WriteResPassword, ReadOnlyRecommended, CreateBackup, AccessMode, ConflictResolution, AddToMru, TextCodepage, TextVisualLayout, Local, WorkIdentity)
46804 def SaveAs(self, Filename=defaultNamedNotOptArg, FileFormat=defaultNamedNotOptArg, Password=defaultNamedNotOptArg, WriteResPassword=defaultNamedNotOptArg
46805 , ReadOnlyRecommended=defaultNamedNotOptArg, CreateBackup=defaultNamedNotOptArg, AccessMode=1, ConflictResolution=defaultNamedOptArg, AddToMru=defaultNamedOptArg
46806 , TextCodepage=defaultNamedOptArg, TextVisualLayout=defaultNamedOptArg, Local=defaultNamedOptArg, WorkIdentity=defaultNamedOptArg):
> 46807 return self._oleobj_.InvokeTypes(3174, LCID, 1, (24, 0), ((12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (3, 49), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17)),Filename
46808 , FileFormat, Password, WriteResPassword, ReadOnlyRecommended, CreateBackup
46809 , AccessMode, ConflictResolution, AddToMru, TextCodepage, TextVisualLayout
46810 , Local, WorkIdentity)
com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', 'SaveAs method of Workbook class failed', 'xlmain11.chm', 0, -2146827284), None)
As you see at the end of the error, it says SaveAs method of Workbook class failed - which is a VBA method error?
Do anyone have any suggestions?`
In advance, thank you :)

How do I save a new workbook in Python using xlwing while it gives traceback error

I have a simple code to create a new book and then after I want to fill it with data, but .save
doesn't work
import xlwings as xw
app = xw.App(visible=False)
wb = xw.Book()
wb.save(r'D:\XX\report.xlsx')
wb.close()
app.quit()
and this is the error:
Traceback (most recent call last):
File "MyPython.py", line 5, in <module>
wb.save(r'D:\XX\report.xlsx')
File "C:\Python38\lib\site-packages\xlwings\main.py", line 1065, in save
self.impl.save(path, password=password)
File "C:\Python38\lib\site-packages\xlwings\_xlwindows.py", line 829, in save
self.xl.SaveAs(
File "C:\Python38\lib\site-packages\xlwings\_xlwindows.py", line 95, in __call__
v = self.__method(*args, **kwargs)
File "C:\Users\XX\AppData\Local\Temp\gen_py\3.8\00020813-0000-0000-C000-000000000046x0x1x9.py", line 46571, in SaveAs
return self._oleobj_.InvokeTypes(3174, LCID, 1, (24, 0), ((12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (3, 49), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17)),Filename
pywintypes.com_error: (-2147352573, 'Member not found.', None, None)
Here is my python version: Python 3.8.0
XLwings vesrion: xlwings-0.27.7
The issue is coming from the path that you give as argument to the function save(). You can see that your code works if you save in the folder where your script is running:
import xlwings as xw
app = xw.App(visible=False)
wb = xw.Book()
wb.save('report.xlsx')
wb.close()
app.quit()
If you want to save to specific folder, you can do like this:
import xlwings as xw
app = xw.App(visible=False)
wb = xw.Book()
wb.save('C:/Users/rcapron/report.xlsx')
wb.close()
app.quit()
Please note that I use / instead of \.

Target specific Excel workbook by name with Python with win32com

If I have multiple Excel workbooks open on Windows 10, and I'm using win32com in Python, is there a way to choose a workbook by name? So far, I have been using:
ExcelApp = win32com.client.GetActiveObject('Excel.Application')
wb = ExcelApp.Workbooks(2)
but that requires the correct workbook to be the second one. Is there some way I can do it by name or filepath instead? I tried:
ExcelApp = win32com.client.GetActiveObject('Excel.Application')
wb = ExcelApp.Workbooks.Open(os.path.join(os.path.dirname(__file__), 'myworkbook.xlsm'))
but this does not work either if I have multiple Excel workbooks open. It ends up choosing the wrong workbook since later on, when it is looking for a specific sheet by name, it cannot find it.
If I try:
ExcelApp = win32com.client.GetActiveObject('Excel.Application')
wb = ExcelApp.Workbooks('My Workbook Name')
I get this:
Traceback (most recent call last):
File "E:\Archives\mypyscript.py", line 79, in <module>
wb = ExcelApp.Workbooks('My Workbook Name')
File "C:\Users\username\AppData\Local\Temp\gen_py\3.8\00020813-0000-0000-C000-000000000046x0x1x9\Workbooks.py", line 198, in __call__
ret = self._oleobj_.InvokeTypes(0, LCID, 2, (13, 0), ((12, 1),),Index
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2147352565), None)```

MDB/ACCDB execute macro/function (with parameters) by python script

I want to execute a macro/function code with python script. I have this code example:
from win32com.client import Dispatch
objAccess = Dispatch("Access.Application")
objAccess.Visible = False
objAccess.OpenCurrentDatabase(strDbName)
objDB = objAccess.CurrentDb()
objAccess.DoCmd.RunMacro('MyMacro')
objAccess.Application.CloseCurrentDatabase()
objAccess.Application.Quit()
del objAccess
del objDB
But I get this error:
Traceback (most recent call last):
File "D:\workspace-python\TOOLS\SHPTOOL\test.py", line 8, in <module>
objAccess.DoCmd.RunMacro('MyMacro')
File "<COMObject <unknown>>", line 3, in RunMacro
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, u"Microsoft Office Access can't find the object 'MyMacro.'", u'ACMAIN11.CHM', 10183, -2146825803), None)
Then I try another approach, call RUN method:
objAccess = Dispatch("Access.Application")
objAccess.Visible = False
objAccess.OpenCurrentDatabase(strDbName)
objDB = objAccess.CurrentDb()
objAccess.Run('merge', "mystringparameter")
objAccess.Application.Quit()
error:
Traceback (most recent call last):
File "D:\workspace-python\TOOLS\SHPTOOL\test.py", line 58, in <module> objAccess.Run('merge', "mystringparameter")
File "<COMObject Access.Application>", line 14, in Run
File "C:\Python27\lib\site-packages\win32com\client\dynamic.py", line 287, in _ApplyTypes_
result = self._oleobj_.InvokeTypes(*(dispid, LCID, wFlags, retType, argTypes) + args)
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, u"Microsoft Office Access can't find the procedure 'merge.'", None, -1, -2146825771), None)
And my MDB code, the 3 functions:
Sub merge(path As String)
MsgBox "Inside generated macro!!! " & path
End Sub
Sub MyMacro()
MsgBox "Inside generated macro!!!"
End Sub
Function MyFunction()
MsgBox "You MUST select a Destination Folder!"
End Function
Thanks
Just replace
objAccess.DoCmd.RunMacro('MyMacro')
by
objAccess.run('MyMacro')
\o/

Categories