Mostrando entradas con la etiqueta openpyxl. Mostrar todas las entradas
Mostrando entradas con la etiqueta openpyxl. Mostrar todas las entradas

miércoles, 8 de octubre de 2025

Demanda. Propuesta.


Demanda de evaluación (V)




Elaboración del documento de solicitud

Aunque con algunos cambios respecto lo expuesto en la [entrada anterior] y admitiendo que la formulación de ese script se puede mejorar sustancialmente, damos por concluida esa primera fase del proyecto y nos embarcamos en la segunda: la elaboración del documento de demanda.

Este documento se genera automáticamente a partir de los datos recogidos en la fase anterior y almacenados para su uso posterior en un archivo llamado datos.txt, contenido en el subdirectorio datos (1). 

Opto por elaborar primeramente un documento en formato docx para que pueda se manipulado fácilmente por el profesorado una vez generado su contenido-base (2). Esto requiere trabajar con la biblioteca Python-docx (3). Una vez elaborado ese documento, propongo convertirlo a formato PDF para su tramitación segura (4).

Para el correcto desarrollo de esta fase del proceso se requiere acceder al archivo que contiene los datos (datos.txt) y manipularlo para obtener de él, de forma desglosada, toda la información. Dentro de este procedimiento es necesario convertir lo que son cadenas de caracteres en elementos de lista.

La segunda parte de la fase consiste en recuperar la información de los documentos que contienen los listados de DA, características EA y actuaciones MAD. Estos datos son necesarios para identificar los contenidos que son relevantes para el caso, ya que serán ellos los que consten en el documento (5)

Finalmente, la tercera parte de esta segunda fase es la creación del documento. Para ello necesitamos trabajar con Python-docx, aunque el objetivo es crear un documento simple, por lo que no me detendré en cuestiones de forma y estilo (6).

Paso a continuación a presentar este script.

#Importar bibliotecas

from docx import Document
from docx.shared import Inches

#CARGAR DATOS. Acceder al archivo datos.txt ------------------------------------------------

'''
Acceder al archivo, cargar la información y convertirla en lista.
'''

dir_archivo = 'datos/datos.txt'

archivo = open(dir_archivo,'r',encoding='utf-8')

texto=archivo.readlines()

archivo.close()

#Paso del contenido de cada línea a una variable

al = texto[0].rstrip()
da = texto[1].rstrip()
ea = texto[2].rstrip()
mad = texto[3].rstrip()

#Transformación de cada línea en una lista

datos_al = al.split('|')
datos_da = da.split('|')
datos_ea = ea.split('|')
datos_mad = mad.split('|')

#Extracción de información de datos_al

if datos_al[4] == 'EI':
    etapa = 'Educación Infantil'
else:
    etapa = 'Educación Primaria'

#Extracción de datos de las MAD (datos_mad)

'''
Requiere al acceso previo al documento que recoge estas medidas (ncc/mad.txt)
y la comparación de cada elemento de datos_mad con su contenido
'''

medidas_ap = []

mad_aplicadas = []

dir_datos = 'ncc/mad.txt'

archivo_mad = open(dir_datos,'r',encoding='utf-8')

medidas= archivo_mad.readlines()

for i in range(0,6,1):
    if datos_mad[i] == 'S':
        mad_aplicadas.append(medidas[i].strip())

#Extracción de datos de las DA  y EA observadas (condicionado al nivel escolar)

#Acceso a los documentos

dir_da = ''
dir_ea = ''
lista_da = []
lista_ea =[]

val_nivel = int(al[-1])

if val_nivel == 1:
    dir_da = 'ncc/da_n1.txt'
    dir_ea = 'ncc/ea_a.txt'
elif val_nivel == 2:
    dir_da = 'ncc/da_n2.txt'
    dir_ea = 'ncc/ea_b.txt'
elif val_nivel == 3:
    dir_da = 'ncc/da_n3.txt'
    dir_ea = 'ncc/ea_a.txt'

archivo_da = open(dir_da,'r',encoding='utf-8')

lista_da = archivo_da.readlines()

archivo_ea = open(dir_ea,'r',encoding='utf-8')

lista_ea = archivo_ea.readlines()

# Listado de características DA realmente observadas

caract_da = []

n_da = len(datos_da)

for i in range(0,n_da,1):
    if datos_da[i] == 'S':
        caract_da.append(lista_da[i].strip())

#Listado de características EA realmente observadas

caract_ea = []

n_ea = len(datos_ea)

for i in range(0,n_ea,1):
    if datos_ea[i] == 'S':
        caract_ea.append(lista_ea[i].strip())

