lunes, 7 de abril de 2025

Evaluación. Python.

Base de datos en Excel

Aunque nada impide que podamos trabajar con registros individuales según vimos en el [entrada anterior], realmente no parece que sea el modo más eficiente de tratar con múltiples entradas. De ahí que en el [docap modelo] desarrolláramos un procedimiento para crear una tabla de datos o data frame, si se prefiere. El objetivo mínimo con Python es alcanzar al menos el mismo nivel de complejidad en el procedimiento.



Para ello, y en principio, debemos crear un script que en genere un soporte con formato de tabla, escribiendo los encabezados y, sobre esta base, un segundo script va añadiendo al soporte-tabla de datos cada una de los registros a modo de filas. Al finalizar el proceso, deberemos disponer de un data frame con todos los registros en formato filas-columnas. Posteriormente precisaremos desarrollar procedimientos para acceder a ese conjunto de datos, pero para ello openpyxl posiblemente ya no sea la mejor opción, dado que, para ello, existe bibliotecas más potentes. Pero esta es ya otra cuestión.

De momento vamos a centrarnos en crear una tabla de datos (base de datos) sobre Excel recurriendo a openpyxl, empezando por crear el documento-base; si bien antes deberemos diseñar (sobre papel) la estructura de la tabla: cuantos campos (columnas) y cual será su identificador de columna (cabecera). Tomaré como referencia la estructura de contenidos ideada [en esta ocasión], considerando como datos de interés los de identificación, las respuestas del sujeto a los ítem, la puntuación que recibe en cada ítem y las puntuaciones finales (sumatorio de PD, porcentaje y puntuación típica). Todo ello hace un total de 20 campos-columnas, lo que resulta ya suficientemente complejo.

Sobre esta estructura creamos en nuestro script una lista de encabezados (campos[]):

campos = [
            'Nombre','Apellidos','Curso',
            'r1','r2','r3','r4','r5','r6','r7',
            'p1','p2','p3','p4','p5','p6','p7',
            'PD','Porcentaje','P. típica'
    ]

El siguiente paso consiste en crear el libro Excel (tbl = Workbook()). No necesitamos crear ninguna hoja ya que es suficiente con la que se genera por defecto, con lo que simplemente la identificaremos como hoja activa (hoja = tabla.active).

La copia de los encabezados en la primera fila de la tabla se resuelve mediante un bucle for (for i in range(0,19):) utilizando el procedimiento que permite identificar individualmente fila (que será fija -> fila 1) y columna (que será variable -> columna i+1, y cambiará a cada vuelta del ciclo, al igual que el contenido a escribir)  -> (hoja.cell(row = 1, column = i+1, value = campos[i]))

Para finalizar, sólo resta guardar el archivo (tabla.save("Prueba_uno_tabla.xlsx"))

Hasta aquí podemos decir que ya sabemos crear un libro en formato de tabla simple, pero ahora nos falta aprender a llenarla de contenido. Para ello podemos situarnos en diferentes contextos, pero vamos a hacerlo en el que posiblemente sea el más común: el que resulta como alternativa a la creación de registros individuales, esto es, cada vez que introducimos los datos de un alumno, estos (además de servir para generar un informe individualizado, cuestión que ahora no nos interesa), se guardan en una tabla-base de datos o data frame, según se prefiera.

Para ello, tomando como base el script de referencia, deberemos elaborar uno distinto del que nos sirvió para crear la tabla, que se define, en primer lugar, como de acceso al archivo-tabla antes creado (tabla = load_workbook(filename = 'Prueba_uno_tabla.xlsx')), lo que requiere haber importado previamente el módulo load_workbook (from openpyxl import load_workbook) y posteriormente habernos situado en la hoja que contiene la tabla (hoja = tabla.active).

Obviamente necesitamos acceder a los datos mediante el o los procedimientos que correspondan; en este caso, según lo establecido en [el script] que nos sirve de base, y que ahora no hace falta explicar. 

