59

我正在尝试通过 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
4

8 回答 8

79

我希望错误与您正在调用的宏有关,请尝试以下代码:

代码

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
于 2013-11-02T16:01:33.350 回答
12

我对 SMALLY 的代码做了一些修改,以便它可以在 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
于 2017-08-11T23:05:52.173 回答
4

只是一个带有空格的 xlsm 的快速注释。

file = 'file with spaces.xlsm'
excel_macro.Application.Run('\'' + file + '\'' + "!Module1.Macro1")
于 2019-01-08T22:36:21.077 回答
3

我怀疑您没有授权您的 Excel 安装从自动 Excel 运行宏。它是安装时默认的安全保护。要改变这一点:

  1. 文件 > 选项 > 信任中心
  2. 单击信任中心设置...按钮
  3. 宏设置>选中启用所有宏
于 2013-10-28T15:12:22.487 回答
1

SMALLY 代码的一个变体,如果您已经打开它,它不会退出 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
于 2018-12-18T10:12:40.280 回答
0

嗯,我在那个部分遇到了一些问题(是的,仍然是 xD):

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

因为我不经常使用excel(与vb或宏相同,但我需要它来使用femap和python)所以我最终解决了它检查宏列表:开发人员->宏:我看到:这macroname.macroname应该sheet_name.macroname像“宏”列表。

(我花了 30 分钟到 1 小时试图解决它,所以它可能对像我这样的 excel 新手有帮助)xD

于 2015-01-22T20:49:34.860 回答
0

我尝试了 win32com 方式和 xlwings 方式,但我没有得到任何运气。我使用 PyCharm 并没有在 win32com 的自动完成中看到 .WorkBook 选项。当我尝试将工作簿作为变量传递时,出现 -2147352567 错误。

然后,我找到了一个使用 vba shell 来运行我的 Python 脚本的方法。完成所有工作后,在您正在使用的 XLS 文件上写一些东西。这样 Excel 就知道是时候运行 VBA 宏了。

但是 vba Application.wait 函数将占用 100% 的 cpu,这很奇怪。有人说用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
于 2018-06-08T06:51:00.730 回答
-2

对于 Python 3.7 或更高版本(2018-10-10),我必须结合 @Alejandro BR 和 SMALLY 的答案,因为 @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
于 2018-10-19T22:27:47.550 回答