2015-12-02 33 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到能夠處理多個小區相同的文字。

這可以與只讀模式相結合以實現最小的內存佔用。當然,如果你想編輯文件。