效率:openpyxl还是VBA?

Efficiency: openpyxl or VBA?

我正在尝试找出对于类似任务通常哪个更快:使用 VBA 或 openpyxl。

我知道这可能取决于你想要完成的任务,但是 假设我有一个 table 宽 50 个单元格,高 150,000 个单元格,我想从工作簿 A 到工作簿 B.

关于 python 是否会做得更好或者 Excel 是否更好地处理自己有什么想法吗?

我的直觉告诉我 python 应该相当快 出于某些原因:

除此之外,我想知道我是否可以对 openpyxl 脚本做一些进一步的改进,比如多线程或者可能与它一起使用 NumPy。

感谢您的帮助!

TBH 最快的方法可能是使用 xlwings 远程控制 Excel,因为这可以利用 Excel 的优化。 VBA 可能也可以连接到它,但我从来没有发现 VBA 很快。

Python 必须从 XML 转换为 Python,然后再转换回 XML。你有大约 5,000,000 百万个单元格,所以我预计这在我的机器上大约需要一分钟。我建议结合只读和只写模式来执行此操作以保持低内存使用率。

如果您只有数字数据(没有日期),那么您也许可以找到一个快捷方式和 "transplant" 相关工作表 XML 文件从一个 Excel 文件到另一个文件,然后只需更改相关元数据即可。

TL;DR 考虑直接连接到 Excel 文件(ADO in VBA or Python+PyWin32, pyodbc在 Python 或 .NET OleDbConnection class 等中)。您建立这种联系所用的语言无关紧要。

长版

如果您只想处理数据本身,您可能需要考虑使用 ADO、pyodbc 或 .NET OleDbConnection class 直接连接到 Excel .

自动化 Excel 应用程序(使用 Microsoft Excel 对象模型,或(大概)使用 xlwings)会产生大量开销,这是可以理解的,因为您可能不仅仅阅读Excel 文件中的数据,还可以操作 Excel UI 中的所有对象 — windows、菜单 — 以及数据之外的对象,例如对个人进行格式化单元格或范围。

确实 openpyxl 没有 UI 元素的所有这些开销,因为它直接读取文件,但我假设仍然会产生一些开销,因为 openpyxl 必须提供所有文件中的信息,这不仅仅是数据 — 例如,单元格格式。

建立数据连接还允许您将 Excel 文件视为一个数据库,您可以向其发出 SQL 语句,并具有 SQL -- 连接的所有功能, 排序, 分组, 聚合。

有关使用 ADO 和 VBA 的示例,请参阅 here

openpyxl ...

这个 link 对我很有帮助:

https://blog.dchidell.com/2019/06/24/openpyxl-poor-performance-optimisation/

  1. Use read_only when opening the file if all you're doing is reading.

  2. Use the built in iterators!

I cannot stress this enough - the iterators are fast, crazy fast.

  1. Call functions as infrequently as possible and store intermediate data in variables. It may bulk the code up a bit, but it tends to be more efficient and also allows your code to be more readable (but this is icing on the cake compared to points 1 and 2). Python can also be ambiguous as to what is a variable and what is a function; but as a general rule intermediate variables are good for multiple function calls.

我正在阅读特定工作簿中的值,我最初是这样做的:

wb = load_workbook(filename)

这将花费将近 80 秒。在操作之间缓存工作簿很有帮助,但每次重新加载脚本时仍然很痛苦。

我切换到只读。

wb = load_workbook(filename, data_only=True, read_only=True)

现在只需 < 0.1 秒。