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

jueves, 13 de marzo de 2025

Aprendizaje. Presentación.

Diferentes soportes.

En  este repaso por las opciones de creación de recurso par la presentación de información es necesario conocer diferentes formas en que podemos elaborar este tipo de materiales haciendo uso, simplemente, de lo que nos ofrece una suite ofimática como LibreOffice.


Para revisar algunas de estas opciones retomo el contenido de una entrada publicada ya hace tiempo, en la que exponía tres formas de crear una presentación sobre unos materiales que desarrollaron en su momento  Elia Zapico y de Cristina Castellano, utilizando los pictos de ARASAAC y otros materiales. Titulé estos materiales NOS ALIMENTAMOS.



El material original es una presentación Impress (podría ser Power Point) y no emplea más que los recursos propios de este servicio. Con esto quiero decir que no contiene código OOo Basic.

A partir de ella elaboré un documento pdf que resulta de la conversión de la presentación en documento pdf (Archivo | Exportar a | Exportar a PDF). Esta opción de Impress permite mantener en el formato PDF algunas de las funcionalidades de la presentación, lo que facilita la navegación por el documento (.pdf).

Finalmente presento también uno último documento presentación soportado sobre una hoja de cálculo (LO-Calc). Se trata de mostrar que es posible utilizar Calc con esta finalidad, resultando bastante sencillo hacerlo, aunque en este caso, para imitar el funcionamiento de una presentación es necesario recurrir a OOo Basic. No importa tanto que Calc sea o no sea el soporte más adecuado, como el hecho de que, gracias a OOo Basic, es posible darle esta función, lo que en determinadas ocasiones puede resultar de mucha utilidad.

Documentos. En los enlaces que siguen puedes acceder a los documentos citados en la entrada. Añado un cuarto documento (txt) con el código asociado al documento Calc.

Aprendizaje. Presentación.

Contenidos y actividades

Aunque no es la continuidad temática que presenté en su momento, la propia lógica del desarrollo de la temática me ha llevado a este punto en el que se asocian la presentación y el aprendizaje (y la evaluación), la primera para la exposición de los contenidos de aprendizaje y la segunda como ejercicios para reforzar este aprendizaje: la forma clásica y más frecuente de presentación de los materiales curriculares, especialmente en las etapas iniciales del proceso educativo.



También en este caso no necesito más que recatar una entrada desarrollado hace ya tiempo en la que ambos tipos de de material se combinan formando una unidad de aprendizaje. Esta combinación lo es también de dos soportes diferentes: Impress para la presentación de los contenidos y Calc como soporte para la presentación de las actividades y su ejecución sobre el mismo soporte. Esto permite informatizar dicha ejecución y, consecuentemente, la evaluación de los resultados.

Vimos en otra entrada que es posible combinar varios soportes para crear una presentación y también mostré en otra que es posible utilizar Calc como soporte para hacer una presentación. Pero también es posible combinar ambas estrategias sin cargar sobre Calc con tareas para las que otros soportes (Impress) están mejor adaptados.

Por su parte, Impress no está pensado para trabajar del modo en que sí es posible hacerlo en Calc, coincidiendo ambas adaptaciones a los roles de presentación de la información y evaluación del aprendizaje. 

Esta combinación información-ejercicios, como dije, es básica en el diseño de materiales escolares, especialmente en la  etapa de E. Primaria.

Aunque uso de OOo Basic sólo en Calc, también es posible implementarlo en Impress, pero en realidad, en este caso, la mayor parte del trabajo se basa en las funcionalidades de ambos servicios.

Documentos

Materiales del docap:
  • NosAlimentamosIni.ods. Docap basado en Calc. Contiene la presentación, las actividades y su evaluación.
  • NosAlimentamos.odp. Presentación Impress que cumple la función de presentación de los contenidos.
Anexos:
  • AnexoCodigo.txt. Anexo .txt con el código OOo Basic empleado en el docap (Libro Calc. La presentación no contiene código)
  • AccesoImpress.pdf. Anexo .pdf donde explico el script para acceder a una presentación Impress y lanzarla. Este código también se encuentra en el anexo .txt. 

domingo, 9 de marzo de 2025

Aprendizaje. Recursos.

Formatos y recursos

Una ventaja que deriva de diferenciar la original mezcla entre evaluación e intervención en dos secciones (Aprendizaje y Evaluación) es poder tratar en la primera (Aprendizaje) una cuestión que resultaba casi ajena al mismo en la formulación original del blog: la creación de recursos para el aprendizaje y la evaluación.