#CREAR INFORME. Datos de identificación en formato docx  -------------------------------------

info_deriva = Document()

titulo = 'PROPUESTA DEL EQUIPO DOCENTE  DE SOLICITUD DE EVALUACIÓN PSICOPEDAGÓGICA'

info_deriva.add_heading(titulo, level = 0) #Título del documento

centro_curso = (f'Centro {datos_al[2]} \nCurso escolar {datos_al[3]}') #Datos de identificación

info_deriva.add_heading(centro_curso , level = 2)

dat_per = (f'Alumno/a: {datos_al[0]} {datos_al[1]}')

dat_escol = (f'Etapa y curso: {etapa} ({datos_al[5]})\nTutor/a: {datos_al[7]}')

dat_tut = (f'Fecha de emisión: {datos_al[6]}')

info_deriva.add_heading(dat_per , level = 3)

info_deriva.add_heading(dat_escol , level = 3)

info_deriva.add_heading(dat_tut , level = 3)

presenta = info_deriva.add_paragraph(f'\nMediante este documento el Equipo Educativo solicita al SEO la evaluación psicopedagógica de {datos_al[0]} {datos_al[1]} al observar la presencia de las dificultades de aprendizaje que se indican.\n') #Presentación del documento

medidas = info_deriva.add_paragraph(f'Previamente se informa de las medidas ordinarias de atención a la diversidad adoptadas con anterioridad a la formulación de esta demanda.\n') 

for mad in mad_aplicadas:

    info_deriva.add_paragraph(mad, style='List Bullet')

#Salto de página para crear los listados de las DA y las características EA observadas

info_deriva.add_page_break()

#Escritura de listado DA realmente observadas

info_deriva.add_paragraph('Se enumeran a continuación las dificultades de aprendizaje observadas\n')

for da_ob in caract_da:
    info_deriva.add_paragraph(da_ob, style='List Bullet')

#Escritura de las características (deficiencias) EA realmente observadas

info_deriva.add_paragraph('\nIgualmente se informa de las características del estilo de aprendizaje que se considera motivan la presente demanda de intervención del SEO:\n')

for ea_ob in caract_ea:
    info_deriva.add_paragraph(ea_ob, style='List Bullet')

#Fin y cierre del documento docx

print('FIN DEL SCRIPT DE COMPOSICIÓN DEL DOCUMENTO DE DERIVACIÓN')

info_deriva.save('solicitud.docx') # Cierre del documento docx

Espero que la aclaración que precede al script y los comentarios que éste contiene te sirvan para comprender su lógica y las instrucciones empleadas.

Cuando el procedimiento esté completo aportaré la documentación necesaria, de momento te propongo que estudies este script y manipules sus partes para entender cómo funciona. Para ello te aporto los documentos necesarios, incluyendo un ficticio datos.txt. Están disponibles en este [archivo zip].


NOTAS

(1) No era la única opción disponible y en cierto sentido puede resultar menos eficiente que otras, pero me ha parecido adecuada para facilitar la diferenciación de los dos subprocesos y aligerar de extensión y complejidad el script en el que he estado trabajando hasta ahora.
(2) Que es el que crea automáticamente el script anterior.
(3) Ver subsección del mismo nombre en la sección [Textos]
(4) En su momento trataré con más detalle estas cuestiones de procedimiento. De momento decir que esa última manipulación se realiza mediante la utilidad de conversión disponible en Word y en Writer. Como ya sabemos, aunque se cree un documento docx, es posible trabajar con él mediante Writer, incluyendo la posibilidad de exportar a formato PDF.
(5) Al contrario de la formulación de los soportes de las Administraciones educativas, los recursos de programación que empleamos y los script resultantes nos permiten identificar qué es lo relevante del caso y qué no lo es. No parece lógico renunciar a esta ventaja y reproducir fórmulas que son propias de modelos tipo formulario.
(6) Aun queda una última parte: la conversión del documento .docx en .pdf; pero no la considero relevante para esta exposición, como tampoco lo es la posible modificación que pueda realizar el profesorado del documento creado, opción disponible precisamente por crear el documento en un formato editable y accesible para los procesadores de texto de uso más común.

lunes, 7 de abril de 2025

Evaluación. Propuestas.

Python. Del registro a la tabla


Quedó dicho en [esta entrada] que los soportes -hoja de datos como informatización (o como mera digitalización) de la evaluación era un recurso de cierta incidencia en la práctica profesional (menos de lo deseable, también quedó dicho), así que es de esperar que exista un número importante de documentos que contengan datos de este tipo en los expedientes SEO. Dentro de una buena práctica del Servicio como tal está el análisis de esta documentación y Python nos puede ayudar en ello.


