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

lunes, 26 de mayo de 2025

Becas NEAE


Beca NEAE


DocAp simple sobre marcadores



En esta entrada presento un modelo de cumplimentación automatizada de informe para solicitud de Beca NEAE basado en Writer y OOo Basic. Es posible que esté un tanto obsoleto y que requiera ser modificado, pero te puede servir de base incluso en su actual formulación.

Este tipo de documento plantea diversas vías de automatización, incluyendo la combinación del procedimiento basado en la identificación de variables y el uso a los marcadores. Esta segunda opción se puede considerar la más apropiada si en el documento se suceden intercalados bloques de contenido basados en tablas y otros basados en párrafos, como es el caso del informe de solicitud de beca NEAE, documento cuya automatización es posible abordar de diferentes maneras, siendo una de ellas la que ejemplifica el DocAp al que puedes acceder desde este enlace [InfoBecaNEAE].

He calificado este DocAp como simple por usar únicamente el servicio Writer, pero no por ello deja de presentar cierta complejidad, causada en parte por al uso de un cuadro de diálogo como interfaz, pero sobre todo por el uso de macros modificadas a modo de script, procedimiento un tanto anacrónico, pero básico en el momento en que creé la versión original del DocAp (2023).

No tengo interés en modificar el código; es más, me parece interesante mantenerlo tal y como está para que se aprecie la evolución que ha tenido este blog desde su inicio a la actualidad (2025). Tampoco descarto realizar una versión actualizada, precisamente para facilitar esa misma comparación.

De momento, después de descargarlo y tras realizar una copia de seguridad (siempre recomendable) puedes acceder al Docap desde Herramientas | Macros | Ejecutar macro y buscar la macro/script Documento que está en el directorio Standard/ModEscritura de las macros asociadas al documento-base.

domingo, 25 de mayo de 2025

Interfaz. OOo Basic.

Escritura de datos en tabla


Mientras que [en esta entrada] planteamos cómo automatizar un documento basado en texto "plano", ahora nos fijaremos en cómo acceder a un campo de una tabla. Y como ya vimos [en otro momento] podemos considerar ambos tipos de documento como las tipologías básicas desde la perspectiva de la automatización documental.

En realidad lo que voy a plantear en esta entrada es doblemente inexacto, pero consideraremos que no lo es para una mejor didáctica de la comprensión del procedimiento: ni es la única forma de abordar el trabajo con tablas (también se puede hacer mediante instrucciones basadas en "lenguaje macro"), ni se puede considerar limitado al trabajo con ellas (también es posible usarlos para localizar texto dentro de texto preescrito). Me estoy refiriendo al procedimiento de escritura de datos en campos de tablas mediante marcadores.

Efectivamente, aunque existen otras opciones y aunque su utilidad no se limita al trabajo con tablas, lo cierto es que la combinación de OOo Basic y el uso de marcadores resulta ser, en mi opinión, el procedimiento más "limpio" y funcional para solucionar el reto que supone automatizar la escritura de documentos prescriptivos o que han devenido en tales y que se caracterizan por el uso de tablas. Es en estas donde el uso de marcadores se hace aun más necesario como medio de automatización de la escritura en posiciones concretas (campos de la tabla).

El procedimiento podría ser el siguiente:
  1. Acceder al documento portador de tablas.
  2. Establecer los marcadores en las celdas y/o en las posiciones del documento (Insertar | Marcador)
  3.  Crear el módulo para escribir el script (Herramientas | Macros | Organizar Macros | Basic).
  4. Desarrollar el script.
  5. Implementar un comando en el documento para facilitar el acceso al script 
Es importante insistir, aunque parezca obvio, en que ahora trabajamos sobre un documento con el que es muy posible que hayamos trabajado muchas veces sin macros, por lo que lo conocemos perfectamente y sabemos qué tipo de datos requiere, dónde se sitúa cada uno de ellos (y más si es un documento prescriptivo) y cuánto tiempo lleva cumplimentarlo.

Dado que lo urgente se impone siempre, es también muy probable que no hayamos pensando nunca (o muy pocas veces) en automatizarlo, pero hacerlo supone, en el medio plazo y a poco que lo usemos, un ahorro de tiempo considerable. Aunque para ello normalmente hace falta desarrollar un DocAp al completo, y no simplemente lo que ahora vamos a explicar.

