我有带有宏功能的.xlsm文件。 我正在使用openpyxl加载它,并将一些数据写入文件,最后想另存为另一个.xlsm文件。
要将文件另存为XLSM文件,我在Python脚本中使用了以下代码。
wb.save('testsave.xlsm');
但是,如果我按上述方法保存,则无法打开该文件。 但是,如果我将其另存为.xlsx,则可以在没有原始文件具有的Macro函数的情况下打开文件。
我想打开一个具有宏功能的Excel工作表,编辑该文件,然后使用openpyxl将其另存为新的.xlsm文件。 我怎样才能做到这一点?
对我来说,这与版本openpyxl==2.3.0-b2一起有效
wb = load_workbook(filename='original.xlsm', read_only=False, keep_vba=True)
..
wb.save('outfile.xlsm')
在此处的文档中也有提及:http://openpyxl.readthedocs.org/en/latest/usage.html?highlight=keep_vba#write-a-workbook-from-xltm-as-xlsm
此后是否可以从python调用并运行宏?
如果您已安装MS Office并运行Windows,则可以使用OLE api运行它。否则,您必须在Python中使用openpyxl重新设计宏代码。
该链接不会指向与xlsm相关的任何内容!实际上,如果您转至openpyxl.readthedocs.io/en/latest/usage.html?highlight=xlsm您会看到,由于xlsm没有任何内容,因此不会显示任何内容。
我认为他们现在删除了关于xlsm的那一部分,但仍然提到支持文件类型。重要的似乎是显式设置keep_vba标志,因为它默认为false。 openpyxl.readthedocs.io/en/latest/usage.html?highlight=keep_vba
此方法并不总是将ActiveX组件(如按钮)连接到代码。可能与被转换为图像的按钮的openpyxl错误相同。
我不知道这是否与提出该问题的人有关,但我正在处理相同的问题并找到了可能的解决方案。
打开原始文件(例如:1.xlsm)并使用openpyxl进行魔术处理;
另存为2.xlsx;
这两个文件实际上都是压缩文件:将它们解压缩到一个临时目录中;
将文件从原始文件的目录复制到xlsx文件的目录:其中一个文件是宏(vbaProject.bin),并且其中两个文件是必需的,因为它们描述了文件的类型;
将属于xlsx目录的所有文件放回zip文件,并将其从zip重命名为xlsm。该文件包含原始宏,并已使用openpyxl进行了编辑;
(可选)删除两个临时目录和2.xlsx文件。
示例代码:
import openpyxl
import zipfile
from shutil import copyfile
from shutil import rmtree
import os
PAD = os.getcwd()
wb = openpyxl.load_workbook('1.xlsm')
#####
# do magic with openpyxl here and save
ws = wb.worksheets[0]
ws.cell(row=2, column=3).value = 'Edited' # example
#####
wb.save('2.xlsx')
with zipfile.ZipFile('1.xlsm', 'r') as z:
z.extractall('./xlsm/')
with zipfile.ZipFile('2.xlsx', 'r') as z:
z.extractall('./xlsx/')
copyfile('./xlsm/[Content_Types].xml','./xlsx/[Content_Types].xml')
copyfile('./xlsm/xl/_rels/workbook.xml.rels','./xlsx/xl/_rels/workbook.xml.rels')
copyfile('./xlsm/xl/vbaProject.bin','./xlsx/xl/vbaProject.bin')
z = zipfile.ZipFile('2.zip', 'w')
os.chdir('./xlsx')
for root, dirs, files in os.walk('./'):
for file in files:
z.write(os.path.join(root, file))
z.close()
#clean
os.chdir(PAD)
rmtree('./xlsm/')
rmtree('./xlsx/')
os.remove('./2.xlsx')
os.rename('2.zip', '2.xlsm')
该解决方案是我找到的最接近的解决方案,但是,我仍然在文件中遇到一些错误,excel尝试将其恢复。在此恢复过程中,它(有时并非总是)使宏混乱!
没错,openpyxl无法读取和写入VBA代码。
根据这个线程:
I think you should not give the xlsM extension, because the file will
contain no VBA code. openpyxl is used to build xlsX files only.
请尝试尝试使用此派生:如果将keep_vba=True参数传递给load_workbook,它将完成此工作。
希望能有所帮助。
它对我没有用。这是我的wb = load_workbook(template.xlsm, keep_vba = True);代码
如果此fork不起作用-则无法使用openpyxl使其起作用。
如果您最初的excel是使用python创建的,则可能还需要添加workbook.xml并解析xlms表:
for sheet in range(1,4):
with open('sheetX.xml', 'r') as myfile: 'r') as myfile:
my_str=myfile.read()
substr =""
idx = my_str.index(substr)
my_str = my_str[:idx] + inserttxt + my_str[idx:]
with open('sheetX.xml',"w") as text_file:
text_file.write(my_str)
使用openpyxl编辑xlsm文件时,我遇到了相同的问题。我尝试了stackoverflow和其他论坛中提供的大多数解决方案/解决方法。但是他们都不起作用。然后我发现了xlwings,这个python库处理xlsm文档,它保留了所有宏。
import xlwings as xw
wb = xw.Book('macro_xl.xlsm')
sheet = wb.sheets['Sheet1']
sheet.range('A1').value = 'From Script'
wb.save('result_file_name.xlsm')
错误:TypeError:Book对象不可下标