Dedicaré esta entrada a diferenciar tipos de recursos y en sucesivas a explicar en detalle en qué consiste cada uno de ellos. Estamos ante una cuestión previa al tratamiento de los ítem de evaluación, al constituir estos una concreción de uno de los usos posibles, mientras que en la formulación anterior de la sección única constituían el centro de la misma. Esta pérdida de centralidad es consecuencia del "descubrimiento" de que en realidad la evaluación es sólo una de las posibles aplicaciones de los recursos disponibles; precisamente aquella que la formulación oficial de la competencia digital entiende como principal manifestación de dicha competencia en el ámbito docente: la creación de materiales para la instrucción y el aprendizaje.

Efectivamente, de eso va esta entrada, pero no en el marco de la interpretación "oficial" de la competencia, así que no se espere aquí, en esta sección, un tratamiento de las herramientas de autor; más bien se trata de analizar cómo nuestras herramientas y nuestro enfoque competencial también sirven para resolver las necesidades docentes que cubre los campos de la elaboración de materiales para la evaluación, pero también para el proceso E-A en sentido amplio.

Desde esta perspectiva, el primer formato en que se expresan estos recursos tiene que ver con la forma más simple de expresarse el objetivo instruccional y de plantearse la interacción del alumno con el material (de aprendizaje): la presentación o exposición del contenido y de la información en soporte digital. No es casual que la principal herramienta que sirve a tal fin lleve también el mismo nombre, así como la forma básica en que se presenta como producto: presentación (de contenidos) es tanto el enfoque del objetivo, como la herramienta (programa de presentación, vg. Power Point) como el producto (una presentación de diapositivas, seguimos llamando a dicho producto, en justo recuerdo de sus antecedentes analógicos). Es verdad que este término (presentación), no está, pues, exento de riesgos por la confusión a que puede dar lugar (por ejemplo, entre objetivo y medio), pero creo que es el mejor y el más justo, si queremos reconocer a los antecedentes analógicos el papel que cumplieron para que ahora estemos aquí. 

Por orden de importancia en el proceso E-A, aunque resulte dudoso, sitúo la creación de recursos que contribuyen al aprendizaje, sea este entendido como entrenamiento más o menos sistemático de procedimientos (generalmente simples, aunque no sólo) o como ejecución de actividades de captación y recuerdo de aprendizajes (normalmente de datos y conceptos). Mientras que ante los materiales de presentación, la labor del discente era receptiva (sin connotaciones negativas), ahora es activa, ya que es el alumno quien maneja e interactúa con los materiales de aprendizaje, nombre que utilizaré como descriptor, sobreentendiendo que con él me refiero a todos aquellos que tienen que ver con la realización de actividades de ejercitación de procedimientos, recuerdo y adquisición de contenidos y refuerzo y recuperación de procesos de aprendizaje.

No cabe duda que estos materiales van de la mano de (y complementan a) los anteriores, pero no se pueden confundir con ellos, ni la tecnología de soporte con que se realizan son los mismos, aunque sí existen tecnologías mixtas (herramientas de autor) que aúnan ambas funciones. Lo "curioso" es que precisamente la combinación de medios ofimáticos ofrece también la posibilidad de elaborar productos que, entendidos como conjunto, combinan la presentación con el aprendizaje, justamente sin necesidad de específicas "herramientas de autor". Por este, aunque no son las únicas, serán tratadas especialmente en esta sección del blog; por este motivo, pero también por compartir (o hacer posible cubrir) dos objetivos: el aprendizaje y la evaluación del aprendizaje. 

El tercer formato, la demostración en sus diferentes formas y niveles de complejidad, no deja de ser un desarrollo del primero (la presentación), pero es de mayor complejidad en cuanto a requisitos técnicos; tanto que el medio que hasta ahora ha resultado fundamental (en programa de elaboración de presentaciones), ahora requiere de todo su potencial (recursos de animación e incorporación de MAV) para estar cerca de quedarse corto. También es este el límite en el que algunas herramientas de autor se muestran aprovechables, aunque requieren un nivel de dominio que no está disponible para todos los usuarios, por lo que dejan que desear como recursos de expresión de la competencia digital docente: pretenden eludir un procesos de aprendizaje que permita alcanzar un nivel de dominio satisfactorio, pero lo requieren para dar respuesta a necesidades a las que da igual o mejor respuesta el aprendizaje de la programación.

Finalmente, un cuarto formato queda identificado como juego, que reúne las exigencias de dinamismos e interacción de los formatos anteriores, y que se puede entender como desarrollo de la lógica que preside las actividades de aprendizaje, aunque contiene elementos de todos los anteriores. El desarrollo de este tipo de productos no es asumible desde los servicios de una suite ofimática y tampoco por la mayoría de las herramientas de autor (podría haberlo sido para los lenguajes de autor), por lo que tenemos que recurrir a lenguajes de programación que dispongan de utilidades específicas: PyGame de Python es una de ellas. Esta librería nos permite crear juegos bidimensionales, pero, por lo dicho antes, también se puede usar para generar los diferentes formatos de los que hemos hablado en esta entrada. Digo esto por constituir por ello una alternativa al uso de los servicios ofimáticos y las herramientas de autor.