Dim mDatos(4) As String, mMarcas() As String
Dim oMarca As Object
Dim i As Integer

mDatos(0) = InputBox("Fecha de la actuación:")
mDatos(1) = InputBox("Nombre del Servicio de Orientación:")
mDatos(2) = InputBox("Nombre del Orientador o de la Orientadora:")
mDatos(3) = InputBox("Nota:")

mMarcas() = Array ("m0","m1","m2","m3")

For i = 0 To UBound(mMarcas())
oMarca = ThisComponent.getBookmarks().getByName(mMarcas(i))
oMarca.getAnchor.setString(mDatos(i))
Next

Este script contiene dos matrices para facilitar el posterior desarrollo del script. El contenidos de ambas queda claro en el script.

Aunque en el planteamiento más simple no sería necesario, un script mínimamente realista los requiere. Gracias a ellas, al final del script es posible automatizar eficientemente la escritura de los datos en el documento mediante un bucle (For i = 0 To UBound(mMarcas())).

El uso de la función InputBox() es la herramienta que facilita la interacción con el usuario, la cual se basa en el comando inserto en el documento (Cumplimentar datos).

Es clave para el correcto funcionamiento del script el uso de la variable de objeto oMarca, que se asocia a las funciones que nos dan acceso a los objetos marcadores insertados en el documento en el punto 2 del procedimiento. Este proceso, que se desarrolla dentro del bucle comentado antes, lo hace en dos momentos:

  • Acceso al marcador (oMarca = ThisComponent.getBookmarks().getByName(mMarcas(i)))
  • Escritura de datos (oMarca.getAnchor.setString(mDatos(i)))
Obsérvese que en cada uno de ellos empleamos una de las matrices explicadas antes.

Es importante finalizar todo este trabajo creando dos documentos: uno en formato odt, como documento-base, y otro en formato plantilla (ott) que será el que utilicemos en la práctica. El documento-base queda como reserva para posibles modificaciones o mejoras, además de para a posible pérdida del documento plantilla.

Documentos. Desde este enlace puedes descargar la versión odt. Antes de hacer nada, te recomiendo que, una vez descargado, generes una copia como plantilla (Archivo | Guardar como).

martes, 3 de diciembre de 2024

Textos. Automatización.

Documentos creados mediante script OOo Basic


Aunque no tenemos por qué prescindir totalmente del código macro, tras estar cierto tiempo recurriendo a Grabar macro para realizar ciertas tareas, reutilizando ese código desde OOo Basic, estaremos en condiciones de generar procedimientos de composición de textos basados fundamentalmente en código creado directa y mayoritariamente en este lenguaje.


Además de dar este paso, para mejorar la funcionalidad de nuestros docap puede ser necesario dar otros dos más: uno para facilitar la creación de interfaces basadas en formularios y otro para mejorar el posicionamiento de los contenidos en el documento.

Para lo primero es conveniente aprender a trabajar con dos servicios: Calc y Writer. Sobre la primera construiremos la interface y el sistema de script necesarios para dar funcionalidad a nuestro docap. Esto nos ahorra mucho trabajo ya que es relativamente sencillo implementar un formulario sobre una hoja de cálculo, combinando la utilidad de éste con la facilidad de relacionar sus controles con las celdas de la hoja. También es bastante sencillo acceder al contenido de las celdas mediante OOo Basic, con lo que Calc nos servirá además como almacén accesible de datos.

Una vez desarrolla esta fase, la segunda consiste en trasladar la información gestionado mediante el algoritmo que creemos desde el IDE al documento final. Esto supone ser capaces de crear un documento Writer o, como alternativa, acceder a uno ya creado que nos sirva de plantilla. En este segundo caso es conveniente utilizar marcadores de posición para ubicar adecuadamente la información textual.

Puedes apreciar que estamos planteando un docap complejo tanto por el uso de varios servicios como por la complejidad del conjunto de componentes que precisa. También se hace evidente al recurso a un modo de trabajo basado en la modularidad, lo que requiere cierto grado de planificación antes de iniciar la tarea.

La ventaja que deriva de tanto esfuerzo es que habremos creado un documento-aplicación muy funcional y potente con el que semi-automatizar la composición de textos complejos. Esa es la primera: la segunda es que podemos reutilizar el código y, con ciertas modificaciones, utilizarlos para crear otros docap.