De hecho [el script de la entrada] antes citada puede considerarse la base de ese procedimiento, si bien necesitamos complementarlo con el procedimiento que desarrollamos precisamente [en la entrada que ha precedido] a la actual. En realidad lo que ahora se trata es de aplicar ese mismo procedimiento a una segunda situación o necesidad: la conversión de registros individuales en una base de datos.

Resumiendo, se trata de lo siguiente:
  • Recopilamos los datos de interés de documentos-Excel que contienen registros de resultados de aplicación de una prueba de la que carecemos de una tabla de datos que sirva de síntesis acumulativa de datos. Para ello empleamos el procedimiento descrito en este script (o uno equivalente, convenientemente adaptado a la realidad del registro a estudiar). 
from openpyxl import load_workbook

lista_al = ['Jaime','Lorenzo','Maria','Juan','Antonio','Lucrecia','Marcos','Susana','Noemi','Javier']
nombres = []
item3 = []
pdt = []

for i in range(0,9):
    libro = load_workbook(filename = 'Reg_'+lista_al[i]+'.xlsx')
    hoja =libro['Sheet']
    
    celda_nom = hoja['B2'].value
    print (celda_nom)
    nombres.append(celda_nom)
    
    celda_it3 = hoja['G4'].value
    print(celda_it3)
    item3.append(celda_it3)
    
    celda_pd = hoja['J2'].value
    print(celda_pd)
    pdt.append(celda_pd)

  •  Sobre la lista de datos que hemos obtenido en el proceso anterior creamos un documento-Excel en formato hoja de datos o data frame. Para ello podemos recurrir al procedimiento desarrollado en este script, con los ajustes que resulten precisos, claro está.

#Importar el módulo de creación del libro excell
from openpyxl import Workbook

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

#Crear libro
tabla = Workbook()

#Hoja activa
hoja = tabla.active

#Copiar encabezados en columnas

for i in range(0,20):
    hoja.cell(row = 1, column = i+1, value = campos[i])


#Guardar libro
tabla.save("Prueba_uno_tabla.xlsx")

Y finalizamos trasladando los datos recogidos en la fase 1 de este procedimiento a la tabla del documento-Excel qua acabamos de crear. Es en este punto donde debemos pensar en un procedimiento específico, ya que también lo es el objetivo que nos proponemos; no obstante, si lo que nos planteamos en estos momentos no tiene pretensiones de ser demasiado complejo, lo cierto es que el mismo procedimiento que empleamos para crear el encabezado de la tabla nos puede servir para completar la tabla, columna a columna, ya que así hemos recogido los datos de los registros individuales: en listas que se asimilan a las columnas de la tabla.

Con las modificaciones que corresponde, esta podría ser una primera solución. No es muy "elegante" que digamos, y puede ser mejora, pero es funcional, sencilla y replicable, así que de momento nos quedamos con ella. Aquí te muestro un ejemplo...

for i in range(0,10):
    hoja.cell(row = i+2, column = 1, value = nombres[i])

... que no te resultará desconocido después de haber estudiado el script de creación de la tabla: de hecho es el mismo, salvo la modificación del funcionamiento de filas y columnas y la llamada a una de las listas de los contenidos recuperados mediante el script de acceso a los registros.

Documento. Aquí tienes [acceso al script] comentado en la entrada. Con él finalizamos un recorrido por posibles opciones de trabajo con Python en el proceso de automatización de la evaluación. Pero hay más... más adelante.

Evaluación. Propuestas.

Python y 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.

sábado, 5 de abril de 2025

Evaluación. Propuestas

Acceso a registros con Python


La facilidad con la que se crean soportes para registro de datos en el servicio Hoja de cálculo (Calc o Excel, que también en esto son iguales), hace que sea frecuente encontrar este sistema como recurso aplicado a diferentes pruebas. En realidad se usa menos de lo que cabría esperar y sería de desear, pero aun así su uso es relativamente frecuente. Por lo visto en la [entrada anterior] también es sencillo crear estos registros mediante Python (OpenPyXL).


Y, claro está, no tiene mucho sentido tomarse el tiempo necesario para generar este sistema de registro si después no vamos a hacer uso de él. En tiempos en los que se trataba únicamente de digitalizar el registro de los resultados de la evaluación, la consulta del mismo era directa y sobre el soporte y los cálculos que se pudieran implementar en él mediante fórmulas propias, servían para construir el informe de resultados. 

