【问题标题】:Efficiency: openpyxl or VBA?效率:openpyxl 还是 VBA?
【发布时间】:2016-02-13 17:58:03
【问题描述】:

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

我知道这可能取决于您想要完成的任务,但是假设我有一张宽 50 个单元格、高 150,000 个单元格的表格,我想将它从工作簿 A 复制到工作簿 B。强>

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

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

  • 为了让子从工作簿复制到另一个,两者都应该打开并运行,而使用 python 我可以简单地加载两者;
  • VBA 必须处理大多数任务的混乱情况,并且需要大量的系统资源

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

感谢您的帮助!

【问题讨论】:

  • 回答您的问题的最简单方法是对两种方法都计时。无需猜测。 “VBA 必须处理大多数任务的大量混乱,并且需要大量的系统资源”——这是基于什么?
  • 我不是最有经验的 VBA 编码器,但根据我的经验和我所知道的,使 VBA 高效是一项非常艰巨的任务,而且管理大量数据通常会变得非常慢。另外,我开始用两种资源编写这个例程,对于 VBA,我需要打开两个电子表格,每次我需要处理另一个电子表格时都必须激活它们,它会立即刷新,等等
  • 我会说,如果您没有使用 VBA 的经验,那么绝对有可能使 VBA 效率低下,但对于任何语言都可以这样说。 VBA 在性能方面的一大优势是它在与 Excel 相同的进程中运行,因此没有与从 VBA 自动化 excel 相关的跨进程开销:如果您进行大量调用,这可能会变得非常重要Excel 来自另一个进程。尽可能使用数组而不是逐个单元格可以帮助减少这种情况,但这绝对是一个因素。
  • 我认为这是我的情况。我使用 Python 比使用 VBA 更舒服。此外,我想我必须对每个文件进行一次调用

标签: python vba excel openpyxl


【解决方案1】:

TBH 最快的方法可能是使用xlwings 远程控制 Excel,因为这可以利用 Excel 的优化。 VBA 或许也能与之挂钩,但我从未发现 VBA 速度很快。

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

如果您只有数字数据(没有日期),那么您也许可以找到一个快捷方式并将相关的工作表 XML 文件从一个 Excel 文件“移植”到另一个文件,然后只更改相关的元数据。

【讨论】:

  • 我不知道xlwings,但我一定会看看!我没有考虑在 XML 和 Python 之间进行转换的不利之处。 “结合只读和只写模式”是什么意思?并且电子表格有很多文本和日期......无论如何,非常感谢您的帮助!
  • 一些伪代码:wb1 = load_workbook("file.xlsx", read_only=True); wb2=Workbook(write_only=True); ws1=wb1.active; ws2.wb2.active; for row in ws1.iter_rows(): ws.2.append([c.value for c in row])。有日期会减慢一些速度,因为 Excel 要求它们被格式化。
【解决方案2】:

TL;DR 考虑与 Excel 文件(VBA 或 Python+PyWin32 中的 ADO、Python 中的 pyodbc 或 .NET OleDbConnection 类等)建立直接数据连接。您建立这种联系所使用的语言的相关性要低得多。

加长版

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

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

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

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

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

【讨论】:

    【解决方案3】:

    openpyxl ...

    这个链接对我很有帮助:

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

    1. 如果您所做的只是阅读,则在打开文件时使用 read_only。

    2. 使用内置的迭代器!

    这点我怎么强调都不过分——迭代器的速度非常快,非常快。

    1. 尽可能不频繁地调用函数并存储中间函数 变量中的数据。它可能会使代码变大一点,但它往往是 更高效,还可以让您的代码更具可读性(但这 与第 1 点和第 2 点相比是锦上添花)。 Python也可以 什么是变量,什么是函数不明确;但作为 一般规则中间变量适用于多种功能 来电。

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

    wb = load_workbook(filename)
    

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

    我切换到只读模式。

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

    现在只需要

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-14
      • 1970-01-01
      • 1970-01-01
      • 2022-06-15
      • 2013-01-16
      • 2022-01-22
      相关资源
      最近更新 更多