viernes, 20 de diciembre de 2024

Análisis. Datos.

Acceso a tabla: columnas y filas.

Antes de iniciar el análisis de datos, y como paso previo, trabajando con OOo Basic es necesario aprender a acceder a las columnas (campos o variables, según se prefiera) y a las filas (o registros).


Ambos accesos se circunscriben al trabajo con OOo Basic como herramienta para el análisis de datos, ya que en otros lenguajes (R y Python) no son necesarios como tales, puesto que el proceso se resuelve de forma directa mediante las funciones correspondiente (1).

Lo que sí van a tener los tres lenguajes es que en el proceso de análisis de datos también en OOo Basic trabajaré directamente desde el IDE como espacio para la generación de script y el desarrollo del propio proceso de análisis. Como consecuencia de ello, y al contrario del planteamiento de trabajo que implica el desarrollo de docap, aquí no existirá otra interface que el propio IDE y el recurso a ventanas emergentes (MsgBox) como medio para que OOo Basic genere las salidas de datos. Esto significa que, en principio, no se prestará atención a la entrada de datos y a la salida sólo mediante escritura en la hoja de cálculo cuando resulte pertinente; el resto queda a la escritura de código y a la recopilación manual por parte del usuario. Es este un procedimiento extraño al objetivo para el que fue ideado OOo Basic, pero muy común en los lenguajes Python y R (especialmente este último) y empleándolo me quiero aproximar a ese modo de trabajo, eludiendo de paso la carga de trabajo que supone el diseño de interfaces de usuario. Se espera que a estas alturas del proceso de aprendizaje LO - OOo Basic este modo de uso del lenguaje no suponga ningún problema para el usuario.

Para concretar y ejemplificar ambos procedimientos de acceso a los datos emplearé una tabla ficticia que recoge el registro de actuaciones mensuales de un OE en un determinado centro a lo largo del curso (2). Sobre esta base, empezaré por explicar el acceso a una columna de datos, que es, posiblemente, el procedimiento más empleado en el análisis de datos.

Sub AccesoCol

Dim vN As Integer, i As Integer
Dim vHoja As String, vCol As String, vTipoDat As String
Dim mDatosCol() As Variant
Dim oHoja As Object, oCelda As Object

vN = 9
vHoja = "Datos"
vCol = "E"

ReDim mDatosCol(vN)

vTipoDat = "N" 'Tipo de datos a capturar: T - Texto y N - Numérico

oHoja = ThisComponent.getSheets().getByName(vHoja)

For i = 0 To UBound(mDatosCol())
oCelda = oHoja.getCellRangeByName(vCol & i+2)
If vTipoDat = "N" Then
mDatosCol(i) = CInt(oCelda.getString)
ElseIf vTipoDat = "T" Then
mDatosCol(i) = oCelda.getString
End If
Next

End Sub

Tras la declaración de las variables, asignamos valores a las variables que nos van a permitir dimensionar la matriz de datos (ReDim mDatosCol(vN)) y acceder a la hoja (vHoja = "Datos") y  a la columna (vCol = "E")  donde se encuentran dichos datos. Después seleccionamos el tipo de datos al que se va a acceder (vTipoDat = "N") (3), a fin de facilitar el uso de procedimiento adecuado a ese tipo de datos, según veremos un poco más abajo.

Lo siguiente que hacemos es acceder a la hoja (oHoja = ThisComponent.getSheets().getByName(vHoja)) y después, mednte un bucle (For i = 0 To UBound(mDatosCol())), a cada una de las celdas de la columna seleccionada (oCelda = oHoja.getCellRangeByName(vCol & i+2)). Como la instrucción de acceso es diferente en función del tipo de datos (textos o números), empleamos un condicional para acceder a números (If vTipoDat = "N" Then) -> (mDatosCol(i) = CInt(oCelda.getString)) u otro para acceder a textos (ElseIf vTipoDat = "T" Then) -> (mDatosCol(i) = oCelda.getString).

Y ya estamos en disposición de trabajar con esta matriz de datos que consideramos valores de la variable (en este caso) Actividad Tipo 1 (AT1), sea esta lo que sea.

Si quisiéramos acceder a una segunda variable, deberíamos crear una segunda matriz de datos y proceder del mismo modo, lo que implica complicar el script. En caso de que este script resulte demasiado complejo y se reduzca la funcionalidad de uso, sería conveniente plantearse la creación de una función o una subrutina en la que concretar aquellos procedimientos que se repiten varias veces en dicho script (4).

