将 pandas 数据框写入 xlsm 文件(启用宏的 Excel)

Posted

技术标签:

【中文标题】将 pandas 数据框写入 xlsm 文件(启用宏的 Excel)【英文标题】:Write pandas dataframe to xlsm file (Excel with Macros enabled) 【发布时间】:2015-03-26 00:33:56 【问题描述】:

.xlsx 格式将pandas.DataFrame 写入Excel 工作簿非常简​​单:

import pandas as pd
df = pd.DataFrame('firstColumn' : [5, 2, 0, 10, 4], 'secondColumn' : [9, 8, 21, 3, 8])
print(df)
df.to_excel('test.xlsx')

给出:

   firstColumn  secondColumn
0            5             9
1            2             8
2            0            21
3           10             3
4            4             8

以及相应的 Excel 文件。

是否也可以将DataFrame 写入.xlsm Excel 文件?这实际上或多或少与.xlsx 相同,但可以在文件中存储 VBA 宏。我需要这个,因为我想在创建文件后插入并运行 VBA 宏。

但是,在常规 xlsx 文件上尝试此操作时,我会在弹出窗口中收到以下错误消息:

The following features cannot be saved in macro-free workbooks: VB project.
To save a file with these features, click No, and then choose a macro-enabled file type in the File Type list.
To continue saving as macro-free workbook, click Yes.

然后我可以手动选择将文件保存为.xlsm,其中将包含我的宏。但是,我更愿意自动执行此操作而无需额外步骤。

documentation for the to_excel method 表明这应该是可能的(参见engine 参数)。但是,我不明白如何启用它。

当我简单地将输出文件名更改为*.xlsm 时,会创建一个.xlsx 文件,命名 .xlsm。当我尝试打开它时,我得到了

Excel cannot open the file 'myFilename.xlsm' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.

如果我手动将扩展名更改为.xlsx,我可以再次打开它。

关于this part of the pandas documentation:

openpyxl:这包括对 OpenPyxl 1.6.1 直至但不包括 2.0.0 的稳定支持,以及对 OpenPyxl 2.0.0 及更高版本的实验性支持。`

我的Openpyxl 版本是1.8.6。更新到 2.1.4 并没有解决问题。也没有将 XlsxWriter 从 0.63 更新到 0.6.6。

按照建议使用df.to_excel('test.xlsx', engine='openpyxl')也没有解决问题。

【问题讨论】:

如果您只是将文件名更改为'test.xlsm' 会发生什么?根据ExcelWriter source,engine“默认为io.excel.<extension>.writer。另见pandas.pydata.org/pandas-docs/stable/… 哦,是的,我忘了提...这会创建一个名为 xlsmxlsx 文件。当我尝试打开它时,我得到Excel cannot open the file 'myFilename.xlsm' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file. 如果我手动将扩展名更改为xlsx,我可以再次打开它。 请您编辑问题以包含此信息和任何其他相关信息。您是否尝试过指定engine='openpyxl' 不,没有其他错误 - 命名文件 xlsm 时,我得到一个扩展名错误的 xlsx 文件。只需将文件命名为 xlsm 并且 pandas 会选择正确的引擎,它对您有用吗?如果不是,那么我猜熊猫的文档在这方面有点过于简化了,尤其是关于 jmcnamara 的(更复杂的)建议,它起到了作用。 我没有在此处安装pandas,我只是想鼓励您提供所有适当的故障排除信息。不过,很高兴您找到了有效的答案。 【参考方案1】:

Pandas 要求工作簿名称以 .xls.xlsx 结尾。它使用扩展来选择使用哪个 Excel 引擎。

您可以传递一个临时名称,然后用以下内容覆盖它:

import pandas as pd

df = pd.DataFrame('First' : [5, 2, 0, 10, 4], 
                   'Second' : [9, 8, 21, 3, 8])

writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')

df.to_excel(writer, sheet_name='Sheet1')

workbook  = writer.book
workbook.filename = 'test.xlsm'
# !! Won't load in Excel !!

writer.save()

这将创建一个扩展名为 .xlsm 的 Excel 文件。

但是,由于名为“扩展强化”的功能,Excel 不会打开此文件,因为它知道它不包含宏并且实际上不是xlsm 文件。 (就是您上面报告的 Excel 错误。)

您可以使用最新版本的 XlsxWriter 解决此问题,方法是从真正的 xlsm 文件中提取 VbaProject.bin 宏文件并将其插入到新文件中:

import pandas as pd

df = pd.DataFrame('First' : [5, 2, 0, 10, 4], 
                   'Second' : [9, 8, 21, 3, 8])

writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')

df.to_excel(writer, sheet_name='Sheet1')

workbook  = writer.book
workbook.filename = 'test.xlsm'
workbook.add_vba_project('./vbaProject.bin')

writer.save()

有关详细信息,请参阅 XlsxWriter 文档的 Working with VBA Macros 部分。

【讨论】:

这太棒了!顺便说一句,我无法运行您在文档中提到的vba_extract.py 脚本 - 源代码看起来像 html 文件并导致 SyntaxError?或者应该如何使用?但是,as suggested here,也可以简单地将xlsm 文件重命名为zip,用任何归档工具打开它,然后从xl 文件夹中提取vbaProject.bin 文件。确保xlsm文件至少包含一个宏,否则不会有这个文件。 安装 XlsxWriter 时,您的构建系统/打包程序应将 vba_extract.py 实用程序安装到您的路径中。如果不是,它也包含在存储库的示例目录中。 如果我试图将数据框写入已经包含大量宏的现有工作表 (xlsm) 怎么办?它会“破坏”我现有的文件吗?我会丢失宏吗? 对于想要将启用宏的新文件保存在不同位置的人,只需提供文件名的完整路径即可。例如:workbook.filename = '/path/of/your/choice/filename.xlsm'

以上是关于将 pandas 数据框写入 xlsm 文件(启用宏的 Excel)的主要内容,如果未能解决你的问题,请参考以下文章

在python中使用pandas数据框保存.xlsm(excel)文件的问题

如何将 Pandas 数据框写入 HDF5 数据集

将 Pandas 数据框的全部内容写入 HTML 表

如何使用 openpyxl 使用宏保存 XLSM 文件

使用 Pandas 写入时文件损坏

使用 pandas 读取和更新 XLSM 文件中的工作表,同时保留 VBA 代码