Pero si implementamos procedimientos de automatización del informe, ese almacenamiento de registros puede resultar innecesario, salvo que pensemos en procesos posteriores de análisis de datos. Y es en esto en lo que actualmente estamos, a caballo entre la sección Evaluación y la sección (análisis de) Datos, en lo que a la estructura de este blog se refiere.

El objetivo de esta entrada es plantear en Python un sistema que permita acceder de forma automática a un determinado conjunto de registros de datos soportados sobre Excel (con independencia de que originalmente sean documentos Calc o Excel, ya que, como sabemos, la conversión de unos en otros es factible mediante LibreOffice). Es, como se puede deducir, un procedimiento complementario al desarrollado en la propuesta formulada en la [entrada anterior], motivo por el que se puede afirmar que dicha propuesta forma parte (y es la parte primera) de un procedimiento de doble acceso, por más que, en cuanto a script, resulte más apropiado diferenciar uno de otro, y en consecuencia, también en cuanto a entrada del blog.

El uso de este procedimiento para acceder a un registro individual puede estar justificado en ciertos casos, pero en la mayoría se trata de acceder a un conjunto de registros iguales para analizar determinado subconjunto de datos de los mismos. En sentido estricto, por tanto, se trata más de una cuestión que afecta a la sección Datos, que a Evaluación, pero por continuidad con la temática en que se enmarca la mantendré en ésta.

Partimos pues de la necesidad de trabajar con una lista de nombres de archivo, lo que nos obliga a modificar el planteamiento de trabajo expuesto [en la entrada] en la que se expuso el modo de acceder a hojas de cálculo mediante OpenPyXL, aunque podremos aprovechar estos procedimientos para resolver nuestra tarea actual.

Otro requisito previos es tener bien definido el objetivo de trabajo y conocer el documento de referencia para establecer correctamente el conjunto de hojas y celdas a las que debemos acceder.

Para ejemplificar este propuesta, crearé un conjunto de 10 registros con el script de la entrada precedente. Lo que me propongo es acceder a esos registros (libros Excel) y, en ellos, al nombre del alumno, a la puntuación que obtiene en uno de los ítem y al sumatorio PD. Este es el scritp necesario.

from openpyxl import load_workbook

lista_al = ['Jaime','Lorenzo','Maria','Juan','Antonio','Lucrecia','Marcos','Susana','Noemi','Javier']
nombres = []
item3 = []
pdt = []

for i in range(0,9):
    libro = load_workbook(filename = 'Reg_'+lista_al[i]+'.xlsx')
    hoja =libro['Sheet']
    
    celda_nom = hoja['B2'].value
    print (celda_nom)
    nombres.append(celda_nom)
    
    celda_it3 = hoja['G4'].value
    print(celda_it3)
    item3.append(celda_it3)
    
    celda_pd = hoja['J2'].value
    print(celda_pd)
    pdt.append(celda_pd)

  • Primero accedo al contenido de la librería que contiene las funciones de acceso a libros Excel (from openpyxl import load_workbook) 
  • Después creo una lista con los identificadores de los archivos a los que deseo acceder...
(lista_al = ['Jaime','Lorenzo','Maria','Juan','Antonio','Lucrecia','Marcos','Susana','Noemi','Javier'])
  • ... y tres listas vacías más, una para cada colección de datos (vg. nombres = [])
  • Mediante una estructura de bucle (for i in range(0,9):) genero un proceso cíclico que recorriendo la lista de libros (lista_al libro = load_workbook(filename = 'Reg_'+lista_al[i]+'.xlsx')) y estableciendo la hoja Sheet como hoja activa (hoja =libro['Sheet']), carga en una variable el contenido de las celdas seleccionadas (vg. celda_nom = hoja['B2'].value) y lo añade mediante la función append() al final de la lista creada previamente (vg. nombres.append(celda_nom))
(La función print() (print (celda_nom)) sirve únicamente para verificar el funcionamiento, por lo que se puede comentar en el script definitivo).

Con esto únicamente hemos accedido al contenidos predefinido de múltiples libros Excel, y resta tratar esos datos del modo que se desee, pero esa es una cuestión que ahora no tiene mayor importancia, por lo que, una vez alcanzado el objetivo propuesto, podemos dar por finalizado el script, si bien deberemos retomarlo (y modificarlo) para un objetivo concreto.

Documento. Aunque repetitivo con el contenido de la entrada, [este enlace] te da acceso al script que explico en ella. Su correcto funcionamiento presupone que tiene creados los libros que resultan del desarrollo de la función load_workbook(), los cuales se generan mediante el [este otro script]. Los script y los libros Excel están ubicados en el mismo directorio. Para probar el funcionamiento del script debes hacerlo desde el IDE de Python, no desde el cmd (símbolo de sistema).

