Biblioteca openpyxl (2). Acceso a datos.
La segunda parte, y a la vez la inversa del proceso descrito en la entrada anterior, es el acceso a un libro Excel y a los datos contenidos en cualquiera de sus hojas. Existen diferentes recursos Python para hacerlo, pero por ahora nos limitaremos a la biblioteca openpyxl.
Lo primero que tenemos que hacer es acceder al módulo que nos permite cargar un libro Excel mediante la instrucción correspondiente (from openpyxl import load_workbook), que, mediante su función load_workbook() permite acceder con facilidad a cualquier archivo identificado como .xlsx. Esta función recibe un parámetro asociado al atributo filename que asocia la dirección del archivo (load_workbook(filename = 'Libro2.xlsx') -> en este caso se supone que el archivo se encuentra en el mismo directorio que el script). Para facilitar el manejo del objeto, lo referenciamos en una variable, lo que facilita el trabajo posterior (vg. libro = load_workbook(filename = 'Libro2.xlsx'))
El segundo paso consiste en acceder a la hoja en la que se encuentran nuestros datos. Esto podemos hacerlo de dos formas diferentes:
- Accediendo a la hoja activa (la primera) (hoja = libro.active)
- O identificando la hoja por su nombre (Vg. hoja =libro['Hoja0'])
Aunque cualquiera de los dos procedimientos es válido, posiblemente sea el segundo el de mayor utilidad, aunque requiere saber de antemano el nombre de cada una de las hojas a las que deseamos acceder; nada que deba suponer un problema para nosotros, teniendo en cuenta el uso que vamos a hacer de script de este tipo.
El tercer paso es en realidad un conjunto de opciones (de las que vamos a ver algunas de ellas), que tienen en común, como es de esperar, el acceso a los datos contenidos en celdas.
Y la forma más simple de hacerlo es identificando directamente la celda por su posición (A1). Así, por ejemplo, para celda1 = hoja['A1'].value, la expresión print('El dato de la celda A1 es: '+ celda1) nos muestra el contenido de dicha celda. Aunque si el contenido es un número nos dará error, siendo necesario convertir la variable a string (str(celda1)). Dado que no incurrimos en error en caso de convertir un string en string, parece conveniente emplear la función de conversión por defecto cuando el objetivo sea el manejo de cadenas de texto (concatenación), como es el caso de lo que pretendemos con la función print().
Si conocemos (y así será la mayoría de la veces) la estructura de los datos a los que deseamos acceder, podemos crear un procedimiento basado en la repetición del modelo anterior, lo cual es funcional y suficiente cuando deseemos acceder a hojas de cálculo diseñadas como registro de datos, pero puede no ser lo más adecuado cuando trabajamos con hojas de cálculo que contienen tablas, que son la mayoría de las que nos podemos encontrar. En estos casos nos van a ser de utilidad conocer otras formas de acceder al contenido.
Disponemos, en primer lugar, de un procedimiento para conocer cuantas filas y columnas hay creadas en nuestra hoja, punto de partida interesante para el trabajo posterior:
- col_n = hoja.max_column -> print('Número total de columnas: '+str(col_n))
- fil_n = hoja.max_row -> print('Número total de filas : '+str(fil_n))
... nos devuelven respectivamente sendos integer con el número de columnas y de filas. Estos datos son de interés cuando la hoja está organizada de forma simple y compacta, pero puede generar confusión cuando cuenta con tablas diferentes y de escasa identidad en cuanto a contenido. De ahí también el interés de construir tablas con sentido y unidad de criterio, aunque sea a costa de aumentar el número de hojas del libro.
Pero bueno, esta es otra cuestión. Volvamos a lo que nos interesa, que ahora es acceder al contenido de una fila de datos, para lo cual recurrimos a una estructura compleja basada en la función cell().value y una estructura for...
- valores_fila = [hoja.cell(row=2, column=i).value for i in range(1,hoja.max_column+1)]
... que trataré de explicar a continuación:
- los valores obtenidos mediante la función cell() toma como referencia (en esta caso) la segunda fila (row =2) de la tabla (colección de celdas) de la hoja referenciada en la variable hoja (hoja.cell().value).
- Sobre las columnas iterará el bucle for que desarrolla el atributo value de la estructura (.value for i...)
- Es este ciclo es que se encarga de recoger los valores de las columnas (de la fila indicada antes), desde la primer hasta la última de las columnas (hoja.max.column+1)
De modo similar podemos acceder al contenido de una columna de datos mediante una estructura simular a la anterior...
- valores_col=[hoja.cell(row=i,column=2).value for i in range(2,7)]
... en la que...
- usamos la misma función cell().value asociada a un ciclo for (cell().value for i...) en la que ahora la itinerancia de ciclo se realiza sobre el identificador de la fila (row=i), mientras que se establece el valor fijo de la columna (column=2 -> en este caso nos interesa al segunda columna de la tabla)
- ...lo que repercute en el contenido de range(), que tiene como primer parámetro la segunda celda (de la segunda columna) empezando desde B1 (ergo B2) y recorre hasta la posición 7
Para finalizar esta entrada, vamos a ver cómo podemos acceder a un conjunto de registros (filas y columnas), lo que equivale decir que a una base de datos. Este procedimiento viene a ser el resumen de los dos anteriores, pero se desarrolla de forma diferentes.
- Primero creamos un rango de celdas (las que nos interesan para nuestro análisis) mediante un procedimiento de acotado sobre la hoja (rango_celdas = hoja['A2':'C6'])
- Y después lo recorremos mediante for indicando explícitamente cada uno de los elementos de su estructura (for cell1, cell2,cell3 in rango_celdas:)
- ... para (en este ejemplo) mostrarlo por pantalla (print(cell1.value, cell2.value,cell3.value))
El rango de celdas establecido identifica la fila (en este caso A2, para no acceder al encabezado de la tabla) y la columna final (en este caso C6, para recoger todos los registros de datos). La enumeración de celdas en la estructura for y en el función print() es fundamental para que efectivamente podamos acceder a ellas mediante el bucle y (en este caso) mostrar su contenido (vg. cell1.value).
Documento. Accede desde este enlace al script en el que se recoge el código analizado en esta entrada.
No hay comentarios:
Publicar un comentario
Comenta esta entrada