El acceso a una determinada fila | registro de la tabla, en principio, no es muy diferentes al modo que utilizamos para grabar los datos en una determinada fila, según quedó explicado en entradas anteriores [por ejemplo en esta], y que empleamos para crear el docap de generación de la tabla de datos [ver aquí], pero presenta algunas diferencias debidas al cambio de tratamiento de los datos.

Sub AccesoFil

Dim oHojaBD As Object, oCeldaInicio As Object, oCeldaRegistro As Object
Dim vN As Integer, i As Integer
Dim vHoja As String
Dim a As Integer, b As Integer, c As Integer, vFil As Integer
Dim mDatos() As String

vHoja = "Datos" ' Nombre de la hoja de datos

oHojaBD = ThisComponent.getSheets().getByName(vHoja)

vN = 7 'Nº de elementos de la fila (campos del registro)
ReDim mDatos(vN)

c = 100
vFil = 5 'Id de la fila (registro) a seleccionar

For b = 0 To c
If b + 1 = vFil Then
For i = 0 To UBound(mDatos())
oCeldaRegistro = oHojaBD.getCellByPosition(i,vFil)
mDatos(i) = oCeldaRegistro.getString()
Next
End If
Next

End Sub

Primero accedemos a la hoja (oHojaBD = ThisComponent.getSheets().getByName(vHoja)) identificada previamente en la variable (vHoja = "Datos") y después redimensionamos la matriz (ReDim mDatos(vN)) en función del número de campos del registro (vN = 7) y terminamos identificando el Id el registro deseado (vFil = 5).

Después ejecutamos la estructura ciclo-Condicional-ciclo que nos va a permitir acceder al contenido de los campos de ese registro. Para ello recorremos la base de datos (For b = 0 To c) hasta encontrar el valor del contador b que coincida con el Id del registro buscado (vFil) estableciendo en ese momento la condicionalidad (If b + 1 = vFil Then) dentro de la cual ejecutamos un segundo bucle (For i = 0 To UBound(mDatos())) que recorre las columnas (oCeldaRegistro = oHojaBD.getCellByPosition(i,vFil)) asignando a la matriz el contenido de las celdas correspondientes a ese registro (mDatos(i) = oCeldaRegistro.getString()).

También aquí el script deberá repetirse tantas veces como registros deseemos capturar, por lo que puede volverse poco manejable. En ese caso también será conveniente reconvertir el script en una función (ver nota 4).

Documento. Desde [este enlace] puedes acceder al documento que contiene ambos script.

NOTAS

(1) El trabajo con estos lenguajes se verá en próximas entradas, pero por ahora me voy a limitar a trabajar con OOo Basic.
(2) Aunque la base es el docap para crear una tabla expuesto en [esta entrada], el código que contiene los procedimientos de acceso se ubica en un módulo específico (ModAccesoDatos), diferentes del módulo que contiene los script y subrutinas del docap original (renombrado ahora como ModCrearTabla). Al código anterior no haré mención en la entrada actual.
(3) La forma en que se plantea este subproceso deriva directamente del modelo de trabajo empleado (trabajo en OOo Basic directamente desde el IDE) , incluyendo el uso de un comentario que clarifica cómo se debe proceder. De prestar una mínima atención al modo clásico de trabajo deberíamos crear un formulario de entrada de datos o recurrir a la función InputBox(), pero ahora eso es innecesario, ya que se espera que el usuario introduzca los datos directamente en el script.
(4) Solución que aplicaremos cuando llegue el momento. Por ahora es suficiente con exponer cómo acceder a los datos de una columna | variable | campo y te aconsejo que practiques este procedimiento hasta tener seguridad en su manejo.


jueves, 19 de diciembre de 2024

Análisis. Datos.

Tabla de datos basada en LibreOffice

Me propongo desarrollar en esta entrada un modelo de docap basado en Calc y OOo Basic que facilite la recogida sistemática de aquellos datos que, por el planteamiento del problema, no está contemplada en los modelos de docap anteriores. Remitiéndome a una [entrada previa], estaría hablando aquí de los datos necesarios para el análisis de datos no contemplado como análisis de resultados de un test. Esto equivale a decir, datos para análisis de las actuaciones, del funcionamiento del SEO o del funcionamiento de una prueba no contemplada en el capítulo de evaluación de pruebas.


Este docap tiene como único objetivo facilitar la recogida de datos para construir la tabla que será posteriormente objeto de análisis; no implica nada respecto al análisis propiamente dicho, procedimiento que tiene su propia lógica y sus fases. Como docap es realmente muy simple, ya que resulta de "recortar" el docap previamente definido como docap-modelo de evaluación, que [se expuso aquí].

Consta de dos fases: la creación del formulario (incluyendo la asociación de los controles a celdas) y de la tabla-base, y el desarrollo del código.