Un ejemplo de este nivel de desarrollo es el [modelo C de documento de Acreditación], pero también, y con mayor nivel de complejidad, el docap que integra en una misma solución el trabajo con el informe, el dictamen y la acreditación, al que puedes acceder [desde este enlace] y encontrar también en esta sección del blog.

jueves, 2 de mayo de 2024

Interfaz. OOo Basic

Campos de opción

Considero campos de opción cuando en una tabla se presentan varios campos entre los que hay que seleccionar uno sólo como propuesta o identificador de la opción seleccionada. Tanto en el dictamen como en el informe podemos encontrar ejemplos de estos campos.


Los campos de opción de los documentos prescriptivos son reminiscencia y ejemplo del origen de estos documentos como recursos para cumplimentar manualmente o mediante el procesador de texto. En ese contexto suponen un avance respecto a la mera escritura de la opción y sirven además para acotar las posibles respuestas. Desde la perspectiva de la automatización de estos documentos suponen una complicación totalmente innecesaria, pero dado el carácter prescriptivo de los documentos-modelo, tenemos que considerarlos tal y como se presentan.

Analicemos ahora cómo se concretan estos campos en el dictamen...


... y en el informe (1)

Se puede considerar que todos ellos facilitan el uso "manual" de ambos documentos, dándoles una apariencia de formulario (más acentuada en el dictamen, que es realmente un formulario), pero otras opciones menos "vistosas" pero más funcionales podría resultar alternativas válidas. Por ejemplo, en el caso del apartado 2 del informe sería suficiente con completar la frase "Está motivado por:" con el texto que sigue a cualquiera de esas cuatro opciones. Algo similar se podría plantear para los apartados 3 y 4 del dictamen (2).

Dado que se presentan como opciones, analicemos el procedimiento de respuesta que se espera, tomando como ejemplo el apartado 3 del dictamen:
  • Dado que el dictamen es documento prescriptivo únicamente para casos de necesidades educativas especiales (NEE), el apartado se expresa mediante una tabla bastante compleja en la que se recoge la casuística NEE  tal y como está establecida normativamente por la Consejería de Educación.
  • Cada una de las categoría se asocia a una "casilla", de modo que "marcarla" (escribir una "x") implica seleccionar la opción que se considera responde a las características del alumno.
  • Se espera que el OE "marque" una y sólo una categoría.
  • Se supone también que esta forma gráfica facilita la identificación de la opción seleccionada.
De igual modo, pero se deberán cumplimentar los apartados 2 y 4 del dictamen y 2 del informe (3).

La forma de automatizar la cumplimentación de estos apartados según el comportamiento esperado podría ser la siguiente (4):

Dim oMarcador As Object
Dim sOpcion As String

sOpcion = InputBox ("Selecciona el motivo del informe" & Chr(13) &_

"A. Cambio de centro" & Chr(13) &_
"B. Cambio de etapa" & Chr(13) &_
"C. Nueva escolarización" & Chr(13) &_
"D. Revisión-Modificación","CIRCUNSTANCIAS QUE MOTIVAN EL INFORME", "A-B-C-D")

Select case sOpcion

Case "A"
oMarcador = ThisComponent.getBookmarks().getByName("mcr0")
 Case "B"
oMarcador = ThisComponent.getBookmarks().getByName("mcr1")
 Case "C"
oMarcador = ThisComponent.getBookmarks().getByName("mcr2")
 Case "D"
oMarcador = ThisComponent.getBookmarks().getByName("mcr3")

