使用Python将宏注入Spreadsheets

Joh*_*ith 15 python excel vba excel-vba vbe

我有一个宏,我想要使用一堆现有的电子表格.唯一的问题是,有太多的电子表格,手动操作太费时间了!

我编写了一个Python脚本来使用pyWin32访问所需的文件,但我似乎无法找到一种方法来使用它来添加宏.

这里有一个类似的问题给出了这个答案(它不是Python,但看起来它仍然使用COM),但我的COM对象似乎没有一个名为VBProject的成员:

Set objExcel = CreateObject("Excel.Application") 
objExcel.Visible = True 
objExcel.DisplayAlerts = False 
Set  objWorkbook = objExcel.Workbooks.Open("C:\scripts\test.xls") 
   Set xlmodule = objworkbook.VBProject.VBComponents.Add(1)  
   strCode = _ 
   "sub test()" & vbCr & _ 
   "   msgbox ""Inside the macro"" " & vbCr & _ 
   "end sub" 
   xlmodule.CodeModule.AddFromString strCode 
objWorkbook.SaveAs "c:\scripts\test.xls" 
objExcel.Quit 
Run Code Online (Sandbox Code Playgroud)

编辑:链接到引用的类似问题:将Excel VBA代码注入并执行到从外部源接收的电子表格中

我也忘了提到虽然这不是Python,但我希望通过COM对象可以使用类似的对象成员.

dil*_*ert 9

这是转换的代码.您可以使用win32comcomtypes包.

import os
import sys

# Import System libraries
import glob
import random
import re

sys.coinit_flags = 0 # comtypes.COINIT_MULTITHREADED

# USE COMTYPES OR WIN32COM
#import comtypes
#from comtypes.client import CreateObject

# USE COMTYPES OR WIN32COM
import win32com
from win32com.client import Dispatch

scripts_dir = "C:\\scripts"
conv_scripts_dir = "C:\\converted_scripts"
strcode = \
'''
sub test()
   msgbox "Inside the macro"
end sub
'''

#com_instance = CreateObject("Excel.Application", dynamic = True) # USING COMTYPES
com_instance = Dispatch("Excel.Application") # USING WIN32COM
com_instance.Visible = True 
com_instance.DisplayAlerts = False 

for script_file in glob.glob(os.path.join(scripts_dir, "*.xls")):
    print "Processing: %s" % script_file
    (file_path, file_name) = os.path.split(script_file)
    objworkbook = com_instance.Workbooks.Open(script_file)
    xlmodule = objworkbook.VBProject.VBComponents.Add(1)
    xlmodule.CodeModule.AddFromString(strcode.strip())
    objworkbook.SaveAs(os.path.join(conv_scripts_dir, file_name))

com_instance.Quit()
Run Code Online (Sandbox Code Playgroud)


Dir*_*irk 5

由于我也花了一些时间来解决这个问题,因此我将提供另一个示例,该示例应该适用于Excel 2007/2010/2013的xlsm格式。上面提供的示例没有太大差异,只是稍微简单一点,而无需循环访问不同的文件并包含更多注释。此外,宏的源代码是从文本文件加载的,而不是在Python脚本中对其进行硬编码的。

请记住要根据需要调整脚本顶部的文件路径。

此外,请记住,Excel 2007/2010/2013仅允许以宏xlsm格式存储带有宏的工作簿,而不能以格式存储xlsx。将宏插入xlsx文件时,将提示您将其保存为其他格式,否则该宏将不包含在文件中。

最后但并非最不重要的一点是,检查是否已激活Excel的从应用程序外部执行VBA代码的选项(出于安全原因,默认情况下已将其禁用),否则,您将收到一条错误消息。为此,请打开Excel并转到

文件->选项->信任中心->信任中心设置->宏设置->激活选中标记Trust access to the VBA project object model

# necessary imports
import os, sys
import win32com.client


# get directory where the script is located
_file = os.path.abspath(sys.argv[0])
path = os.path.dirname(_file)

# set file paths and macro name accordingly - here we assume that the files are located in the same folder as the Python script
pathToExcelFile = path + '/myExcelFile.xlsm'
pathToMacro = path + '/myMacro.txt'
myMacroName = 'UsefulMacro'

# read the textfile holding the excel macro into a string
with open (pathToMacro, "r") as myfile:
    print('reading macro into string from: ' + str(myfile))
    macro=myfile.read()

# open up an instance of Excel with the win32com driver
excel = win32com.client.Dispatch("Excel.Application")

# do the operation in background without actually opening Excel
excel.Visible = False

# open the excel workbook from the specified file
workbook = excel.Workbooks.Open(Filename=pathToExcelFile)

# insert the macro-string into the excel file
excelModule = workbook.VBProject.VBComponents.Add(1)
excelModule.CodeModule.AddFromString(macro)

# run the macro
excel.Application.Run(myMacroName)

# save the workbook and close
excel.Workbooks(1).Close(SaveChanges=1)
excel.Application.Quit()

# garbage collection
del excel
Run Code Online (Sandbox Code Playgroud)