Para la creación del formulario deberemos tener en cuenta la diferenciación entre los datos de identificación y los datos de resultados, definiéndose los campos como variables o columnas de la base de datos. Se mantiene aquí la misma diferenciación que vimos en el docap de evaluación, pero no la diferenciación en la asignación de cada categoría a una columna de celdas, ya que en este docap no se plantea realizar ningún procesamiento de los datos, únicamente recogerlos. Esto tiene implicaciones en cuanto a simplificación del código, como veremos posteriormente. También lo tiene en el propio planteamiento del formulario, ya que no es necesario recoger nada que pueda ser calculado a posteriori, correspondiendo estos cálculo al propio proceso de análisis.


La imagen anterior representa lo que podría ser una formulación básica del formulario. En él se representa un sistema simple de recogida de datos de un conjunto de actuaciones identificadas por tipología (que deberá establecerse a priori) por OE (podría plantearse otro docap similar para cada perfil del SEO), centro y mes (1).

En la segunda fase (código) se diferencian dos script principales: Main y BorrarDatos. Este segundo permite reutilizar el docap sin necesidad de borrar manualmente los contenidos previamente introducidos (2). En esta entrada me centraré en explicar Main y su subrutina asociada (PasarDatos()), la cual se ocupa de pasar los datos a la tabla.

Empezaremos por establecer las variables necesarias...

Dim oHoja As Object, oCelda As Object
Dim mDatos() As Variant
Dim i As Integer, ni As Integer

... y por acceder a la hoja que contiene los datos.

oHoja = ThisComponent.getSheets().getByName("Form")

Después, dimensionamos la matriz mDatos() (ReDim mDatos(ni)) atendiendo al número de campos del formulario (ni = 6) que es el mismo que celdas I contienen datos. También definimos los contenidos de la matriz que identifica esas celdas (mCeldasi= Array("I1","I2","I3","I4","I5","I6","I7")).

Una vez establecidos estos valores, mediante un bucle recorremos esas celdas y asignamos su contenido a los elementos de la matriz mDatos(), siguiendo el procedimiento ya conocido.

For i = 0 To UBound(mDatos())
oCelda = oHoja.getCellRangeByName(mCeldasi(i))
mDatos(i) = oCelda.getString()
Next
 
Usamos esa matriz como parámetro que pasamos a la subrutina PasarDatos() para que ésta resuelva el proceso de pasar los datos a la tabla (3).

Sub PasarDatos(Datos() As Variant)

Dim oHojaBD As Object, oCeldaInicio As Object, oCeldaNuevoRegistro As Object, oCeldaId As Object
Dim i As Integer, a As Integer, b As Integer, c As Integer, d As Integer

oHojaBD = ThisComponent.getSheets().getByName("Datos")

c = 1000

For i = 0 To c
oCeldaInicio = oHojaBD.getCellRangeByName("A" & CStr(i+2))
If oCeldaInicio.getValue() = 0 Then
a = i + 2
d = i + 1
Exit For
End If
Next

MsgBox "Id de la nueva entrada: " & d

'Escritura de los datos en el registro vacío

oCeldaId = oHojaBD.getCellRangeByName("A" & CStr(a))
oCeldaId.setValue(d)

For b = 0 To UBound(Datos())
oCeldaNuevoRegistro = oHojaBD.getCellByPosition(b+1,a-1)
oCeldaNuevoRegistro.setString(Datos(b))
Next

End Sub

Documento. Puedes descargar el archivo [desde este enlace]

NOTAS

(1) Se suponen identificados a priori SEO y curso, aunque éste se identifica en el encabezamiento. Y todo ello en un contexto que define el objetivo del análisis al que servirá esta base de datos como de análisis de una tipología dada de actuaciones en un curso. Este planteamiento encaja con el supuesto de análisis de actuaciones del SEO. La base de datos (hoja Datos) contiene como encabezados (campos) los mismos conceptos.
(2) Dada su simplicidad y el carácter complementario que tiene respecto al objetivo del docap, me limito a remitirte al código de este script, que puedes encontrar en su IDE.
(3) Aunque el código de esta subrutina es fundamental para este docap, ya ha sido explicado en [esta entrada], en su parte final.

miércoles, 18 de diciembre de 2024

Evaluación. Automatización.

Modelo básico de docap

Calificar de básico este modelo equivale a decir que es concreción del docap tipo 2 visto en [esta entrada]; decir docap incide en el uso de OOo Basic como lenguaje de referencia. Al estar en la sección Evaluación concretamos que este docap es un intento de automatización de los procedimientos de evaluación, con las especificaciones que realizamos en la [entrada que precede] a la actual.


Aclaro en primer lugar que me limito al docap-modelo el de tipo 2 por ser el de uso más frecuente también en el ámbito de la evaluación, pero también por similitud con el soporte básico de recogida de datos que veremos la sección Análisis.