Aunque no es obligatorio, sí es conveniente unificar en una única lista (lista_datos = []) todos los contenidos que deseamos guardar en nuestra base de datos. Para ello utilizaré de forma reiterada y acumulativa la función append() (vg. lista_datos.append(nombre)), aprovechando un ciclo for (for i in range(0,7):) para cargar en la lista-sumatorio cada uno de los registros que se presentan también en formato lista en el cuerpo del script de recogida de datos (vg. lista_datos.append(respuestas[i])).

Una vez creada la lista única nos queda trasladar su contenido a la base de datos, pero antes tenemos que identificar en qué registro o fila corresponde hacerlo. Para ello, una posible solución pasa por identificar cual es la primera celda de la columna A que no contiene datos y utilizar ese valor para posicionarnos en el proceso final de escritura del registro. 

El segmento de script que se encarga de identificar esa celda presenta cierta complejidad, por lo que es conveniente explicarlo con cierto detalle.
  • Identificamos una variable como fila con valor 0 para disponer de una referencia de base (fila = 0). Esto no es obligatorio hacerlo, pero clarifica el proceso.
  • Después establecemos un ciclo como recurso para recorrer la columna A (for i in range(1,100):). Aunque he puesto como límite la celda A100, se puede aumentar o reducir este valor si se prevé que el número de registros va a ser mayor o menor. En todo caso se trata de una referencia sujeta a modificación que no tendrá mayor relevancia en el funcionamiento real del script, como podremos entender más adelante.
  • Después establecemos el procedimiento de desarrollo del bucle (celda = hoja['A'+str(i)].value) que se puede resumir diciendo que la variable celda contiene sucesivamente el valor contenido en las celdas de la columna A de la hoja activa (hoja[]), siendo la expresión 'A'+str(i) la responsable de modificar la celda referenciada en función del desarrollo del bucle y el cambio de valor de la variable contador i.
  • El condicional incrustado en el ciclo que sigue a la instrucción anterior nos permite valorar el cumplimiento del criterio indicado antes: si la celda no contiene ningún valor (está vacía) (if celda == None:) entonces damos a la variable fila el valor de i (fila = i), lo que nos asegura que es coincidente con el identificador numérico de la fila.
  • En ese caso se produce el fin del bucle gracias a la instrucción break; pero en caso contrario (else:), continua el desarrollo del bucle (instrucción continue). En realidad, esta segunda parte del condicional no es necesaria por redundante, pero clarifica el funcionamiento de la estructura.
Con ese valor de fila establecido, procedemos finalmente a escribir en la tabla los valores contenidos en nuestra lista (lista_datos[]) usando el mismo procedimiento que ya usamos en el script con que generamos el encabezamiento de la tabla y que se explica en la primera parte de esta entrada.
  • Mediante un bucle for (for i in range(0,20):) con el que vamos a recorrer las posiciones de la tabla y de la lista de datos...
  • ... gracias a la función cell() y sus tres parámetros (hoja.cell(row = fila , column = i+1, value = lista_datos[i])):
    • El valor fila (row = fila), donde empleamos la variable fila calculada antes.
    • El valor de la columna (column = i+1), que se va incrementando en el transcurso del buble, recorriendo así todas las columnas de la tabla.
    • Y el dato a grabar en las celdas correspondientes, que se ubica en las diferentes posiciones de nuestra lista (value = lista_datos[i]), que también recorremos mediante los valores sucesivos de la variable contador i.
Este script finaliza necesariamente guardando de nuevo el archivo original, para que sea efectivo el incremento de datos de la tabla (tabla.save('Prueba_uno_tabla.xlsx')). En ocasiones nos puede interesar guardar el archivo con un nombre diferente cada vez que actualizamos nuestra base de datos, pero generalmente no va a ser el caso.

Documentos. Mediante este script puede crear la tabla y mediante este otro pasar datos a la misma. El primero queda explicado al inicio de esta entrada y el segundo en su segunda parte.

No hay comentarios:

Publicar un comentario

Comenta esta entrada