【问题标题】:Running an Excel macro via Python?通过 Python 运行 Excel 宏?
【发布时间】:2013-11-06 03:04:13
【问题描述】:

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

【问题讨论】:

  • 可能模块和方法不要使用相同的名称。
  • 宏定义是什么?是像Public sub testMacro 还是Private 一样声明?
  • 您需要从 Python 运行宏吗?无论如何,都可以轻松地在 Python 中完成所有工作。也可以使用 del xl 而不是 xl=0 来正确删除对对象的引用。
  • @TimWilliams 详细说明?
  • @enderland 没有,只​​是Sub testMacro

标签: python excel vba python-2.7


【解决方案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

【讨论】:

  • 这是在后台使用 win32com 启动 Excel,所以它在 Linux 上不起作用。
  • 如果我的宏保存在其他地方 .xlsm 并且我必须运行的文件是另一个 xls 文件,我该怎么办
  • @NimishBansal,您找到解决方案了吗?我也有类似的问题。我能想到的一种方法是同时打开xlsxlsm 文件,就像手动打开excel 文档时所做的那样......但还没有尝试过
  • @cole 没有在 Linux 上运行 VBA/.xlsm 完全不是初学者?
  • 对。绝对不是初学者 :) 如果我没记错的话,有人问它是否可以在 linux 上运行......否则我不知道我为什么写这个。
【解决方案2】:

我对 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

【讨论】:

  • 在 python 3.6 上测试过,效果很好。次要输入,在我的情况下,“ThisWorkbook.Template2G”不起作用,而是直接给出宏名称。示例:excel_macro.Application.Run("Template2G")
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

    1. 文件 > 选项 > 信任中心
    2. 点击信任中心设置...按钮
    3. 宏设置 > 勾选启用所有宏

    【讨论】:

    • 是否选中了同一屏幕下方的启用 vba 模型复选框?另外,您在上一个问题中尝试从 python 生成宏,您是否从 Excel 中检查过您打开的 xlsm 文件是否真的包含宏?
    【解决方案5】:

    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
    

    【讨论】:

    • 如果我在 Module1 中有多个 Sub ,我应该每次都包含每个名称吗?
    【解决方案6】:

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

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

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

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

    【讨论】:

    • 这应该没有必要。 macroname 不一定与特定工作表相关联。但是您是否尝试在名为 sheet_name 的特定工作表上运行 macroname
    【解决方案7】:

    我尝试了 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
    

    【讨论】:

      【解决方案8】:

      对于 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
      

      【讨论】:

        猜你喜欢
        • 2019-07-24
        • 2012-06-16
        • 1970-01-01
        • 1970-01-01
        • 2016-01-27
        • 2012-12-24
        • 1970-01-01
        • 2017-11-01
        相关资源
        最近更新 更多