Entrando ya en materia y completando lo indicado en la entrada citada al inicio de ésta, el docap-modelo que presento ahora no se diferencia demasiado del presentado [en esta entrada] respecto al trabajo con documentos. Salvando algunas diferencias (que puede haberlas), la mayor y más significativa es que el docap actual añade una base de datos a los componentes del docap; el resto de no tiene por qué ser diferente, aunque sí lo será el procedimiento de análisis. No obstante, como este análisis no será abordado detenidamente en esta entrada por los mismos motivos (más otros añadidos) (1) que en aquel caso, las diferencias reales entre ambos soportes, en términos de código, se reducen significativamente, por lo que no resultará demasiado complicado explicar y entender lo que a continuación voy a exponer: en gran medida será suficiente con repetir lo ya visto.

Para concretar un docap-modelo de evaluación primero se debe especificar en que nivel se recoge los datos, ya que es posible diferenciar tres: respuestas del alumno, puntuaciones obtenidas por ítem y puntuación total de la prueba. Considero que para que resulte realmente operativo (en términos de automatización) se debe entender como nivel básico el segundo, aunque en función de los objetivos de esta entrada yo trabajaré desde el primer nivel: recogida de las respuestas, que implica que la puntuación de las mismas se debe resolver en el docap.

Una segunda cuestión, aunque se refiere al análisis de datos y dije antes que en esto no iba a ser abordado en esta entrada, es con qué referentes se van a calificar los resultados. Esta cuestión requiere aclarar previamente qué tipo de evaluación se propone: normativa, criterial o mixta. Estas cuestiones no corresponden a esta entrada, ya que es necesario clarificar el significado concreto de esos conceptos y sus implicaciones, por eso opto aquí por una solución de compromiso simplificada (2).

La primera fase del proyecto es, como en los modelos documentales, el trabajo con la hoja de cálculo, empezando por la creación del formulario (hoja Form) (3). Este podría ser el resultado:


No he pretendido hacer nada complicado, por lo que es mejorable (también a nivel estético), pero sirve para nuestro objetivo actual: recoger la información de forma eficiente sin sobrepasar el nivel de complejidad técnica básico, que por ahora consiste en el uso de funcionalidades de formulario de Calc. No obstante presenta algunas diferencias respecto al nivel más elemental de trabajo con documentos, y lo explico a continuación:
  • En el formulario se diferencian tres partes, frente a las dos de los modelos anteriores: a parte de los botones de comando, los controles de entrada se diferencian por su función: los tres primeros son para datos de identificación y los restantes para la recogida de las respuestas de los ítem.
  • Esta diferencia se reproduce en la asignación de esos controles a celdas: los controles de datos de identificación se asocian a tres celdas de la columna I, y los de los controles de ítem a siete celdas de la columna J.
  • Esta diferenciación por columnas puede no ser necesaria, pero sí la diferenciación en el acceso a cada uno de los dos tipos de datos, como veremos en el código correspondiente. Después explicaré el motivo.
Además, y esa es la principal diferencia con los docap-modelo documentales, deberemos crear una segunda hoja (Datos) donde crearé la tabla de datos, concretamente los encabezamientos de las columnas que sirven para identificar sus campos.

Una vez preparado el documento Calc, corresponde desarrollar el código que nos permite acceder a los datos introducidos por el usuario. Para ello declaro las variables (4) y accedo al documento y a la hoja Form, siguiendo el procedimiento ya conocido...

Dim oHoja As Object, oCelda As Object
Dim mDatosper() As String, mCeldasi() As String
Dim mResp() As String, mCeldasj () As String, mAcierto() As String
Dim mPtos() As Integer, PD As Integer
Dim n1 As Integer, nj As Integer
Dim i As Integer
Dim Md As Single, Dt As Single, Pz As Single, Pc As Single
Dim mDatos() As Variant

oHoja = ThisComponent.getSheets().getByName("Form")

Observa que he declarado dos matrices para contener los datos (mDatosper() y mResp()), ya que me interesa trabajar de forma independiente con cada uno de los dos bloques. Como dije antes, esta diferenciación obedece al diferente tratamiento que tendrán los datos de identificación y los de respuestas a los ítem: los primeros no presentan novedad respecto a otras ocasiones, pero los segundos sí: sobre ellos realizaremos operaciones específicas, como tendremos ocasión de ver en su momento. Repito: con los datos personales nos limitamos acceder a ellos, pero los datos de respuesta a los ítem serán usados para generar los elementos de la tercera matriz (mPtos()), que contendrá la puntuación de los ítem, que resulta de la corrección de la prueba; los referentes para la corrección de los ítem están contenidas en una cuarta matriz (mAcierto()).

Por ello, el acceso a las respuestas del alumno, con la que finaliza la primera fase del script principal Main se resuelve de forma similar a cómo se resolvió el acceso a los datos personales, mediante un bucle For (For i = 0 To UBound(mResp()))