viernes, 4 de abril de 2025

Evaluación. Propuestas.

Modelo de registro de datos en Python.


Frente al modelo básico en el que no he considerado necesario registrar los resultados, partimos ahora de que esto sí es necesario. Para ello crearé un sistema de registro basado en una hoja de cálculo.


Obsérvese que hablo de registro (individual) de datos, no de base de datos, diferencia esta muy importante. de hecho, este segundo modelo se diferencia del [anterior], pero también deja pendiente un tercer nivel de desarrollo para alcanzar lo ya conseguido mediante OOo Basic y el docap [que ya explicamos].

Ahora me planteo usar una hoja de cálculo, aunque también podría ser una alternativa válida utilizar un documento de texto: en sentido estricto, ambas ofrecen el mismo servicio. Pero en previsión de desarrollos posteriores es evidente que una hoja de cálculo presenta ventajas de acceso que no se dan en un documento de texto.

En cuanto al código, este segundo modelo aprovecha el desarrollado en el anterior script, introduciendo la creación de un libro Excel y la escritura de la información que se considera relevante para crear el registro individual de resultados. Para ello implemento procedimientos de trabajo de la biblioteca [OpenPyXL].

Y dado que el el código de base ya fue explicado en la [entrada precedente], me centraré en ésta en explicar el código que se añade y que se sitúa (salvo la instrucción from openpyxl import Workbook que se ubica al inicio del script) tras los cálculos de las puntuaciones del sujeto y la creación del informe en soporte documento.

#Hoja de datos
hc_reg = Workbook()

#Acceder a la hoja activa
hoja_act= hc_reg.active

#Escritura en celdas de los datos de identificación

id_datos = ['Registro de resultados','Nombre','Apellidos','Curso']
datos_per = [nombre, apellidos, curso ]

for i in range(0,4):
    hoja_act['A'+str(i+1)] = id_datos[i]

for i in range(0,3):
    hoja_act['B'+str(i+2)] = datos_per[i]

#Guardar datos de los resultados de la prueba

hoja_act['E1'] = 'ítem'
hoja_act['F1'] = 'Respuestas'
hoja_act['G1'] = 'Puntos'

for i in range (1,8):
    hoja_act['E'+str(i+1)] = 'ítem'+str(i)
    hoja_act['F'+str(i+1)] = respuestas[i-1]
    hoja_act['G'+str(i+1)] = pd[i-1]
    
hoja_act['I2'] = 'PD'
hoja_act['J2'] = pdt

hoja_act['I3'] = 'Porcentaje'
hoja_act['J3'] = pc

hoja_act['I4'] = 'Punt. típica'
hoja_act['J4'] = pz

#Guardar hoja
hc_reg.save('C:/PON_AQUÍ_TUS_DIRECTORIOS/Reg_' + nombre + '.xlsx')

Si has seguido este blog te darás cuenta de que lo fundamental de este código se corresponde con lo explicado en [esta entrada]. En todo caso te remito a ella para mayor detalle y aquí pasaré por alto las cuestiones básicas vistas en ella, como la creación del libro Excel (hc_reg = Workbook()) o el posicionamiento en la hoja (hoja_act= hc_reg.active).

La escritura de datos en una celda (vg. hoja_act['E1'] = 'ítem') no presenta ninguna dificultad y a esta instrucción he recurrido con frecuencia, como puedes observar. esto hace que el código no sea muy elegante, pero sí muy sencillo de entender y replicar.

Tampoco es demasiado complejo escribir una colección de datos en un grupo de celdas (esto es, crear una tabla, aunque con las limitaciones que esto tiene en este momento). Veamos como ejemplo el procedimiento más complejo de los que he usado en esta oportunidad: la creación de la tabla de respuestas y puntuaciones.

  • Primero creo la cabecera de la tabla (vg. hoja_act['E1'] = 'ítem')
  • Después utilizo un for (for i in range (1,8):)
  • ... y recorro las celdas colocando los datos generados directamente mediante el propio bucle (hoja_act['E'+str(i+1)] = 'ítem'+str(i)) o tomando los resultados de una lista (vg. hoja_act['F'+str(i+1)] = respuestas[i-1])
Observa que, para que todo funcione como se espera, es fundamental controlar qué valores se asignan al contador i, ya que unas veces se usa como referente para identificar la celda (['E'+str(i+1)]), otras para crear una cadena de texto ('ítem'+str(i)) y otra para referenciar el índice de una lista (respuestas[i-1])

Documento. Desde [este enlace] puedes acceder al script que desarrolla este modelo.