2012-05-16 12 views
9

Ich brauche eine xlsx Datei von 10x5324 ZellenIterieren über einen Bereich von Zeilen ws.iter_rows im optimierten Leser von openpyxl mit

Dies ist der Kern zu lesen, was ich tun wollte:

from openpyxl import load_workbook 
filename = 'file_path' 

wb = load_workbook(filename) 
ws = wb.get_sheet_by_name('LOG') 

col = {'Time':0 ...} 

for i in ws.columns[col['Time']][1:]: 
    print i.value.hour 

Der Code brauchte viel zu lange, um zu laufen, dann sollte es (ich führte Operationen, nicht Drucken) und nach einer Weile wurde ich ungeduldig und annullierte es.

Irgendeine Idee, wie ich es im optimierten Leser arbeiten kann? Ich muss über einen Bereich von Zeilen, nicht über alle Zeilen iterieren. Das ist, was ich versucht, aber es ist falsch:

wb = load_workbook(filename, use_iterators = True) 
ws = wb.get_sheet_by_name('LOG') 
for i in ws.iter_rows[1:]: 
    print i[col['Time']].value.hour 

Gibt es eine Möglichkeit, es ohne die Range-Funktion tun können?

Ich denke, eine Möglichkeit, es zu tun wäre:

for i in ws.iter_rows[1:]: 
    if i.row == startrow: 
     continue 
    print i[col['Time']].value.hour 
    if i.row == endrow: 
     break 

aber ist es eine elegantere Lösung? (das nicht funktioniert, entweder btw)

Antwort

5

Vom documentation:

Hinweis: Wenn ein Arbeitsblatt im Speicher erstellt wird, enthält es keine Zellen. Sie werden beim ersten Zugriff erstellt. Auf diese Weise erstellen wir keine Objekte, auf die nie zugegriffen werden würde, wodurch der Speicherbedarf reduziert wird.

Warnung: Aufgrund dieser Funktion, Scrollen durch Zellen anstatt direkt zugreifen sie alle im Speicher erstellen, auch wenn Sie keinen Wert ihnen zuweisen. Etwas wie

>>> for i in xrange(0,100): 
...    for j in xrange(0,100): 
...      ws.cell(row = i, column = j) 

wird 100x100 Zellen im Speicher für nichts schaffen.

Allerdings gibt es eine Möglichkeit, alle diese unerwünschten Zellen zu reinigen, wir sehen später .

Ich denke, der Zugriff auf die Spalten oder Zeilen Eigenschaften wird dazu führen, dass viele Zellen in den Speicher geladen werden müssen. Ich würde vorschlagen, nur zu versuchen, direkt auf die Zellen zuzugreifen, die Sie benötigen.

z.

col_name = 'A' 
start_row = 1 
end_row = 99 

range_expr = "{col}{start_row}:{col}{end_row}".format(
    col=col_name, start_row=start_row, end_row=end_row) 

for (time_cell,) in ws.iter_rows(range_string=range_expr): 
    print time_cell.value.hour 
18

Die einfachste Lösung mit einer unteren Grenze etwas so sein würde:

# Your code: 
from openpyxl import load_workbook 
filename = 'file_path' 
wb = load_workbook(filename, use_iterators=True) 
ws = wb.get_sheet_by_name('LOG') 

# Solution 1: 
for row in ws.iter_rows(row_offset=1): 
    # code to execute per row... 

Hier ist eine andere Art und Weise auszuführen, was Sie beschreiben, mit der enumerate Funktion:

# Solution 2: 
start, stop = 1, 100 # This will allow you to set a lower and upper limit 
for index, row in enumerate(ws.iter_rows()): 
    if start < index < stop: 
     # code to execute per row... 

Der Index Die Variable zählt, in welcher Zeile Sie sich befinden, daher kann sie anstelle von Bereich oder X-Bereich verwendet werden. Diese Methode ist ziemlich einfach und arbeitet mit Iteratoren im Gegensatz zu Bereich oder Slicing und kann, wenn gewünscht, auch nur mit der unteren Grenze verwendet werden. Prost!

+1

zu Lösung 2 hinzufügen - Sie können eine Else-Anweisung hinzufügen, um aus der for zu brechen, um die Iteration über alle Zeilen zu stoppen, wenn sie einmal vorbei ist –