End Select

 oMarcador.getAnchor.setString("X") 

  • En este script se presupone que previamente se han establecido  cuatro marcadores en el documento, uno en cada una de las celdas (cuadrados) que anteceden a la causa y en el orden que permite hacer coincidir la opción A con el marcador mcr0, la B con mcr1, C con mcr2 y D con mcr3.
  • La variable sOpcion permite que el usuario identifique el motivo del informe según la causa que se expresa en la función InputBox()
  • El formato complejo del InputBox simula una lista de opciones, cuyo identificador (v.g. A) se expresa en el enunciado y se repite como opción de respuesta.
  • Esas opciones de respuesta se incluyen como tercer parámetro en la función InputBox(), debiendo el usuario eliminar las que no correspondan. Se espera que no se comentan errores en el manejo de estos datos (5)
  • Se utiliza el condicional múltiple Select case por ajustarse mejor a la demanda del algoritmo, pero podría usarse también una estructura If...ElseIf
  • La condicionalidad se aplica a la asignación del objeto marcador a la variable oMarcador. De este modo queda condicionado el marcador que será utilizado por la instrucción oMarcador.getAnchor.setString("X") para establecer la marca ("X"
Podemos hacer más legible el código introduciendo una variable para asignar el nombre del marcador (sMarca) de modo que el procedimiento de escritura se mantenga independiente del condicional Select case, resultando entonces el siguiente script:

Dim oMarcador As Object
Dim sOpcion As String, sMarca As String

sOpcion = InputBox ("Selecciona el motivo del informe" & Chr(13) &_

"A. Cambio de centro" & Chr(13) &_
"B. Cambio de etapa" & Chr(13) &_
"C. Nueva escolarización" & Chr(13) &_
"D. Revisión-Modificación","CIRCUNSTANCIAS QUE MOTIVAN EL INFORME", "A-B-C-D")

Select case sOpcion

Case "A"
sMarca = "mcr0"
 Case "B"
sMarca = "mcr1"
 Case "C"
sMarca= "mcr2"
 Case "D"
sMarca = "mcr3"

End Select

oMarcador = ThisComponent.getBookmarks().getByName(sMarca)
oMarcador.getAnchor.setString("X") 

Y también podemos hacer aun alguna mejora en nuestro script, pero el problema de base sigue siendo el mismo: para evitar errores dependemos únicamente de la habilidad del usuario. Si queremos evitar esta dependencia (que en este supuesto no es muy grave) deberemos reformular el script aplicando lo ya dicho en el anterior: cuando estemos ante una opción que se puede expresar en términos booleanos (V/F) la mejor solución es utilizar la función MsgBox() (6)

Para ello deberemos:
  • Crear las mismas variables que propongo en el script anterior
  • Crear una matriz con el contenidos de las opciones de respuesta que se expresan en la tabla (mOpciones(3)) y otra (mMarcadores(3)) con los identificadores de los marcadores. Asignar a ambos su contenido.
  • Crear una variable contador para usar en un bucle (i As Integer)
  • Y otra (iSelec As Integer) para capturar el valor del botón comando pulsado en el MsgBox()
  • Recorrer con un bucle For la matriz mOpciones()
  • Anidar al bucle un condicional If simple que contenga tanto la asignación del valor de la matriz mMarcadores() como la sentencia de salida del bucle en caso de que se cumpla la condición (valor 6: If iSelec = 6 Then) de la función MsgBox(). En caso contrario sigue el recorrido de las opciones (Motivos del informe)
  • Mantener las instrucciones para la escritura en el documento ("x" en el marcador que corresponda según elección del usuario)
Dim oMarcador As Object
Dim mOpciones(3) As String, mMarcadores(3) As String
Dim sMarca As String
Dim iSelec As Integer, i As Integer

mOpciones(0) = "Cambio de centro"
mOpciones(1) = "Cambio de etapa"
mOpciones(2) = "Nueva escolarización"
mOpciones(3) = "Revisión-Modificación"

mMarcadores = Array("mcr0","mcr1", "mcr2","mcr3") (7)

For i = LBound(mOpciones()) To UBound(mOpciones())

iSelec= MsgBox(mOpciones(i),4,,"CIRCUNSTANCIAS QUE MOTIVAN EL INFORME")
If iSelec = 6 Then
sMarca =  mMarcadores(i)
Exit For
End If
Next

oMarcador = ThisComponent.getBookmarks().getByName(sMarca)
oMarcador.getAnchor.setString("X") 
En este caso dejo [acceso al documento de ejemplo] para facilitarte el aprendizaje.

NOTAS

(1) También el dictamen tiene un campo de opción similar al de informe, pero he referido mostrar las tablas de los apartados 3 y 4 para no repetir ejemplos. 
 
(2) Esto permitiría tratarlos como campos simples, aunque serían necesarias instrucciones específicas que detallaran los contenidos que en la forma elegida se identifican como opciones.

(3) Si no fuera por las dificultad que conlleva la ubicación del puntero en la casilla correspondiente, y más en el contexto del conjunto del documento, se podría considerar que esta forma gráfica es una ayuda que se debería agradecer.

(4) Para variar, tomaré como ejemplo el apartado 2 del informe. Su sencillez facilita que el script sea relativamente breve, lo que redunda en una menor extensión de esta explicación. Pero el mismo procedimiento es aplicable a cualquiera de estas tablas, con las debidas modificaciones, claro está.

(5) En ese supuesto no se ofrece alternativa al error, lo cual no deja de ser optimista. Dado que se supone que el usuario es quien crea el docap o alguien directamente instruido por él, esta suposición optimista parece ser suficientemente realista.

(6) Realmente en este caso es dudoso que realmente sea mejor solución, pero interesa conocer cómo se puede plantear esta solución, ya que en otros casos, con tablas más complejas, como es el caso de la tabla 3 del dictamen, realmente puede ser mejor opción.

(7) Opto por esta solución de asignación de contenido para ejemplificarla, aunque también podría haber empleado la asignación individual, como en la matriz mOpciones(0)mMarcadores se presta al uso de Array() por la brevedad de las expresiones que contiene.

Interfaz. OOo Basic.

Campos condicionados


Otro tipo de campo frecuente en las tablas del dictamen y del informe es el que denomino aquí campo condicionado. Estos campos se caracterizan por ser dependientes de otro campo con el que se encuentra conceptualmente relacionado.


Veamos primero un ejemplo de este tipo de campos en el dictamen:


Los campos del apartado 5 del dictamen (también los del 6. Recursos de apoyo especializado) son de tipo condicionado, ya que el campo de la columna Sí/No condiciona su correspondiente de la columna Breve descripción: si contestamos en el primero deberemos incluir información en el segundo; en caso contrario el campo asociado quedará vacío (1)

También se presenta este tipo de campos en el modelo de informe, como comprobamos en la captura que sigue:


En este caso se trata de una tabla en la que se registra la presencia vs. ausencia de Medidas de Atención a la Diversidad (MAD). Su funcionamiento es igual al de la tabla anterior (dictamen): si la respuesta al ítem es , se deberá aportar información en el campo asociado de la columna 4. En caso contrario (No) su campo asociado quedará vacío.

Paso ahora a explicar el código necesario. Como ejemplo trabajaré con la tabla 5 del dictamen desarrollando una de las dos opciones, la menos eficiente, por lo que recomiendo una lectura atenta de todo lo que sigue.

Sub DictamenMod2

Dim oMarcador As Object
Dim sAjustesOrganizativosA As String, sAjustesOrganizativosB As String

sAjustesOrganizativosA = InputBox("¿Son necesarios ajustes organizativos y metodológicos?","DICTAMEN. 5. Adapciones que precisa","Sí-No")

 If sAjustesOrganizativosA= "Sí" Then

sAjustesOrganizativosB = InputBox("Describe las medidas organizativas, metodolóogicas y curriculares de acceso que consideras necesario.","DICTAMEN. 5. Adaptaciones que precisa")

ElseIf  sAjustesOrganizativosA= "Sí" Then

 sAjustesOrganizativosB = ""

Else

MsgBox("No has dado respuesta a lo demandado en el campo Ajustes organizativos del aparado 5 del DICTAMEN o la respuesta no se acepta como válida") 

   End If 

oMarcador = ThisComponent.getBookmarks().getByName("mcr0")
oMarcador.getAnchor.setString(sAjustesOrganizativosA)
oMarcador = ThisComponent.getBookmarks().getByName("mcr1")
oMarcador.getAnchor.setString(sAjustesOrganizativosB)

End Sub

  • Necesitamos crear la misma estructura que usamos en el caso de campos simples, incluyendo la creación de marcadores en el documento. 
  • Además de la variable object (oMarcador) que nos permite acceder a los objetos marcador del documento (mcr0 mcr1) Declaramos dos variables de contenido por aspecto: una para el campo condicionante (sAjustesOrganizativosA ) y otra para el condicionado (sAjustesOrganizativosB):
Dim oMarcador As Object
Dim sAjustesOrganizativosA As String, sAjustesOrganizativosB As String
  • Dar contenido a la variable condicionante se ajusta al modelo de campo básico, por lo que se le puede tratar mediante la misma fórmula...
sAjustesOrganizativosA = InputBox("¿Son necesarios ajustes organizativos y metodológicos?","DICTAMEN. 5. Adapciones que precisa","Sí-No")

... pero esto genera un posible error por omisión (respuesta vacía) o por separarse (en forma o en contenido) de las dos únicas opciones válidas (Sí/No). Para controlar estos posibles errores se pueden usar diferentes opciones y aunque estos errores sean excepcionales, su solución no es simple (2).

Otra posible formulación pasa por emplear la función MsgBox(), lo que nos obliga, a su vez una nueva variable Integer (Dim iR as Integer) a asociar a la función MsgBox(). Esta opción evita posibles errores por parte del usuario, aunque obliga también a modificar la estructura condicional, condicionando un script alternativo:

 Dim oMarcador As Object

Dim sAjustesOrganizativosA As String, sAjustesOrganizativosB As String

Dim iR As Integer

iR = MsgBox ("¿Son necesarios ajustes organizativos y metodológicos?",4,"DICTAMEN. 5. Adaptaciones que precisa")

 If iR = 6 Then

sAjustesOrganizativosA = "Sí"
sAjustesOrganizativosB = InputBox("Describe las medidas organizativas, metodolóogicas y curriculares de acceso que consideras necesario.","DICTAMEN. 5. Adapciones que precisa")

Else

 sAjustesOrganizativosA = "No"
 sAjustesOrganizativosB = ""

 End If 

Como podemos comprobar, esta segunda opción simplifica el script y lo hace más resisten a errores de uso (en realidad los reduce a cero), por lo que es preferible al primer script (3).

  • Finalmente, la escritura en el texto se mantiene en la formulación ya explicada en la entrada anterior sobre campos simples, aunque ahora son necesarias dos fases de escritura, que aquí se resuelven meramente por repetición del mismo procedimiento (4):

oMarcador = ThisComponent.getBookmarks().getByName("mcr0")
oMarcador.getAnchor.setString(sAjustesOrganizativosA)
oMarcador = ThisComponent.getBookmarks().getByName("mcr1")
oMarcador.getAnchor.setString(sAjustesOrganizativosB)

NOTAS

(1) Este segundo campo también sería condicionado si el contenido a introducir fuera uno u otro según la respuesta dada al campo condicionante. El ejemplo que presento aquí es la formulación más simple de este tipo de campos, pero también el único que se presenta en el informe y en el dictamen.

(2) En este caso se incluye en InputBox() las dos opciones de respuesta como tercer parámetro de la función; también se incluye la opción Else en el condicional If con un mensaje de advertencia. En el modelo propuesto podría añadirse a continuación de Else volver a interrogar sobre la variable sAjustesOrganizativosA y repetir el análisis que realiza el condicional, dando así una segunda opción. Como se puede ver, la solución no es sencilla, aunque en realidad es posible que estas circunstancias adversas se produzcan excepcionalmente.

(3) En principio, cuando nos encontremos con un campo de dos opciones siempre es preferible utilizar la función MsgBox() en lugar de InputBox(); no ahorraremos posibles errores y obtendremos un código más limpio y funcional. MsgBox() funciona en realidad como Boolean, pero su configuración de respuesta en OOo Basic nos obliga a asociarla a una variable numérica, ya que sus comandos (aquí el parámetro 4, que muestra las opciones - No) devuelven respectivamente los valores 6 y 7.

(4) Cuando el número de variables y marcadores a usar se multiplique será necesario trabajar con una matriz para agrupar las variables y un bucle para el proceso de escritura. Para los objetivos de esta entrada ambos resultan innecesarios. 

miércoles, 1 de mayo de 2024

Interfaz. OOo Basic

Tablas. Campos simples.

Por aclarar: en estas entradas entiendo por documentos prescriptivos aquellos que elabora la Consejería de Educación para uso obligatorio de los SEO. El documento que impone como tal la Consejería cumple la función de documento-modelo (tanto en forma como en formato) y es de uso obligado. No obstante es posible realizar un doble proceso de conversión (Word->Writer->Word) desde LO-Writer, lo que, entremedias, nos permite automatizar (semi-automatizar cuanto menos) su cumplimentación. Aquí es donde entre OOo Basic.


Tanto el dictamen de escolarización como el informe psicopedagógico son dos de esos documentos prescriptivos,  yo diría que los principales, tanto por su uso (muy frecuente) como por su función (fundamental en la intervención de los SEO). 

Además añaden a la complejidad que conlleva la evaluación psicopedagógica el tener que ajustarse en lo formal al propio documento y al formato que impone. Sería de agradecer que que la Consejería de Educación aportara recursos que facilitaran la cumplimentación de estos documentos, pero no parece que esté en su agenda de prioridades; así que o nos ponemos nosotros manos a la obra o podemos esperar sentados. La IA no tiene mucho que aportar al respecto, al menos de momento (después a lo peor hasta nos arrepentimos de que sí, quien sabe...)

Quejas y suspiros a parte, y salvando que la principal dificultad es la complejidad que supone la evaluación psicopedagógica, sí podemos hacer mucho por simplificar y (semi)automatizar el trabajo, o parte significativa de él. Este es el propósito de esta serie de entradas que inicio con esta, y de otra que publico en [Recursos] (1).

Aquí, en [Usos]me ha parecido conveniente empezar por el trabajo con las tablas, ya que son componentes fundamentales de los documentos. El propio hecho de formar parte de estos documentos "impuestos" por la Consejería nos obliga, a su vez, a desarrollar formas específicas que trabajo, lo que tiene su parte positiva: obligatoriamente también agudiza el ingenio.

Partiré de los modelos de informe y dictamen de 2024 (los últimos publicados, en estos momentos) e iré analizando cada elemento (ítem) que se puede identificar en ellos, en función de la forma en que se deben (y pueden) cumplimentar.

Inicio por el modelo de dictamen por ser el de mayor complejidad en cuanto al uso y tipología de tablas y sólo realizaré propuestas concretas para el documento Informe en caso necesario, esto es: cuando lo visto en el dictamen no sea adecuado.

Lo primero que tienes que tener es el [dictamen-modelo] de la Consejería.

Y para que esta entrada no sea de mera presentación, voy a proponer una forma de trabajar con aquellos campos (ítem) que son más frecuentes y a la vez más sencillos: los llamaremos Item0 y están presentes (y predominan) en un número importante de las tablas que componen el dictamen (y el informe) (2).


A modo de ejemplo, en éstas que son las dos primeras tablas del dictamen (Tabla1 y Tabla2, diríamos) Item1 puede ser identificado en 6 de los 7 campos que contienen, aunque es cierto que algunos de ellos se pueden plantear de forma más compleja (3)

Cierto es, además, que si trabajáramos "manualmente" ambas tablas presentan una diferencia importante: mientras que en la primer es posible realizar los desplazamientos de celda mediante el tabulador, en la segunda nos vemos obligados a posicionarnos "manualmente" al final del identificador del contenido del campo (v.g. NIE). Pero como vamos a trabajar con OOo Basic, si elegimos el  procedimiento adecuado esa diferencia deja de existir.

Se trata de campos que se pueden cumplimentar partiendo del uso de marcadores en el documento (de ello ya hablé en [esta entrada]), estrategia de trabajo de la que hablaré a continuación. Además, los marcadores permiten una forma de trabajo lineal que facilita la combinación de matrices y bucles para el desarrollo del docap (sobre ello hablo en [esta entrada]). Describo a continuación el proceso a seguir:
  • En el documento-modelo (dictamen convertido a formato Writer) me posiciono en el punto en el que deseo introducir el dato, por ejemplo, Tabla2, tras Nombre y apellidos (4)
  • Sitúo el marcador (Insertar | Marcador) que denomino, por ejemplo, mcr4.
  • Dando por creado Module1 desde el IDE con lo que esto supone, creo el script (5)
    • Declaro las dos variables necesarias para el funcionamiento del script y los procedimientos de asignación de datos. En el caso de la variable sAlumno utilizando la función InputBox()
El script resultante es el siguiente. Observa que no hacemos referencia en ningún momento a la tabla con la que vamos a trabajar. Usando otros procedimientos (basados en macros, por ejemplo) sí sería necesario, pero el uso de marcadores simplifica mucho la ubicación de texto en cualquier posición del documento susceptible de ser marcado (o lo que es lo mismo, identificado con un marcador):

Sub DictamenMod1

Dim oMarcador As Object
Dim sAlumno As String

sAlumno = InputBox("Nombre y apellidos del alumno/a","DICTAMEN")

oMarcador = ThisComponent.getBookmarks().getByName("mcr4")
oMarcador.getAnchor.setString(sAlumno)

End Sub

  • Mientras que la primera variable (oMarcador) es de tipo objeto, la segunda (sAlumno) es de tipo string. Podría ser de cualquier otro tipo (Integer, por ejemplo), pero el trabajo sobre un texto hace que sea tratada como cadena de texto en lo que al proceso de escritura se refiere.
  • La instrucción sAlumno = InputBox("Nombre y apellidos del alumno/a","DICTAMEN") es de sobra conocida, por lo que no necesita más explicación: como sabemos, permite dotar de contenido a la variable de forma interactiva.
  • Mediante la instrucción de asignación...
oMarcador = ThisComponent.getBookmarks().getByName("mcr4")

 ... estamos accediendo mediante OOo Basic al objeto documento activo (ThisComponent), a la colección de objetos marcador (.getBookmarks()) y al marcador identificado por su nombre (.getByName("mcr4")). Para ello, como ya vimos, es necesario que tal objeto haya sido creado previamente en el documento.

  • Finalmente, la instrucción  oMarcador.getAnchor.setString(sAlumno) asigna el texto referenciado en la variable sAlumno (el que previamente haya introducido el usuario mediante InputBox()) en el objeto referenciado por la variable oMarcador, haciendo uso del método .getAnchor y del sub-método o función .setString() asociado al anterior (6)

La repetición de este mismo procedimiento, y su racionalización y simplificación mediante el uso de matrices y bucles, es la base del procedimiento de creación de docap de automatización del dictamen. 

Tendremos ocasión de describir este procedimiento, como ya prometí antes, pero por ahora me limito a proponerte que amplíes este procedimiento a los campos de las tablas del dictamen que consideres susceptibles de ser tratadas de este modo. Unos cuantos campos serán suficientes, ya que la mayoría se podrían resolver de este modo (no todos, como también veremos), pero en algunos de ellos existen alternativas más complejas pero también más funcionales. 

NOTAS

(1) Posiblemente también en Procedimientos y, de ser posible, en Recursos, aunque dependerá de cómo de desarrolle el proceso que ahora inicio.
(2) A Item1 se ajustan la mayoría (en algunas la totalidad) de los campos de 7 de las 19 tablas de que consta el documento. En concreto (y por orden de presentación) las siguientes: tabla 1, tabla 2, tabla 3, tabla 4 y tabla 5, tabla 12 y tabla 18. En este cómputo he incluido las cinco tablas del anexo 1 que corresponde cumplimentar al Equipo Regional (ER).
(3) Más compleja (veremos en qué consiste en otra entrada) y también más simple en algunos casos: Servicios de Orientación y Orientador/a de la Tabla1 bien pueden considerarse como constantes a nivel individual (de cada orientador/a) y figurar como datos del modelo personal de dictamen (y de informe).
(4) Tal vez no sea el campo-tipo ideal, ya que podemos trabajar con otro procedimiento (como veremos en un próxima entrada), pero lo cierto es que también con éste, que es el más simple. Tanto que, incluso incluyendo el uso de marcadores, se acerca mucho en funcionalidad a la que tiene elaborar el documento directamente desde Writer. En realidad esto no es del todo cierto, ya que incluso empleando este procedimiento, crear un docap para automatizar la elaboración del dictamen supone un ahorro de tiempo considerable, mayor cuantos más dictámenes tengamos que hacer.
(5) Estos pasos que aquí se muestran simplificados requieren de sus propios procedimientos. No explicaré cómo trabajar con el IDE para crear las condiciones que requiere la creación de un script por ser un procedimiento sobradamente conocido, ni el requerido para implementar marcadores en un texto puesto que ya traté ese tema en [esta entrada] cuya lectura recomiendo para mayor detalle. El desarrollo del script sí requiere explicación.
(6) Estamos utilizando terminología propia del paradigma de Programación Orientada a Objetos, que es la que se utiliza en Libre Office. Aunque el lenguaje OOo Basic no nos permite crear clases ni objetos, sí trabaja con ellos y con sus métodos y atributos. De ahí que cuente con ese tipo especial de variable de tipo objeto, uno de cuyos ejemplos es nuestra variable oMarcador. De hecho, el trabajo con objetos es fundamental para el desarrollo de script en OOo Basic. Sin ello no podríamos acceder a los documentos ni a los "objetos" que contienen. Tampoco podríamos crear macros.