python - read - openpyxl xls
iterando sobre un rango de filas usando ws.iter_rows en el lector optimizado de openpyxl (2)
De la documentación :
Nota: Cuando se crea una hoja de cálculo en la memoria, no contiene celdas. Se crean cuando se accede por primera vez. De esta forma, no creamos objetos a los que nunca se accedería, reduciendo así la huella de memoria.
Advertencia: Debido a esta característica, al desplazarse por las celdas en lugar de acceder directamente a ellas, las creará todas en la memoria, incluso si no les asigna un valor. Algo 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 forma de limpiar todas esas celdas no deseadas, lo veremos luego.
Creo que acceder 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.
p.ej.
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
Necesito leer un archivo xlsx de 10x5324 celdas
Esta es la esencia de lo que 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 tanto en ejecutarse que 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 intenté, pero está mal:
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 que pueda hacerlo sin la función de rango?
Creo que una forma 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 hay una solución más elegante? (Eso tampoco funciona por cierto)
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 describes, con la función de 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...
La variable de índice 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!