2012-05-16 60 views
9

que necesito para leer un archivo xlsx de 10x5324 célulasiteración en un rango de filas utilizando ws.iter_rows en el lector optimizada de openpyxl

Ésta es la esencia de lo que yo estaba tratando de hacer:

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 

El código tardaba demasiado en ejecutarse, entonces debería (estaba realizando operaciones, no imprimiendo) y después de un tiempo me impacienté y lo cancelé.

¿Alguna idea de cómo puedo trabajar en el lector optimizado? Necesito iterar sobre un rango de filas, no sobre todas las filas. Esto es lo que he intentado, pero es equivocado:

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 

¿Hay alguna manera de hacerlo sin la función de rango?

Creo que una manera de hacerlo sería:

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

pero no es una solución más elegante? (esto no funciona bien por cierto)

Respuesta

5

Desde el documentation:

Nota: Cuando se crea una hoja de cálculo en la memoria, que no contiene células. Se crean cuando se accedió por primera vez. De esta forma, no creamos objetos que nunca sean accedidos, reduciendo así la huella de memoria.

Advertencia: Debido a esta característica, al desplazarse por las celdas en lugar de acceder a directamente las creará todas en la memoria, incluso si no les asigna un valor . Algo así como

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

creará 100x100 celdas en la memoria, para nada.

Sin embargo, hay una manera de limpiar todas esas celdas no deseadas, veremos que luego.

Creo que el acceso a las propiedades de columnas o filas hará que muchas celdas tengan que cargarse en la memoria. Sugeriría solo tratar de acceder directamente a las celdas que necesita.

por ejemplo.

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

La solución más simple con un límite inferior sería algo como esto:

# 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... 

Aquí otra forma de ejecutar lo que usted describe, con la función enumerate:

# 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... 

El índice la variable mantiene el recuento de la fila en la que se encuentra, por lo que se puede usar en lugar de range o xrange. Este método es bastante sencillo y funciona con iteradores a diferencia del rango o el corte, y también se puede usar con el límite inferior, si se desea. ¡Aclamaciones!

+1

para agregar a la solución 2 - puede agregar una instrucción else para salir de para, para detener la iteración sobre todas las filas una vez que está pasada la parada –

Cuestiones relacionadas