ni = 2
ReDim mDatosper(ni)
mCeldasi= Array("I1","I2","I3")

For i = 0 To UBound(mDatosper())
oCelda = oHoja.getCellRangeByName(mCeldasi(i))
mDatosper(i) = oCelda.getString()
Next

A continuación entramos en la segunda fase de Main, en la que corregimos las respuestas dadas por el alumno. En este caso el sistema es muy sencillo, pero puede ser mucho más laborioso de no trabajar con una matriz específica de respuestas, de ahí que sea recomendable diferenciarla de la de datos de identificación, como indiqué en su momento.

Para realizar esta corrección damos contenido a la matriz que contiene las respuestas correctas (mAcierto() = Array("A","B","C","D","E","F","G")) y mediante un nuevo bucle (For i = 0 To  UBound(mResp())) y un condicional (If mResp(i) = mAcierto(i) Then) recorremos la matriz mResp() y comparamos su contenido con el esperado (mResp(i) = mAcierto(i)), asignando la puntuación que corresponde a cada ítem según se cumpla o no dicha condición. Aprovecho este mismo bucle  para calcular el sumatorio de las puntuaciones del alumno (PD = PD + mPtos(i)), lo que supone entrar en la tercera fase del script.

mAcierto() = Array("A","B","C","D","E","F","G")

For i = 0 To  UBound(mResp())
If mResp(i) = mAcierto(i) Then
mPtos(i) = 1
Else
mPtos(i) = 0
End If
PD = PD + mPtos(i)
Next

Como dije, este sumatorio constituye el inicio de la tercera fase, la cual está dedicada a realizar los cálculos que nos permitirán calificar los resultados que obtiene el alumno: el porcentaje de aciertos, en función del tamaño del test y su puntuación directa (Pc = (PD/(nj+1))*100), y la puntuación típica (Pz = (PD - Md)/Dt), en función de supuestos valores de media (Md = 5.38) y la desviación típica (Dt = 0.47) (5).

A continuación se desarrolla la cuarta fase del script principal (Main) que tiene como objetivo construir con los datos parciales anteriores una matriz única de datos con la que trabajaremos en las subrutinas a las que se llama al final de Main (PasarDatos(mDatos()) y Info(mDatos())) (quinta fase). 

Aunque podríamos ahorrarnos esta cuarta fase, por los motivos que dije en su momento puede no ser la mejor opción; pero, en todo caso, sí es conveniente crear una matriz única con todos los datos necesarios, ya que será muy útil para el correcto funcionamiento de las subrutinas que veremos más adelante. 

Para crear esta matriz-síntesis recurriré de nuevo a los bucles como medio para automatizar la asignación de contenidos, aunque es necesario asignar de forma directa algunos de ellos, como puedes comprobar en el código que sigue:

ReDim mDatos(19)

For i = 0 To UBound (mDatosper())
mDatos(i) = mDatosper(i)
Next

For i = 0 To UBound( mResp())
mDatos(i+3) = mResp(i)
Next

For i = 0 To UBound(mPtos())
mDatos(i+10) = mPtos(i)
Next

mDatos(17) = PD
mDatos(18) = Pc
mDatos(19) = Pz

Primero redimensionamos la matriz-resumen (ReDim mDatos(19)) y después vamos asignando los datos, empezando por los personales (mDatos(i) = mDatosper(i)), siguiendo por las respuestas del alumno (mDatos(i+3) = mResp(i)), después los resultantes de la corrección de la prueba (mDatos(i+10) = mPtos(i)), finalizando con los datos-resumen, resultantes de los cálculos (vg. mDatos(17) = PD) (6).

Paso ahora a explicar los dos procedimientos que restan y que se ejecutan de forma independiente del script principal, mediante dos subrutinas: 
  • La primera (Sub PasarDatos(Datos() As Variant)) está pensada para construir la base de datos, trasladando los datos de la matriz-resumen (mDatos()) a la tabla creada en la hoja Datos.
  • La segunda (Sub Info(Datos() As Variant)), ya conocida de [esta entrada], sirve para crear el informe (sobre Writer).
Estas subrutinas constituyen una especie de "externalización de procedimientos" del algoritmo, pero esto, además de ejemplificar el uso del principio de la programación modular, resulta necesario explicarlos con detalle, dada la relativa complejidad de ambos subprocesos y su independencia respecto al objetivo principal del script Main

Dado que la segunda subrutina ya es conocida desde la publicación de [esta entrada], me limitaré a explicar la primera. Con ella automatizamos la creación de la tabla o base de datos, dotando a nuestro docap de un potencial muy interesante: recopilar los resultados de las aplicaciones individuales de una prueba, lo que facilita el posterior análisis de dichos datos (7).

Sub PasarDatos(Datos() As Variant)

