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

martes, 3 de junio de 2025

Textos. OOo Basic

Matrices como recurso para generar datos (output)


También podemos utilizar matrices asociadas a bucles como recurso para generar datos de salida. En realidad no es un procedimiento muy diferente al que empleamos para [facilitar el input] como podremos ver en esta entrada.



En este caso tenemos que dar por supuesto que la matriz de datos cuenta con todos los necesarios, sin entrar en detalles sobre el modo en que llegamos a esta situación (1). Suponemos también que nos enfrentamos a la tarea de automatizar la generación del texto de salida (output) (2) siendo el script el que sigue:

Dim mDatos(7) As String, vTexto As String
Dim i As Integer

mDatos(0) = "Con fecha"
mDatos(1) = "12 de mayo de 2024"
mDatos(2) = "en el CP Caudalia"
mDatos(3) = "tiene lugar la reunión de tutoría"
mDatos(4) = "con la madre"
mDatos(5) = "del alumno"
mDatos(6) = "Carlos López"

Para reconfigurar los segmentos textuales contenidos en la matriz en un único string (3), usamos el bucle For como sigue

vTexto = ""

For i = 0 To UBound(mDatos())
vTexto = vTexto & " " & mDatos(i)
Next

MsgBox (vTexto)

Quede aclarado que MsgBox() suple aquí el procedimiento de escritura del texto resultante en el documento (output), simplificación que me permito por motivos didácticos. Pero lo importante es explicar el funcionamiento del bucle.
  • Recorremos la matriz mDatos() desde su inicio (i = 0) hasta su final (UBound(mDatos()) mediante el bucle For (For i = 0 To UBound(mDatos()))...
  • Asignando a la variable vTexto el contenido de cada uno de los elementos de la matriz (vTexto = vTexto & " " & mDatos(i))...
  • Instrucción en la que quiero incidir en dos detalles:
    • La recursividad: en el nuevo ciclo, sobre la variable vTexto escribimos el contenido de la propia variable en el ciclo precedente (vTexto = vTexto & ...)
    • El añadido de una cadena vacía como separador entre segmentos (& " " &), que no sería necesaria si cada segmento ya la incluyera como elemento final de su string, solución que no recomiendo.
El resultado presenta una pequeña "deficiencia": el string resultante se inicia con un espacio en blanco debido al modo en que se construye la secuencia. Para la mayoría de los usos del procedimiento esto puede resultar irrelevante, así que la solución anterior puede ser más que suficiente. No obstante si nos interesa eliminar ese espacio al inicio de la cadena podremos utilizar la alternativa que sigue...

For i = 0 To UBound(mDatos())
If i = 0 Then
vTexto = mDatos(i)
Else
vTexto = vTexto & " " & mDatos(i)
End If
Next

... en la que mediante un condicional diferenciamos el procedimiento al inicio del ciclo (If i = 0 Then -> vTexto = mDatos(i)) en el que asignamos directamente a vTexto el contenido del primer elemento de la matriz (i = 0) sin el ahora innecesario espacio en blanco, de las siguientes fases del mismo, en las que mantenemos el procedimiento ya explicado (Else -> vTexto = vTexto & " " & mDatos(i)).

NOTAS

(1) Aunque es fácil plantearlo de este modo, en realidad se trata de una cuestión que está cargada de interrogantes, pero ahora simplemente no toca plantearlos.
(2) Supongamos que es parte de la automatización de la composición de un documento
(3) Que reconstruimos sobre la variable vTexto, por lo que inicialmente asignamos a ésta el contenido cadena vacía (vTexto = "") como forma de clarificar el funcionamiento esperado.

Textos. OOo Basic

Matrices como recurso para la entrada de datos

Con ser muy importante la mejora  que permite el [cambio de matrices por variables] para el manejo del código, no es la única ventaja que aporta, ya que esta sustitución facilita el acceso a las posibilidades que supone el uso de estructuras de iteración. En esta entrada concretaremos esa ventaja en la dase input o de solicitud de datos al usuario.



Ya hemos explicado que el uso de InputBox() es probablemente la forma más simple de resolver el problema de cómo aportar al script los datos que se necesitan para cumplir su objetivo, sea éste el que sea (1)...

vAlNom = InputBox("Nombre del alumno o alumna: ")

... pero cuando tenemos que repetir esto 20 o treinta veces esta sencillez se convierte en molesta. Aquí caben dos alternativas: crear una función o emplear un bucle.

En realidad, lo de la función no deja de ser simplificar el código, pero no evita tener que repetir la llamada a la función tantas veces como variables tengamos... o cuantos elementos tenga la matriz. Sin embargo, la segunda alternativa, el uso de un bucle, sí resuelve el tema, tanto si (además) utilizamos una función como si no. Claro que para ello es necesario utilizar matrices en lugar de variables (2).

Veamos un ejemplo:

  • Tenemos una matriz con 10 elementos -> Dim mDatos(10) As String
  • Declaramos además una variable contador -> Dim i As Integer
  • Mediante la estructura For recorremos la matriz aplicando la función InputBox() a cada elemento:
For i = 0 To UBound(mDatos())

mDatos(i) = InputBox()

Next

De este modo, y de forma sencilla, el usuario introduce los datos en cada uno de los diez elementos de la matriz sin que sea necesario repetir diez veces el mismo proceso. No obstante, tenemos un problema para el que existen dos soluciones: el usuario no sabe qué información se le solicita, así que no sabe qué introducir, ya que le falta información aclaratorio en el InputBox(), la cual sí estaba disponible en el formato anterior (InputBox("Nombre del alumno o alumna: ")).

Este problema no se resuelve en el ciclo del mismo modo que fuera de él, ya que no se solicita 10 veces (por ejemplo) el mismo dato. Debemos buscar otra solución, porque no podemos esperar que se resuelva solo recurriendo a que el usuario es conocedor del documento, ni incluso que sea la misma persona que hizo el script. 

La solución más sencilla es crear, aportar (y tener a mano en el momento adecuado) un documento informativo que asocie cada elemento de la matriz con su contenido.

Ítem 0 -> Nombre del alumno 
Ítem 2 -> Apellidos del alumno 

... En este caso sería necesaria una pequeña modificación en el InputBox() (InputBox("Ítem " & i)o similar).

La segunda opción es más costosa pero más apropiada, además de posiblemente también más funcional (3): crear una segunda matriz tipo string cuyos elementos sean sencillas cadenas de texto que informan sobre el contenido de cada elemento de la matriz de datos (4)...

Dim mConten() As String
mConten = Array("Alumno. Nombre","Alumno. Apellidos","Alumno. Fecha de nacimiento"...)

... siendo necesario modificar también el InputBox() (InputBox(mConten(i))

NOTAS

(1) Por ejemplo, la automatización de la escritura de un texto. La forma más sencilla de disponer de un dato tan simple como necesario como es el nombre del alumno es preguntarle al usuario que trabaja sobre el documento que hemos automatizado.
(2) En realidad podemos utilizar variables (y no matrices), pero necesitamos que el nombre de las matrices se asemeje al formato de los elementos de la matriz, así que no deja de ser un sucedáneo del uso de matrices.
(3) Evitamos el riesgo de que se pierda el documento que contiene el listado anterior.
(4) Aun en este caso el código es más limpio y sencillo que utilizando reiteradamente la forma primitiva de la instrucción de input

Textos. OOo Basic

Variables vs. matrices


A fuerza de necesitar conjuntos cada vez más grandes de variables en proyectos de automatización de textos, el uso alternativo de matrices ha supuesto mejoras significativas en el manejo y en la creación del script, aunque este cambio también presenta inconvenientes. Una ventaja asociada al uso de matrices es la posibilidad de trabajar con bucles.



Primero explicaré qué supone modificar la asignación de contenido a variables vs. matrices. Para ello un ejemplo sencillo es la creación de un sistema de asignación de datos mediante InputBox() (1) cuando el número de variables es ya un tanto elevado, por ejemplo cuando alcanzamos la veintena de datos que solicitamos al usuario (2).

En realidad es indiferente que esas veinte o más variables requieran todas ellas de su correspondiente interfaz, o que parte de ellas se cumplimenten "automáticamente" mediante un procedimiento de condicionalidad referenciada (3)...

If vNombreSex = "H" Then
vTratam1 = "niño"
Else 
vTratam1 = "niña"

... el hecho es que ya la simple declaración de veinte variables supone realizar un trabajo innecesario, además de complicar el manejo de este código. Por suerte tenemos una fácil solución a mano: utilizar matrices.

El resultado es un código mucho más limpio y manejable (4), aunque debemos saber que tiene un coste: perdemos en inteligibilidad del código. Usando variables, el nombre de cada una de ellas puede ser suficientemente esclarecedor respecto al dato que contiene (5), siendo ésta una recomendación que se reitera en los manuales de programación; pero cuando usamos una matriz esa posibilidad se pierde en cierta medida. 

Entiendo que en este caso puede ser muy conveniente (6) crear una documentación anexa al script que contenga una tabla en la que se indique la relación entre cada elemento de la matriz con el contenido que referencia

NOTAS

(1) Por poner un ejemplo muy socorrido y usado por su sencillez de implementación. Es dudoso que cuando el número de variables-input a manejar sea elevado, la solución interfaz sea InputBox(). En estos casos, posiblemente lo mejor y más sencillo sea trabajar con un formulario sobre una hoja de cálculo con funciones de gestor, posiblemente una solución con categoría de [docap complejo].
(2) Esa es una cantidad relativamente moderada de variables, ya que en documentos complejos (vg. dictamen de escolarización) las variables necesarias la superan con mucho. En un [ejemplo reciente], la automatización de este documento ha supuesto trabajar con un total de 63 campos/variables, y eso que sólo se trabaja con el núcleo principal del documento y no con sus dos anexos.
(3) Este es el caso de las variables que contienen datos relativos a la expresión de la concordancia gramatical de género o número. En los ejemplos de documentos con los que trabajamos, estas variables expresan normalmente la concordancia de género y se asocian al género gramatical del sujeto, muy frecuentemente a la dicotomía alumno vs. alumna.
(4) Cierto que más cercano a infinito conforme mayor sea el número de variables. LO que debemos sopesar es si interesa trabajar con una o con varias matrices, atendiendo al tipo de datos. La solución de matriz tipo variant no es ni siempre ni necesariamente la mejor opción, aunque nos permite concentrar en una única matriz los distintos tipos de datos posibles.
(5) Al dato e incluso al tipo: es posible leer Dim txtNomAl As String como variable texto (string) que contiene el nombre del alumno.
(6) También aquí, más conveniente cuando mayor sea el tamaño de la matriz. Esta tabla permitirá a otro profesional que desee trabajar con el script una mejor comprensión de su funcionamiento, evitándole una búsqueda de referencias que a veces se vuelve muy complicada.

lunes, 26 de mayo de 2025

Documentos. Dictamen.

DocAp complejo. Dictamen de escolarización


Lo que voy a plantear en esta entrada ya ha tenido otras soluciones en formato [DocAp simple] e incluso como [DocAp complejo] basado en Base, Calc y Writer implicando tres documentos: Informe, Dictamen y Acreditación. Ahora busco desarrollar un DocAp complejo basado en dos servicios (Calc como gestor y base de datos) y Writer como soporte del documento-modelo.


Respecto al objeto de automatización, aunque no es el único documento prescriptivo basado en tablas, el dictamen de escolarización es posiblemente el que mejor representa esta tipología documental. Es además suficientemente extenso y complejo como para que su automatización suponga un ahorro real de tiempo de trabajo, a la vez que resulta un reto y un modelo para aplicar en la automatización de otros documentos similares.

El ahorro de tiempo es consecuencia de que su cumplimentación requiere un tiempo significativo de trabajo, más aun si tenemos en cuenta que es un documento de uso relativamente frecuente a lo largo del curso. Además, como documento prescriptivo que es, aunque se producen o pueden producir variaciones de curso a curso, éstas no suelen ser ni muchas ni importantes, por lo que es posible rentabilizar el esfuerzo que implica crear un DocAp.

En cuanto al documento en sí, cabe decir que en realidad se trata de tres documentos diferenciados que pueden ser tratados de forma independiente: 
  • un cuerpo principal, responsabilidad exclusiva del OE del SEO, y dos anexos. 
  • El primero de estos anexos es responsabilidad del ER y resulta prescriptivo cuando se cumplen determinadas condiciones que implican la participación obligada del ER; en caso contrario este anexo no forma parte del DE. 
  • El segundo anexo es obligatorio en cualquier caso y requiere la participación de la familia o de los representantes legales del menor y recibe un tratamiento diferenciado en cuanto a su gestión.
Esta estructura me permite abordar ahora únicamente la automatización del cuerpo principal del dictamen, dejando los dos anexos para otro momento.

El desarrollo de este DocAp requiere que nos posicionemos respecto al modo de empleo del documento, cuestión esta que presenta mayores dificultades de las que aparenta, pero que, entre ellas, nos permite también un planteamiento simplificador (no alejado de la realidad) en la que el dictamen se cumplimenta en su totalidad por parte del OE tras finalizar la elaboración del informe. Esto permite manejar el documento como un todo y como una única actuación, siendo esta la perspectiva que adopto a la hora de plantear la sucesión de procesos en el manejo del DocAp:
  1. El OE cumplimenta los datos a incluir en el documento usando un formulario como recurso de entrada de datos soportado sobre una hoja de cálculo (Calc)
  2. El script accede a estos datos y los traslada a la plantilla del dictamen-modelo (Writer) y posiciona la información mediante el uso de los marcadores previamente establecidos en ese soporte.
  3. El script genera un nuevo registro en la base de datos (construida sobre Calc)
Esta secuencia debería ser diferente en caso de idear un procedimiento distinto, siendo esto posible gracias a lo que implica el tratamiento modular del procedimiento, lo que ahora se concreta como DocAp complejo.

Documentos. Puedes descargar el [gestor-Calc] y el [documento-modelo] desde sus respectivos enlaces. debes modificar la ruta para que el script acceda correctamente al dictamen...
  • "C:/Users/alons/Desktop/Dictamen24Modelo.ott"
... y no te olvides de generar una plantilla a partir del documento-modelo dándole este nombre...
  • Dictamen24Modelo.ott
... o modificando también el nombre del documento en la ruta que crees.

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

Documentos. Informe

Informe. Carátula sobre DocAp simple.


Con independencia de la complejidad del documento a automatizar, podemos optar por procedimientos diferentes, incluyendo el continuum categorial en función del nivel de complejidad de la propuesta técnica. En esta entrada vamos a trabajar con las carátulas del informe psicopedagógico, lo que supone tratar un caso de automatización de un documento complejo, aunque limitando su automatización a su componente tabular del documento (por lo que entra dentro de esta sección), lo que supone que sólo será automatizado parcialmente, y mediante un procedimiento relativamente simple (un DocAp simple, esto es, que no implica recurrir a más de un servicio LO; en este caso Writer)


Esta estrategia de automatización comparte la simplicidad, pero también la complejidad del procedimiento simple visto [en esta entrada], que la que podemos considerarla expansión. Por ello presenta la ventaja de simplicidad que permite que sea generalizable a documentos de similar o menor nivel de dificultad, especialmente si el uso del documento no va a ser frecuente o va a estar limitado temporalmente.

Se trabaja directamente sobre el documento-modelo que tras la creación del DocAp pasará a ser usado como plantilla y no requiere utilizar otro servicio más que Writer.

Aunque no se da por sentado, resulta conveniente que el usuario final (se espera que la misma persona que crea el DocAp) conozca y acceda al IDE para establecer en él aquellos valores de las variables que en realidad, para esa persona, van a funcionar como constantes. De hecho, aunque no se da en el DocAp que aquí sirve de modelo, es posible eliminar de esas variables  el uso de la función InputBox() y hacer una asignación directa de datos, evitando o saltando esta parte en el funcionamiento visible del script.

Otros datos que no corresponde sean tratados como constantes, sí pueden ser expresados mediante ejemplos. Esto es lo que aquí se hace consiguiendo ejemplificando qué se espera del usuario y, en algún caso, incluso ofreciendo una opción que sólo necesita aceptar como respuesta.

Este DocAp no pretende disimular que sólo es capaz de automatizar la escritura de datos en las tablas, dejando el resto del documento para se tratado "manualmente" por el usuario, pero ya sólo este limitado resultado supone un ahorro de trabajo: el que conlleva el desplazamiento "a mano" por los diferentes campos de las tablas y por las diferentes tablas del documento. No obstante, no es la única solución disponible y, sin salirse del ámbito procedimental de los DocAp, es posible generar respuestas de mayor rendimiento. Aun así, repito, el procedimiento que aquí se presenta puede ser suficiente en determinados casos. Si así lo considerar, sólo necesitas copiar el código del IDE, trasladarlo al módulo del nuevo documento al que lo quieras aplicar (tras crear los marcadores correspondientes, respetando el identificador que se usa en este documento, eso sí) y realizar las adaptaciones de contenido que sea pertinente.

Por eso te expongo y explico a continuación el código OOo Basic de este DocAp, el cual, como verás, consta de un script largo y una subrutina corta:

Sub Main

'Variables y matriz

Dim Conta As Integer
Dim sVar As String
Dim mDatos (33) As String
Dim AlNombre As String, AlApellidos As String
Dim iMAD_RepOrd As Integer, iMAD_PermanExt As Integer, iMAD_MedOrd As Integer, iMAD_MedExt As Integer,iMAD_Otras As Integer
Dim sInfoMotivacion As String

'Datos de identificación del informe

mDatos(0) = InputBox("SEO","DATOS DEL INFORME","EOE de Oviedo")
mDatos(1) = InputBox("Fecha de presentación del informe","DATOS DEL INFORME","12/03/2024")
mDatos(2) = InputBox("Orientador/a responsable del informe","DATOS DEL INFORME","Javier Alonso")

'Datos personales del alumno

AlNombre = InputBox("Nombre del alumno/a","DATOS DEL ALUMNADO","Jaime")
AlApellidos = InputBox("Apellidos de " & AlNombre,"DATOS DE" & AlNombre,"López Pérez")
mDatos(3) = InputBox("NIE de " & AlNombre,"DATOS DE " & AlNombre & " " & AlApellidos,"11122233")
mDatos(4) = AlNombre & " " & AlApellidos
mDatos(5) = InputBox("Fecha de nacimiento de " & AlNOmbre,"DATOS DE "  & AlNombre & " " & AlApellidos,"12/03/2018")
mDatos(6) = InputBox("Edad actual de " & AlNOmbre,"DATOS DE "&  AlNombre & " " & AlApellidos,"7:03 años")

'Datos de escolarización actual

mDatos(7) = InputBox("Centro actual de escolarización de " & AlNombre,"DATOS DE ESCOLARIZACIÓN DE "& AlNombre & " " & AlApellidos,"CP Auleriano Buendía")
mDatos(8) = InputBox("Curso actual de " & AlNombre,"DATOS DE ESCOLARIZACIÓN DE "& AlNombre & " " & AlApellidos,"2º")
mDatos(9) = InputBox("Etapa educativa","DATOS DE ESCOLARIZACIÓN DE "& AlNombre & " " & AlApellidos,"E. Primaria")

'Datos familiares

mDatos(10) = InputBox ("Nombre y apellidos de la madre de" & AlNombre,"Datos familiares de "& AlNombre & " " & AlApellidos,"Maria Soledad Pérez Ramírez")
mDatos(11) = InputBox ("DNI/NIF de la madre","Datos familiares de "& AlNombre & " " & AlApellidos,"10456765J")
mDatos(12) = InputBox ("Nombre y apellidos del padre de" & AlNombre,"Datos familiares de "& AlNombre & " " & AlApellidos,"Domingo López Aramendi")
mDatos(13) = InputBox ("DNI/NIF del padre","Datos familiares de "& AlNombre & " " & AlApellidos,"12345676M")
mDatos(14) = InputBox("Domicilio actual de "& AlNombre,"Datos familiares de "& AlNombre & " " & AlApellidos,"Adv de Portugal 23 - 3º D")
mDatos(15) = InputBox("Código postal del domicilio","Datos familiares de "& AlNombre & " " & AlApellidos,"33011")
mDatos(16) = InputBox("Localidad de residencia","Datos familiares de "& AlNombre & " " & AlApellidos,"Oviedo")
mDatos(17) = InputBox("Teléfono de contacto para notificación","Datos familiares de "& AlNombre & " " & AlApellidos,"654 765 567")

'Escolarización previa

mDatos(18) = InputBox("Centro anteriores (en caso de ser el actual mantener lo propuesto","Escolarización y medidas educativas previas de "& AlNombre & " " & AlApellidos, mDatos(7) & " desde los inicios de la escolarización.")

'MAD previas

iMAD_RepOrd = MsgBox("¿Ha realizado " &AlNombre & " repetición ordinaria de curso a lo largo de su escolarización?",4,"Medidas previas de respuesta educativa")
If iMAD_RepOrd = 6 Then
mDatos(19) = "Sí"
mDatos(20) = InputBox("¿En qué curso o curso realizó repetición ordinaria?","MAD previas")
Else
mDatos(19) = "No"
End If

iMAD_PermanExt = MsgBox("¿Ha realizado " &AlNombre & " repetición extraordinaria a lo largo de su escolarización?",4,"Medidas previas de respuesta educativa")
If iMAD_PermanExt = 6 Then
mDatos(21) = "Sí"
mDatos(22) = InputBox("¿En qué curso o curso realizó permanencia extraordinaria?","MAD previas")
Else
mDatos(21) = "No"
End If

iMAD_MedOrd = MsgBox("¿Se han aplicado " &AlNombre & " medidas ordinarias en los cursos anteriores (ajustes organizativos y/o adaptaciones no significativas)?",4,"Medidas previas de respuesta educativa")
If iMAD_MedOrd = 6 Then
mDatos(23) = "Sí"
mDatos(24) = InputBox ("¿Qué medidas ordinarias se aplicarón?","MAD previas","Ajuste organizativos,Ajustes curriculares de acceso y Adaptaciones metodológicas")
Else
mDatos(23) = "No"
End If

iMAD_MedExt = MsgBox("¿Y medidas extraordinarias (amplicación, flexibilización,exención o ACS)?",4,"Medidas previas de respuesta educativa")
If iMAD_MedExt = 6 Then
mDatos(25) = "Sí"
mDatos(26) = InputBox("¿Qué medidas extraordinarias se han aplicado? (en caso de ACS especificar área(s)","MAD previas","Amplicación, flexibilizazación, exención,ACS en el área de...")
Else
mDatos(25) = "No"
End If

iMAD_Otras = MsgBox("Ha tenido " &AlNombre & " medidas educativas específicas (refuerzo educativo ordinario, apoyos especializados...)?",4,"Medidas previas de respuesta educativa")
If iMAD_Otras = 6 Then
mDatos(27) = "Sí"
mDatos(28) = InputBox("Indica las medidas adoptadas. En caso de apoyos especializados indicar cuáles","MAD previas")
Else
mDatos(27) = "No"
End If

'Circunstancias que motivan el informe

sInfoMotivacion= InputBox("Selecciona el motivo por el que se emite este informe" & Chr(13) &_
"A - Por cambio de centro" & Chr(13) &_
"B - Por nueva escolarización"  & Chr(13) &_
"C - Por cambio de etapa"  & Chr(13) &_
"D - Para revisión o modificación","Motivación del Informe","A-B-C-D")
If sInfoMotivacion="A" Then
mDatos(29) = "X"
ElseIf sInfoMotivacion="B" Then
mDatos(30) = "X"
ElseIf sInfoMotivacion="C" Then
mDatos(31) = "X"
ElseIf sInfoMotivacion="D" Then
mDatos(32) = "X"
End If

mDatos(33) = InputBox("Puedes basarte en el modelo de respuesta que se propone o indicar las que consideres pertinentes.","OBSERVACIONES","Este informe responde a la demanda formulada con fecha 10/02/2024 por la Dirección del centro a petición del Tutor del alumno a fin de ajustar la respuesta educativa a sus actuales necesidades específicas de apoyo.")

'Escritura de contenidos

For Conta = 0 To 33:
sVar = mDatos(Conta)
Posicionamiento(sVar,Conta)
Next

End Sub
 
La mayor parte del script está ocupada por el tratamiento de los elementos de la matriz de datos mDatos(), que en la mayoría de los casos se resuelve con el uso repetido de la función InputBox(), aunque en otros se requieren procedimientos algo más complejos que implican el uso de condicionales. Esto se observa en el bloque MAD previas y Circunstancias...

Aunque ni por extensión ni por complejidad lo parezca, resulta de vital importancia comprender el interés que tiene el bucle con el que finaliza el script, (For Conta = 0 To 33:) que implica llamar a la subrutina que facilita la escritura de los datos en las posiciones que indican los marcadores.

Sub Posicionamiento (sDatos As String,i As Integer)

Dim oMarca As Object

oMarca = ThisComponent.getBookmarks().getByName("m"+CStr(i))
oMarca.getAnchor.setString(sDatos)

End Sub

Esta subrutina, que se puede construir de otra forma (por ejemplo incluyendo en ella el bucle con el que finaliza el script), recibe dos parámetros: el contenido del elemento de la matriz de datos y el valor de una variable contador. Con ellos ejecuta la acción de acceder al objeto marcador (Dim oMarca As Object) referenciado por el valor del contador (oMarca = ThisComponent.getBookmarks().getByName("m"+CStr(i))) y ubicar en esa posición el contenido de la variable (oMarca.getAnchor.setString(sDatos)) que, a su vez el bucle For que lo llama ha pasado desde el elemento de la matriz de datos (sVar = mDatos(Conta)).

Documento. Desde este enlace puedes descargar el DocAp. Te sugiero creer inmediatamente una versión plantilla con la que trabajar; al menos una copia de seguridad para evitar problemas con los marcadores, que ya sabes son muy sensibles y es fácil perderlos.

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).

sábado, 24 de mayo de 2025

Textos. OOo Basic

Automatizar la escritura de una frase


El procedimiento más básico de automatización de la escritura de o en un texto es la escritura de una frase mediante la combinación de texto que vamos a llamar fijo y texto variable mediante el uso de la función de concatenación.


En primer lugar debemos contextualizar este procedimiento en el marco del soporte sobre el que se realizar. Aquí, en esta entrada, trataremos este procedimiento en y desde el procesador de texto LO-Writer usando OOo Basic dado que la alternativa más básica (macro más OOo Basic), que también se emplea aquí en el script EscribirFraseProcedimA, ya ha sido planteada en una [entrada anterior] a la que remito para comprender el procedimiento que concreta la escritura del texto en el documento. En un segundo script (EscribirFraseProcedimB) omito los procedimientos basados en macros.

En este procedimiento se identifican las siguientes fases:
  1. Creación del documento según procedimiento ordinario en LO-Writer, incluyendo la creación del módulo en el que desarrollar el script (Herramientas | Macros | Organizar macros). También se puede considerar este punto como pre-requisito y situar el inicio del procedimiento en el actual punto 2.
  2. Identificación o generación del segmento textual a escribir, identificando en el texto invariable y el variable. El primero se asigna a constantes y como tales se declaran y cumplimentan en el script.
  3. El segundo se asocia a una variable, colección de variables o colección de datos (array) en caso de ser múltiple. Igualmente se declara o declaran en el script.
  4. Se provee de un procedimiento de interface para facilitar al usuario el ingreso de datos en las variables. 
    1. El procedimiento más sencillo consiste en el manejo directo del IDE y la escritura del contenido de las variables como parte del script
    2. Un segundo procedimiento implica el uso sucesivo (si es necesario) de la función input() en asociación a la(s) variable(s) o el array.
    3. En este último caso se puede implementar una iteración (for...next) con la que recorrer los valores índices de los componentes del array.
    4. Un tercera forma consiste en crear un cuadro de diálogo o usar como alternativa un formulario independiente del documento sobre el que escribir. Esta opción no se considera como alternativa en esta entrada, ya que requiere procedimientos específicos.
  5. A continuación se desarrolla un procedimiento basado en la concatenación de las constantes y las variables en la sucesión u orden que corresponda, dando como resultado una variable de síntesis que vamos a identificar aquí como vTexto para simplificar.
  6. Bien directamente, bien mediante una subrutina, formalizamos la escritura de la variable vTexto en el cuerpo del documento.
Una vez creado el documento-soporte (en la práctica el equivalente al DocAp) éste se tratará como plantilla, permitiendo así el uso de documentos derivados de ésta sin que se vea afectado (ni alterado) el documento-soporte que quedará sí siempre disponible.

Se recomienda generar la opción 4.4 (cuadro de diálogo o formulario) en caso de documento-soporte de uso muy frecuente. En este supuesto dejamos de habla de un procedimiento simple y pasamos a considerarlo como procedimiento complejo DocAp.

Documento. A modo de ejemplo y como concreción del procedimiento y concretamente de la opción 4.2 (función input()), desarrollo este documento-soporte. Este documento consta de dos script (EscribirFraseProcedimA y EscribirFraseProcedimB) que constituyen en realidad dos procedimientos diferentes: el primero usa recursos "de lenguaje de macros" y el segundo sólo OOo Basic.

Utilizo el procedimiento directo que supone trabajar desde el IDE para ajustar los valores que se presuponen fijos desde el punto de vista del profesional que crea y usa el recurso (datos de identificación del OE y del SEO) e incluyo un procedimiento basado en la función MsgBox() para tratar con variables asociadas a condiciones concordancia gramatical.