【问题标题】:How to run Excel VBA / Macro from Python如何从 Python 运行 Excel VBA / 宏
【发布时间】:2019-09-20 14:31:56
【问题描述】:

我正在尝试使用 Spyder 中的 python 3.7 在 xlsm 工作簿中运行 VBA 宏。此工作簿有两个工作表。

我当前运行的代码可以毫无问题地保存新文件,但它并没有像应有的那样触发 VBA。

我知道这个宏有效,因为如果我手动单击 Excel 中的按钮,它就可以正常工作。

有人可以帮忙吗?我检查了信任中心下的宏设置并启用了所有宏,所以我认为这不是权限问题,但我不是这台电脑的管理员。

代码如下:

import os
import win32com.client

xl = win32com.client.Dispatch("Excel.Application")
wb = xl.Workbooks.Open("Z:\FolderName\FolderName2\FileName.xlsm")
xl.Application.Run("MacroName")
wb.SaveAs("Z:\FolderName\FolderName2\FileName1.xlsm")
wb.Close()
xl.Quit()

【问题讨论】:

  • 你有什么错误吗?
  • 我没有收到任何错误。新文件 FileName1 没有问题地保存到文件夹中,但是我知道它没有执行此宏。

标签: python excel vba win32com


【解决方案1】:

这可以通过 xlwings 轻松完成。一旦我切换到那个库,我就能够快速地让这个脚本工作。

【讨论】:

    【解决方案2】:

    首先确保您的 All.xlsm 文件在您当前的工作中或在您的用户/文档中(有时它在 yourDocuments 目录中工作,有时不是,所以最好同时拥有)

    将您的宏名称与包含宏的文件名一起传递,您可以根据需要更改 ReadOnly 或 Savechanges 等参数

    并确保在每次运行后删除 xl 对象

    import win32com.client
    
    xl =win32com.client.dynamic.Dispatch('Excel.Application')
    xl.Workbooks.Open(Filename = XYZ.xls, ReadOnly= 1)
    xl.Application.Run('All.xlsm!yourmacroname')
    xl.Workbooks(1).Close(SaveChanges=1)
    xl.Application.Quit()
    del xl
    

    【讨论】:

      【解决方案3】:

      从 Python 运行 Excel 宏

      要从 python 运行 Excel 宏,您几乎不需要任何东西。在完成这项工作的脚本下方。从 Excel 中的宏更新数据的优点是您可以立即看到结果。您不必先保存或关闭工作簿。我使用这种方法来更新实时股票报价。它快速且稳定。 这只是一个示例,但您可以在 Excel 中使用宏执行任何操作。

      from os import system, path
      import win32com.client as win32
      from time import sleep
      
      def isWorkbookOpen(xlPath, xlFileName):
          SeachXl = xlPath + "~$" + xlFileName
          if path.exists(SeachXl):
              return True
          else:
              return False
      
      def xlRunMacro(macroLink):
          PathFile = macroLink[0]
          xlMacro = macroLink[1]
          isLinkReady = False
      
          # Create the link with the open existing workbook
          win32.pythoncom.CoInitialize()
          xl = win32.Dispatch("Excel.Application")
          try:
              wb = win32.GetObject(PathFile)
              isLinkReady = True
          except:
              NoteToAdd = 'Can not create the link with ' + PathFile
              print(NoteToAdd)
          if isLinkReady:
              # If the link with the workbook exist, then run the Excel macro
              try:
                  xl.Application.Run(xlMacro)
              except:
                  NoteToAdd = 'Running Excel Macro ' + xlMacro + ' failed !!!'
                  print(NoteToAdd)
          del xl
      
      def mainProgam(macroSettings):
          FullMacroLink = []
          PathFile = macroSettings[0] + macroSettings[1]
          FullMacroLink.append(PathFile)
          FullModuleSubrout = macroSettings[1] + '!' + macroSettings[2] + '.' + macroSettings[3]
          FullMacroLink.append(FullModuleSubrout)
          if isWorkbookOpen(macroSettings[0], macroSettings[1]) == False:
              # If the workbook is not open, Open workbook first.
              system(f'start excel.exe "{PathFile}"')
              # Give some time to start up Excel
              sleep(2)
          xlRunMacro(FullMacroLink)
      
      def main():
          macroSettings = []
          # The settings below will execute the macro example
          xlPath = r'C:\test\\'               # Change add your needs
          macroSettings.append(xlPath)
          workbookName = 'Example.xlsm'       # Change add your needs
          macroSettings.append(workbookName)
          xlModule = "Updates"                # Change add your needs
          macroSettings.append(xlModule)
          xlSubroutine = "UpdateCurrentTime"  # Change add your needs
          macroSettings.append(xlSubroutine)
          mainProgam(macroSettings)
      
      if __name__ == "__main__":
          main()
          exit()
      

      VBA Excel 宏

      Option Explicit
      
      Sub UpdateCurrentTime()
          Dim sht As Worksheet
          Set sht = ThisWorkbook.Sheets("Current-Time")
          With sht
              sht.Cells(2, 1).Value = Format(Now(), "hh:mm:ss")
          End With
      End Sub
      

      您也可以将其用作动态模块。在 Python 项目中将上面的模块另存为 RunExcelMacro.py。只需使用以下几行:

      from RunExcelMacro import mainProgam
      mainProgram(macroSettings)
      

      它会完成这项工作,成功......

      【讨论】:

        【解决方案4】:

        您还需要引用模块名称


        这里以我在 Module1 下的 vba 代码为例

        Option Explicit
        Public Sub Example()
            MsgBox "Hello 0m3r"
        End Sub
        

        这是我的蟒蛇


        from win32com.client import Dispatch
        
        
        def run_excel_macro():
            try:
                excel = Dispatch("Excel.Application")
                excel.Visible = True
                workbook = excel.Workbooks.Open(
                    r"D:\Documents\Book1.xlsm")
        
                workbook.Application.Run("Module1.Example")
                workbook.SaveAs(r"D:\Documents\Book5.xlsm")
                excel.Quit()
            except IOError:
                print("Error")
        
        
        if __name__ == "__main__":
            run_excel_macro()
        

        【讨论】:

        • 感谢您的回复——这对我也不起作用,但我通过 xlwings 得到了它。
        猜你喜欢
        • 1970-01-01
        • 2020-05-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-01
        • 1970-01-01
        • 2012-06-16
        • 1970-01-01
        相关资源
        最近更新 更多