有什么方法可以在 python 中从头开始创建 .xlsm 文件?

is there any way to create a .xlsm file from scratch in python?

我在 mac 上使用 python 3.8.1 并尝试从头开始创建 .xlsm 文件。我看过 openpyxl 和 xlsxwriter,它们都能够从头开始创建 .xlsx 文件,并且都可以编辑现有的 .xlsm 文件,但我找不到任何关于实际创建 .xlsm 的信息] 文件从头开始。

我查看了 openpyxl 文档 here and the xlsxwriter documentation here,但我无法找到有关如何从头开始创建 .xlsm 文件的任何信息。我什至找不到有关如何将 .xlsx 文件转换为 .xlsm 文件的任何信息。

我最接近的是,您可以使用 xlsxwriter 中包含的 vba_extract.py 从现有的 .xlsm 文件中提取名为 vbaProject.bin 的文件,然后您可以将其添加到一个 .xlsx 文件然后你可以将它保存为 .xlsm 文件,但我需要从头开始创建一个 .xlsm 文件,而不是依赖于那里有一些文件来创建它。

openpyxl、xlsxwriter 或任何其他实用程序是否有任何我可以与 python 3.8.1 一起使用的东西,可以从头开始创建 .xlsm 文件,而不必依赖现有的 .xlsm 还是 vbaProject.bin 文件?一如既往,正确、解释清楚的答案将被标记为已接受并会被点赞。

据我所知,xlsm 格式与 xlsx 基本相同,唯一的区别是它可以包含宏(例如,参见 https://wiki.fileformat.com/spreadsheet/xlsm/)。

因此,您可以使用 openpyxl (https://openpyxl.readthedocs.io/en/stable/),除了将 xlsx 文件保存为 xlsm 扩展名(代码为摘自官方文档并略有更改):

from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws['A1'] = 42
ws.append([1, 2, 3])
wb.save('new_document.xlsm')

但是,在 openpyxl 中有一个奇怪的行为,没有正确记录,因此要使文件在 Excel 中真正可打开,您还需要:

wb = load_workbook('new_document.xltm', keep_vba=True)
wb.save('new_document.xlsm')

这里有一些解释:https://openpyxl.readthedocs.io/en/stable/tutorial.html#saving-as-a-stream

所以完整代码:

from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws['A1'] = 42
ws.append([1, 2, 3])
wb.save('new_document.xlsm')
# and the workaround
wb = load_workbook('new_document.xltm', keep_vba=True)
wb.save('new_document.xlsm')

看起来好像 XLSM 文件是压缩的 Excel 文件,包含宏等

我能够使用 openpxyl:

找到潜在的修复方法 here
import openpyxl as px
from openpyxl import load_workbook
import os
...
wbname='orig_fname.xlsm'
wb = load_workbook(filename=wbname, keep_vba=True)
...
wb.save('temp.xlsm')
os.rename('temp.xlsm', wbname)

请告诉我它是否适合你。

感谢 Alexander Pushkarev 和 APhillips 帮助解决这个问题。离开 Alexander 的 post 我能够想出一个 hack 来让它工作。我并不为此感到骄傲,但它确实有效。

运行 亚历山大的代码我得到这个错误:

Exception ignored in: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/zipfile.py", line 1819, in del self.close() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/zipfile.py", line 1836, in close self.fp.seek(self.start_dir) ValueError: I/O operation on closed file.

我试了一下,发现如果我从 load_workbook 函数中取出 keep_vba=True 代码 运行 但我在尝试时仍然遇到上面提到的错误使用 Excel 打开 .xlsm 文件。

所以,查看最新的错误,我看到最后一行说

I/O operation on closed file.

我查看了 openpxyl 文档并尝试在不使用 keep_vba=True 选项的情况下打开文件,然后再使用 keep_vba=True 打开它,它成功了。

所以请原谅这段丑陋的代码,但这将有助于从头开始创建一个 .xlsm 文件,而不依赖于任何现有文件(准备好复制和粘贴):

from openpyxl import Workbook
from openpyxl import load_workbook

wb = Workbook()
ws = wb.active
ws['A1'] = 42
ws.append([1, 2, 3])
wb.save('new_document.xlsm')
wb1 = load_workbook('new_document.xlsm')
wb2 = load_workbook('new_document.xlsm', keep_vba=True)
wb2.save('new_document.xlsm')