J'essaie de lancer une macro via Python mais je ne sais pas comment le faire fonctionner ...
J'ai le code suivant jusqu'à présent, mais ça ne marche pas.
import win32com.client
xl=win32com.client.Dispatch("Excel.Application")
xl.Workbooks.Open(Filename="C:\test.xlsm",ReadOnly=1)
xl.Application.Run("macrohere")
xl.Workbooks(1).Close(SaveChanges=0)
xl.Application.Quit()
xl=0
Je reçois le suivi suivant:
Traceback (most recent call last):
File "C:\test.py", line 4, in <module>
xl.Application.Run("macrohere")
File "<COMObject <unknown>>", line 14, in Run
File "C:\Python27\lib\site-packages\win32com\client\dynamic.py", line 282, in _ApplyTypes_
result = self._oleobj_.InvokeTypes(*(dispid, LCID, wFlags, retType, argTypes) + args)
com_error: (-2147352567, 'Exception occurred.', (0, u'Microsoft Excel', u"Cannot run the macro 'macrohere'. The macro may not be available in this workbook or all macros may be disabled.", u'xlmain11.chm', 0, -2146827284), None)
import win32com.client
xl=win32com.client.Dispatch("Excel.Application")
xl.Workbooks.Open(Filename="C:\test.xlsm",ReadOnly=1)
try:
xl.Application.Run("test.xlsm!testmacro.testmacro")
# It does run like this... but we get the following error:
# Traceback (most recent call last):
# File "C:\test.py", line 7, in <module>
# xl.Workbooks(1).Close(SaveChanges=0)
# File "C:\Python27\lib\site-packages\win32com\client\dynamic.py", line 192, in __call__
# return self._get_good_object_(self._oleobj_.Invoke(*allArgs),self._olerepr_.defaultDispatchName,None)
# com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2147352565), None)
except:
# Except isn't catching the above error... :(
xl.Workbooks(1).Close(SaveChanges=0)
xl.Application.Quit()
xl=0
Je m'attendrais à ce que l'erreur concerne la macro que vous appelez, essayez le code suivant:
import os, os.path
import win32com.client
if os.path.exists("excelsheet.xlsm"):
xl=win32com.client.Dispatch("Excel.Application")
xl.Workbooks.Open(os.path.abspath("excelsheet.xlsm"), ReadOnly=1)
xl.Application.Run("excelsheet.xlsm!modulename.macroname")
## xl.Application.Save() # if you want to save then uncomment this line and change delete the ", ReadOnly=1" part from the open function.
xl.Application.Quit() # Comment this out if your Excel script closes
del xl
J'ai apporté quelques modifications au code de SMNALLY afin qu'il puisse fonctionner sous Python 3.5.2. Ceci est mon résultat:
#Import the following library to make use of the DispatchEx to run the macro
import win32com.client as wincl
def runMacro():
if os.path.exists("C:\\Users\\Dev\\Desktop\\Development\\completed_apps\\My_Macr_Generates_Data.xlsm"):
# DispatchEx is required in the newest versions of Python.
Excel_macro = wincl.DispatchEx("Excel.application")
Excel_path = os.path.expanduser("C:\\Users\\Dev\\Desktop\\Development\\completed_apps\\My_Macr_Generates_Data.xlsm")
workbook = Excel_macro.Workbooks.Open(Filename = Excel_path, ReadOnly =1)
Excel_macro.Application.Run\
("ThisWorkbook.Template2G")
#Save the results in case you have generated data
workbook.Save()
Excel_macro.Application.Quit()
del Excel_macro
Je suppose que vous n’avez pas autorisé votre installation Excel à exécuter une macro à partir d’un Excel automatisé. C'est une protection de sécurité par défaut lors de l'installation. Pour changer cela:
Pour Python version 3.7 ou ultérieure (2018-10-10), je dois combiner les réponses de @Alejandro BR et SMNALLY, coz @Alejandro oublient de définir wincl.
import os, os.path
import win32com.client
if os.path.exists('C:/Users/jz/Desktop/test.xlsm'):
Excel_macro = win32com.client.DispatchEx("Excel.Application") # DispatchEx is required in the newest versions of Python.
Excel_path = os.path.expanduser('C:/Users/jz/Desktop/test.xlsm')
workbook = Excel_macro.Workbooks.Open(Filename = Excel_path, ReadOnly =1)
Excel_macro.Application.Run("test.xlsm!Module1.Macro1") # update Module1 with your module, Macro1 with your macro
workbook.Save()
Excel_macro.Application.Quit()
del Excel_macro
Une variante du code de SMNALLY qui ne ferme pas Excel si vous l'avez déjà ouvert:
import os, os.path
import win32com.client
if os.path.exists("excelsheet.xlsm"):
xl=win32com.client.Dispatch("Excel.Application")
wb = xl.Workbooks.Open(os.path.abspath("excelsheet.xlsm"), ReadOnly=1) #create a workbook object
xl.Application.Run("excelsheet.xlsm!modulename.macroname")
wb.Close(False) #close the work sheet object rather than quitting Excel
del wb
del xl
J'ai essayé les méthodes win32com et xlwings mais je n'ai pas eu de chance. J'utilise PyCharm et je n'ai pas vu l'option .WorkBook dans l'auto-complétion pour win32com . J'ai eu l'erreur -2147352567 lorsque j'ai essayé de passer un classeur en tant que variable.
Ensuite, j'ai trouvé un moyen de contourner vba Shell pour exécuter mon script Python . Ecrivez quelque chose sur le fichier XLS que vous utilisez lorsque tout est terminé. Ainsi, Excel sait qu'il est temps d'exécuter la macro VBA.
Mais la fonction vba Application.wait prendra 100% du processeur, ce qui est bizarre. Certaines personnes ont dit que l’utilisation de la fonction Windows Sleep permettrait de le réparer.
Import xlsxwriter
Shell "C:\xxxxx\python.exe
C:/Users/xxxxx/pythonscript.py"
exitLoop = 0
attendre que Python termine son travail.
Do
waitTime = TimeSerial(Hour(Now), Minute(Now), Second(Now) + 30)
Application.Wait waitTime
Set wb2 = Workbooks.Open("D:\xxxxx.xlsx", ReadOnly:=True)
exitLoop = wb2.Worksheets("blablabla").Cells(50, 1)
wb2.Close exitLoop
Loop While exitLoop <> 1
Call VbaScript
Juste une note rapide avec un xlsm avec des espaces.
file = 'file with spaces.xlsm'
Excel_macro.Application.Run('\'' + file + '\'' + "!Module1.Macro1")