Подтвердить что ты не робот

Запуск макроса Excel через Python?

Я пытаюсь запустить макрос через python, но я не уверен, как заставить его работать...

У меня есть следующий код, но он не работает.

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

Я получаю следующую трассировку:

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
4b9b3361

Ответ 1

Я ожидаю, что ошибка связана с вызываемым вами макросом, попробуйте следующий фрагмент кода:

Код

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

Ответ 2

Я сделал некоторые изменения в коде SMNALLY, чтобы он мог работать в Python 3.5.2. Это мой результат:

#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

Ответ 3

Я подозреваю, что вы не разрешили установку Excel для запуска макроса из автоматизированного Excel. Это защита по умолчанию при установке. Чтобы изменить это:

  • Файл > Параметры > Центр доверия
  • Нажмите кнопку "Настройки центра управления"...
  • Параметры макросa > Проверить Включить все макросы

Ответ 4

Хм, у меня были проблемы с этой частью (да все еще xD):

xl.Application.Run("excelsheet.xlsm!macroname.macroname")

cos im не использует excel часто (то же самое с vb или макросами, но мне нужно, чтобы он использовал femap с python), поэтому я окончательно решил проверить список макросов:  Разработчик → Макросы: там я увидел это: этот macroname.macroname должен быть sheet_name.macroname как в списке "Макросы".

(я трачу что-то вроде 30min-1h, пытаясь его решить, поэтому может быть полезно для noobs, таких как я, в excel) xD

Ответ 5

Я попробовал путь win32com и xlwings, но мне не повезло. Я использую PyCharm и не увидел опцию.WorkBook в автозаполнении для win32com. Я получил ошибку -2147352567, когда попытался передать книгу как переменную.

Затем я нашел способ использования оболочки vba для запуска скрипта Python. Напишите что-нибудь в файле XLS, с которым вы работаете, когда все будет сделано. Чтобы Excel знал, что пора запускать макрос VBA.

Но функция vba Application.wait займет 100% процессорного времени, что странно. Некоторые люди говорили, что с помощью функции сна Windows это можно исправить.

 Import xlsxwriter


 Shell "C:\xxxxx\python.exe 
 C:/Users/xxxxx/pythonscript.py"

 exitLoop = 0

подождите, пока Python завершит свою работу.

  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

Ответ 6

Для Python 3.7 или более поздней версии (2018-10-10) я должен объединить оба ответа @Alejandro BR и SMNALLY, потому что @Alejandro забыл определить 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

Ответ 7

Вариант SMNALLY-кода, который не выходит из Excel, если он у вас уже открыт:

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

Ответ 8

Просто быстрое примечание с xlsm с пробелами.

file = 'file with spaces.xlsm'
excel_macro.Application.Run('\'' + file + '\'' + "!Module1.Macro1")