【问题标题】:Excel using win32com and pythonExcel 使用 win32com 和 python
【发布时间】:2017-04-08 19:17:50
【问题描述】:

我想知道如何在不使用 python 的 win32com 客户端从 excel 表中迭代的情况下读取整列。

【问题讨论】:

    标签: python win32com


    【解决方案1】:

    您可以使用Range 集合读取整列而无需从工作表中进行迭代。如果您担心性能问题,您应该永远不要使用Cells。 Python 使用 win32com 模块与 Excel COM 库进行交互。每当您使用 Python 和 COM(Excel、PowerPoint、Acess、ADODB 等)时,最大的性能限制之一就是 COM 和 Python 之间的 IO。使用Range 方法,您只需调用一个COM 方法,而使用Cells,您为每一行调用一个。如果您在 VBA 或 .NET 中执行相同操作,这也会更快

    在以下测试中,我在单元格 A1 到 A2000 中创建了一个包含 10 个随机字符的工作表。然后我使用 Range 和 Cells 将这些值提取到列表中。

    import win32com.client
    app = win32com.client.Dispatch("Excel.Application")
    s = app.ActiveWorkbook.Sheets(1)
    
    def GetValuesByCells():
        startTime = time.time()
        vals = [s.Cells(r,1).Value for r in range(1,2001)]
        return time.time() - startTime
    
    def GetValuesByRange():
        startTime = time.time()
        vals = [v[0] for v in s.Range('A1:A2000').Value]
        return time.time() - startTime
    
    >>> GetValuesByRange()
    0.03600001335144043
    
    >>> GetValuesByCells()
    5.27400016784668
    

    在这种情况下,Range 比 Cells 快 2 个数量级 (146x)。请注意,Range 方法返回一个 2D 列表,其中每个内部列表都是一行。列表迭代将vals 转置为一个二维列表,其中内部列表是一列。

    【讨论】:

    • 好的,我对此表示赞同,尽管以目前的形式,我并不认为这是一个答案。对我来说,这是一个很长的评论。为什么我认为它仍然值得一票是它最终比迄今为止提出的其他任何一个答案都更有用和更有帮助(尽管 yuvi 已经被接受了)。这里显示的代码 sn-p 清楚地最接近说明如何“读取整个列而不迭代......使用win32com”。
    • 我刚刚回头看了这个答案,修改后回答了原来的问题
    • 我想知道它对xlrd 的效果如何。如果差异很小,那么 xlrd 将是一个明显的赢家
    • @yuvi:我自己没有进行过广泛的测试,但我认为这在很大程度上取决于数据的性质以及您尝试做的事情的性质。工作簿越大越复杂,Excel 在加载时间方面的优势就越大。您越能依靠 Excel 本身来完成繁重的工作(通过它的范围和计算引擎),Excel 的优势就越大。只要确保您进行尽可能少且高效的 COM 调用即可。
    【解决方案2】:

    您查看过openpyxl 库吗?来自文档:

    from openpyxl import load_workbook
    wb = load_workbook(filename='file.xlsx')
    ws = wb.get_sheet_by_name(name='Sheet1')
    columns = ws.columns()
    

    还支持迭代器和其他好东西。

    【讨论】:

      【解决方案3】:

      最快的方法是通过win32com.client API 使用内置的Range 功能。但是,我不是它的忠实粉丝。我认为 API 令人困惑且文档记录不完善,而且使用它不是很 Python (但这只是我)。

      如果效率对您来说不是问题,您可以使用出色的 xlrd 库。像这样:

      import xlrd
      book = xlrd.open_workbooks('Book1')
      sheet = book.sheet_by_name('Sheet1')
      sheel.col(1)
      sheet.col(2)
      # and so on...
      

      这为您提供了单元格对象。要获得纯值,请使用sheet.col_values(还有其他一些非常适合使用的方法)。

      请记住,xlrd 代表“excel read”,所以如果你想写入一个 excel 文件,你需要一个名为“xlwt”的不同库(这也很不错,虽然在我看来不如 xlrd)。

      【讨论】:

      • 是的,我确实尝试过编写这段代码并且在想,python 可以用来写尽可能少,所以我只是想知道是否有任何东西可以返回我所需的列表列值,无需我编写迭代部分。
      • 你可以使用xlrd库,稍等我加个例子
      • 那里。希望有帮助!
      • 从概念上讲,我认为 OP 正在寻找一种“一次性”检索整个范围的方法,例如使用 SELECT 从数据库中检索结果集。也就是说,在检索期间必须完成的任何“迭代”都会在到达 Python 之前处理。在数据库的情况下,SQL 引擎可能会在后台进行迭代,但您所看到的只是一个单个“返回值”,其中恰好包含多个值。因此,对于 Excel,OP 正在寻找指定一个范围,然后“一次”将所有值抓取到一个元组中。这可能会也可能不会;我不太了解 COM。
      • 说了这么多,我不明白 why 首先需要避免迭代。也许是因为通过 COM 逐个单元格地访问 Excel 非常慢。在 Excel 范围内操作比一次在一个单元格上操作要快得多。但是通过xlrd 直接读取文件(根本不涉及COM)通常足够快。
      猜你喜欢
      • 1970-01-01
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-30
      • 1970-01-01
      • 2014-02-23
      • 2014-04-10
      相关资源
      最近更新 更多