Dim oHojaBD As Object, oCeldaInicio As Object, oCeldaNuevoRegistro As Object, oCeldaId As Object
Dim i As Integer, a As Integer, b As Integer, c As Integer, d As Integer

oHojaBD = ThisComponent.getSheets().getByName("Datos")

c = 1000

For i = 0 To c
oCeldaInicio = oHojaBD.getCellRangeByName("A" & CStr(i+2))
If oCeldaInicio.getValue() = 0 Then
a = i + 2
d = i + 1
Exit For
End If
Next

MsgBox "Id de la nueva entrada: " & d

'Escritura de los datos en el registro vacío

oCeldaId = oHojaBD.getCellRangeByName("A" & CStr(a))
oCeldaId.setValue(d)

For b = 0 To UBound(Datos())
oCeldaNuevoRegistro = oHojaBD.getCellByPosition(b+1,a-1)
oCeldaNuevoRegistro.setString(Datos(b))
Next

End Sub

Esta subrutina cuenta con un argumento que remite a la matriz-resumen (PasarDatos(Datos() As Variant)de los datos del script principal Main, resultando ahora evidente la necesidad de su creación: gracias a ellos se simplifica la escritura de esos datos en la tabla.

Pero antes de dar ese paso debemos acceder a la hoja Datos (oHojaBD = ThisComponent.getSheets().getByName("Datos")) y posicionarnos adecuadamente en la primera fila no escrita (8) mediante un bucle condicionado

For i = 0 To c
oCeldaInicio = oHojaBD.getCellRangeByName("A" & CStr(i+2))
If oCeldaInicio.getValue() = 0 Then
a = i + 2
d = i + 1
Exit For
End If
Next

Cuando encontramos la celda de la columna A (oCeldaInicio = oHojaBD.getCellRangeByName("A" & CStr(i+2))) que cumple la condición (oCeldaInicio.getValue() = 0) asignamos el valor de inicio a la variable-contador que nos van a permitir recorrer las diferentes columnas de la tabla (a = i + 2) y de captura el valor Id de la fila A que precede a la que no cumple el criterio del condicional (d = i + 1). Después interrumpimos el bucle.

Después volvemos a posicionarnos en la celda de la columna A localizada mediante el bucle anterior (oCeldaId = oHojaBD.getCellRangeByName("A" & CStr(a))) y escribimos en ella el valor Id que corresponde (oCeldaId.setValue(d)) y de nuevo, mediante un bucle dimensionado en base a la matriz-resumen (For b = 0 To UBound(Datos())), recorremos ahora las columnas (campos) que se corresponden con la fila (oCeldaNuevoRegistro = oHojaBD.getCellByPosition(b+1,a-1)) y trasladamos a cada celda los datos de la matriz (oCeldaNuevoRegistro.setString(Datos(b))).

Documento. Desde este enlace puedes acceder al docap explicado en esta entrada.

NOTAS

(1) Si en el caso de los docap-documento el tema del procesamiento remitía a las dificultades para tratar de forma simplificada el problema del procesamiento, en el caso de los docap-evaluación la problemática se acentúa, ya que de una prueba de evaluación se derivan muchos más datos cuantitativos y de categorización que requieren procesos de análisis de la bifurcación de mayor complejidad. No obstante el tratamiento de la opcionalidad en el caso de los contenidos textuales es realmente más complejo, ya que se ajustan en menor medida que los datos de un test a un planteamiento de tipo algorítmico.
(2) Por lo que no resulta satisfactorio desde ninguna de las perspectiva de análisis, pero tiene la ventaja de incluir referencias a ambos modelos (y al mixto). Además, y es lo que importa, evidencia los mecanismos básicos del análisis desde ambas perspectivas (la normativa y la criterial), aunque de forma muy simplificada.
(3) Dado que el informe se crea sobre un documento en blanco, no es necesario crearlo. También es posible utilizar un documento previamente creado y formateado, con lo que implica de trabajo previo y de modificación del código de acceso. Ver al respecto el modelo básico 2 de docap de documento en [esta entrada]
(4) Incluyendo las que serán necesarias para el procesamiento posterior y que explicaré en su momento.
(5) Ambos valores sirve únicamente a efectos del funcionamiento del docap, pero no reflejan valores reales de ninguna prueba en concreto.
(6) Puedes apreciar que los tres primeros bloques se ejecutan mediante bucles (reajustando los valores de los índices de la matriz-resumen) y en los últimos la asignación se realiza de forma directa.
(7) Este análisis es anticipatorio pero diferentes del que nos planteamos en la sección Análisis del Blog. También lo es este docap del que podemos crear dentro de ese campo de trabajo.
(8) Recuerda que una fila de una tabla equivale a un registro en una base de datos. Las columnas de la tabla equivalen a los campos de la base de datos y serán tratadas como variables en el análisis de datos.