2015-12-02 32 views
1

我需要在Excel工作表中搜索包含某些模式的单元格。这需要比我能处理更多的时间。下面是我可以编写的最优化的代码。由于数据模式通常是一排一排,所以我使用iter_rows(row_offset = x)。不幸的是,下面的代码在循环的每个循环中发现给定模式的次数越来越多(从毫秒开始并快到几分钟)。我究竟做错了什么?Openpyxl优化单元搜索速度

import openpyxl 
import datetime 
from openpyxl import Workbook 

wb = Workbook() 
ws = wb.active 
ws.title = "test_sheet" 

print("Generating quite big excel file") 

for i in range(1,10000): 
    for j in range(1,20): 
     ws.cell(row = i, column = j).value = "Cell[{},{}]".format(i,j) 

print("Saving test excel file") 
wb.save('test.xlsx') 

def FindXlCell(search_str, last_r): 
    t = datetime.datetime.utcnow() 
    for row in ws.iter_rows(row_offset=last_r): 
     for cell in row: 
      if (search_str == cell.value): 
       print(search_str, last_r, cell.row, datetime.datetime.utcnow() - t) 
       last_r = cell.row 
       return last_r 
    print("record not found ",search_str, datetime.datetime.utcnow() - t) 
    return 1 

wb = openpyxl.load_workbook("test.xlsx", data_only=True) 
t = datetime.datetime.utcnow() 
ws = wb["test_sheet"] 
last_row = 1 
print("Parsing excel file in a loop for 3 cells") 
for i in range(1,100,1): 
    last_row = FindXlCell("Cell[0,0]", last_row) 
    last_row = FindXlCell("Cell[1000,6]", last_row) 
    last_row = FindXlCell("Cell[6000,6]", last_row) 

回答

3

多次循环遍历工作表是低效的。搜索逐渐变慢的原因似乎是在每个循环中使用的记忆越来越多。这是因为last_row = FindXlCell("Cell[0,0]", last_row)意味着下一个搜索将在行末创建新单元格:openpyxl按需创建单元格,因为行在技术上可以是空的,但其中的单元格仍可寻址。在脚本结尾处,工作表总共有598000行,但您始终从A1开始搜索。

如果您希望多次搜索一个大文件的文本,那么创建一个以坐标为值的文本为关键字的矩阵可能是有意义的。

喜欢的东西:

matrix = {} 
for row in ws: 
    for cell in row: 
     matrix[cell.value] = (cell.row, cell.col_idx) 

在真实世界的例子你可能想使用defaultdict到能够处理多个小区相同的文字。

这可以与只读模式相结合以实现最小的内存占用。当然,如果你想编辑文件。