23

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

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

wb.save('testsave.xlsm');

但如果我按上述方式保存,我将无法打开该文件。但是,如果我将它保存为.xlsx,那么我可以在没有原始文件具有的宏功能的情况下打开文件。

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

4

6 回答 6

39

对我来说,这与版本一起工作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

于 2015-09-29T08:37:12.320 回答
8

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

  1. 打开原始文件(比如1.xlsm:)并用 openpyxl 变魔术;
  2. 另存为2.xlsx
  3. 这两个文件实际上都是压缩文件:将它们解压缩到一个临时目录;
  4. 将文件从原始文件的目录复制到文件的目录xlsx:其中一个文件是宏 ( vbaProject.bin),其中 2 个文件是必需的,因为它们描述了文件的类型等;
  5. 将属于该xlsx目录的所有文件放回一个 zip 文件中,并将其重命名zipxlsm. 此文件包含原始宏,并已使用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')
于 2017-01-19T12:56:11.743 回答
4

使用 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')
于 2019-01-11T02:43:08.573 回答
2

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

根据这个线程

我认为您不应该提供 xlsM 扩展名,因为该文件将不包含 VBA 代码。openpyxl 仅用于构建 xlsX 文件。

试试这个 fork:如果你将keep_vba=True参数传递给load_workbook它应该可以完成这项工作。

希望有帮助。

于 2013-07-16T12:17:39.910 回答
0

最好使用 xlwings 处理 xlsm 文档。我已经测试过了。

将 xlwings 导入为 xw

wb = xw.Book(DATA.xlsm)

于 2020-07-25T17:55:07.807 回答
0

如果您的初始 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 = "<dimension ref="
inserttxt = "<sheetPr codeName=\"Sheet"+str(sheet)+"\"/>"

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)
于 2019-01-14T18:43:14.460 回答