如何使用openpyx保存带有宏的XLSM文件

2024-10-04 05:23:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个带有宏功能的.xlsm文件。我正在使用openpyxl加载它,并将一些数据写入文件,最后希望另存为一个不同的.xlsm文件。

为了将文件保存为XLSM文件,我在Python脚本中使用了下面的代码。

wb.save('testsave.xlsm');

但如果我按上述方式保存,我就无法打开该文件。但如果我将其保存为.xlsx,则可以在不使用原始文件的宏函数的情况下打开该文件。

我想打开一个具有宏功能的Excel工作表,编辑文件并使用openpyxl将其保存为新的.xlsm文件。我该怎么做?


Tags: 文件数据函数代码功能脚本save方式
3条回答

对我来说,这和版本openpyxl==2.3.0-b2一起工作

wb = load_workbook(filename='original.xlsm', read_only=False, keep_vba=True)
..
wb.save('outfile.xlsm')

在这里的文档中,它也是mentioend:http://openpyxl.readthedocs.org/en/latest/usage.html?highlight=keep_vba#write-a-workbook-from-xltm-as-xlsm

没错,openpyxl不能读写VBA代码。

根据this thread

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.

改为尝试this fork:如果您将keep_vba=True参数传递给load_workbook,它就应该完成这项工作。

希望能有所帮助。

我不知道这是否仍然是相关的人提出的问题,但我正在处理同样的问题,并找到了一个可能的解决方案。

  1. 打开原始文件(比如:1.xlsm)并使用openpyxl执行魔术
  2. 另存为2.xlsx
  3. 两个文件实际上都是压缩文件:将它们解压缩到一个临时目录
  4. 将文件从原始文件的目录复制到xlsx文件的目录:其中一个文件是宏(vbaProject.bin),其中两个文件是必需的,因为它们描述了文件的类型等
  5. 将属于xlsx目录的所有文件放回zip文件中,并将其从zip重命名为xlsm。此文件包含原始宏,并已使用openpyxl进行编辑
  6. 可选)删除两个临时目录和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')

相关问题 更多 >