Primer script
Al crear una macro nos hemos acercado al IDE, pero no terminamos de entrar en él porque no era necesario. Ahora sí.
REM ***** BASIC *****Sub MainEnd Sub
Sub Mainprint "OOo Basic para orientadores"End Sub
REM ***** BASIC *****Sub MainEnd Sub
Sub Mainprint "OOo Basic para orientadores"End Sub
Parece lógico empezar por explicar estos procedimientos con las herramientas disponibles desde el propio procesador de textos (en nuestro caso Writer), ya que es la herramienta a la que estamos acostumbrados y porque el paso de Grabar macro a la escritura de script desde el IDE del propio servicio nos permite avanzar mucho en este aprendizaje sin necesidad de hacer uso de otros lenguajes. De hecho podríamos limitarnos a usar OOo Basic como única herramienta para automatizar la composición de texto, sin más complicación, pero hacerlo nos limita para el desarrollo de otros aspectos de la competencia digital, así que no es nuestra opción.
Así que, como hay que ir por partes y, a ser posible, que el avance tenga su lógica, inicio esta sección exponiendo diferentes formas de "trabajar" con textos y en la automatización de su composición con las herramientas más básicas y accesibles: macros y script OOo Basic.
Veremos en primer lugar y como prolongación de lo visto en la sección anterior y primera del capítulo Usos, cómo combinar el uso de macros y OOo Basic para desarrollar este proceso de automatización. Hay más que escritura en este proceso, así que también trataremos sobre el establecimiento de formatos y el desplazamiento por el documento. Precisamente en ambos, la combinación de macros y script resulta muy beneficiosa en términos de facilidad de creación de código y simplicidad de uso.
Pasaremos después a trabajar exclusivamente con OOo Basic en cuanto cuenta con alternativas diferenciadas en la funcionalidad Grabar macro para el manejo y la escritura de textos.
Finalmente nos enfrentaremos a tareas específicas, que derivan de las "imposiciones" formales y de formato de algunos textos con los que tenemos que trabajar como documento-base (un ejemplo de ello, los modelos de informe o de dictamen, pero hay más) y abordaremos el modo de cumplimentar "campos" de contenido en ellos.
Además de escribir textos, es frecuente que los documentos contengan también tablas, por lo que resulta de interés saber cómo crearlas y cumplimentarlas, así cómo realizar desplazamientos por ellas de forma automatizada.
La esencia de este procedimiento es la misma que la vista en la entrada anterior, pero la diferencia es que ahora los script son más genuinamente tales, esto es: en ellos se hace uso de los elementos del lenguaje (OOo Basic, en nuestro caso), lo que permite un mejor aprovechamiento de las propias macros y, sobre todo, un funcionamiento más funcional a la vez que complejo del algoritmo.
dim document as objectdim dispatcher as objectrem get access to the documentdocument = ThisComponent.CurrentController.Framedispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
document = ThisComponent.CurrentController.Framedispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
VarSis
dispatcher.executeDispatch(document, ".uno:GoToStartOfDoc", "", 0, Array())
sub LetraTipo (sLetraT As string)
Varsisdim args1(0) as new com.sun.star.beans.PropertyValueargs1(0).Name = sLetraTargs1(0).Value = truedispatcher.executeDispatch(document, ".uno:"+sLetraT, "", 0, args1())
end sub
- Tras el nombre (LetraTipo) abro y cierro paréntesis y en su interior declaro la variable sLetraT como string: sub LetraTipo (sLetraT As string)
- En args1(0) sustituyo el dato original ("Bold") por la variable sLetraT: args1(0).Name = sLetraT. De este modo, en lugar de un valor fijo, puedo trabajar con los valores que asigne a la variable sLetraT.
- Procedo del mismo modo en el ejecutor o lanzador de la macro, sustituyendo el segundo argumento por una cadena de texto resultante de concatenar un texto fijo con la variable anterior. El resto de los argumentos no sufre variación: dispatcher.executeDispatch(document, ".uno:"+sLetraT, "", 0, args1()) (8)
Segundo. Creo un script en OOo Basic cuyo funcionamiento esperado es el siguiente:
Este script que contiene variables a las que se asignan valores; estas variables se pasan como argumentos a la hora de llamar a las macros-subrutinas, las cuales asumen la función de los argumentos que se declaran en dichas macros-subrutinas (ver Primero)
Para generar los saltos de línea se hace uso de un bucle For que se inicia en 0 y se repite tantas veces como el valor numérico que se asigne a iNumLineas (4 en nuestro caso). Tras este salto de línea se ejecuta de nuevo llamada a la macro-subrutina EscribirPalabra(), asignando previamente un string diferente a la variable sTexto (argumento de la macro-subrutina EscribirPalabra().
Podemos pensar en otras formas de utilizar macros como elementos de script; esta es una de ellas, pero no la única. Por ejemplo, siguiendo la misma línea de trabajo que hemos desarrollado en este script, podemos hacerlo interactivo, solicitando al usuario valores de entrada para crear otros texto. Para ello usaríamos la función InputBox(), por ejemplo. Pero lo hecho es suficiente para mostrar las posibilidades que tiene esta forma de hacer uso de la combinación de macros, macros convertidas en subrutinas y script.
Te dejo a continuación acceso al documento que contiene las macros y el script explicados en esta entrada.
Aunque cuando expliqué las macros en OOo Basic ya hable de estos temas, me interesa volver sobre ello para hacerlo desde una perspectiva general y también más utilitaria, esto es: desde la perspectiva del uso que podemos hacer de la combinación de macros (entendidas como código resultante de Grabar macro) y script (entendidos como secuencias de código desarrollados desde el IDE) y los procedimientos de conversión de una macro en un script.
Ahora, como dije, vamos a identificar macro como resultado de usar Grabar macro, ya que otra diferenciación conlleva problemas de concepto que no nos interesan. Grabar macro genera una sub(rutina), lo mismo que la podemos crear nosotros directamente desde el IDE, ambos comparten nombre, pero no filosofía e incluso, tampoco funcionalidad.En la entrada en que expliqué (brevemente) la diferencia entre la programación imperativa y la estructurada, dije que retomaríamos el tema cuando se tratara sobre las macros y su conversión en script, así que vamos a ello, ya que cuando hable de las macros desde OOo Basic poco se dijo al respecto, puesto que el objetivo era otro. De todos modos esa entrada puede serte ahora de interés, así que, si quieres, accede a ella desde este enlace.
Si te fijas, una macro (Grabar macro) es, en realidad, un ejemplo de programación lineal o jerárquica: Grabar macro sólo es capaz de generar una secuencia lineal en la que una instrucción sigue a otra. Es lógico que esto sea así, ya que lo que hace esta funcionalidad de LO-Writer es grabar y convertir en sentencias OOo Basic la sucesión de acciones que realizamos en el documento desde el teclado. Es el uso que nosotros hacemos de las macros creadas el que da al funcionamiento de conjunto la "apariencia" de ejecución asimilable a lo que define a la programación estructurada: el uso sucesivo de subrutinas, pero una subrutina-macro únicamente es una sucesión de instrucciones. Más aun, no es posible que Grabar macro genere código ni con condicionales, ni con bucles, ni siquiera con sentencias GoTo; en resumen, Grabar macro no equivale a programar.
Esto supone una grave limitación que sólo es posible superar trasformando una macro en un script, utilizando OOo Basic y desde el IDE. Afortunadamente esto es perfectamente posible, aunque con un coste: tenemos que entender la lógica de programación de la macro y conocer el lenguaje OOo Basic, algo que, a estas alturas tú ya sabes.
Empezamos usando Grabar macro como puerta de entrada a la programación (en OOo Basic, y por tanto, desde la perspectiva de la competencia ofimática y desde el interior de los documentos), y necesitamos ahora, para mejorar nuestra capacidad de uso de lo aprendido respecto a ese lenguaje, detenernos en los modos o procedimientos de trabajar con el código de una macro para convertirlos en script; esto equivale a pasar de un modelo estrictamente lineal a otro estructurado, e incluso modular.
¿Por qué necesitamos trabajar desde el modelo estructurado, incluso aun mejor desde el modular?. O dicho de un modo más práctico: ¿por qué necesitamos programar en lugar de limitarnos a generar secuencias de macros?.
Desde un punto de vista práctico y de utilidad inmediata, algunos problemas, algunos objetivos, si prefieres, podemos abordarlos exclusivamente con macros, pero la gestión de procedimientos de cierta (no mucho) complejidad requiere algo más, especialmente si nuestro objetivo es la automatización de documentos. Con macros podemos automatizar secuencias fijas de manejo del documento, bien de forma estrictamente lineal (una única macro resuelve todo el conjunto de acciones), bien de forma estructurada pero manual: activamos una secuencia de macros, una tras otra, conforme deseemos que se desarrolle el procedimiento.
Pero en el mismo momento en que nos interesa generar una secuencia de macros de forma automática, ya necesitamos realizar la primera conversión de macros en script: necesitamos crear un script que llame sucesivamente a las macros en vez de hacerlo nosotros.
Esta es la forma más simple de trabajar con macros desde script, y tiene sus ventajas respecto a crear una macro que las incluya a todas: podemos simplificar nuestro trabajo de generar macros (que no deja de ser tedioso) aplicando una forma elemental del modelo estructurado: generar piezas reutilizables de código mediante Grabar macro, que podemos llamar desde diferentes script, cuando las necesitemos, las veces que deseemos y en el orden que nos interese. Este procedimiento es siempre más económico en tiempos de programación que crear una y otra macro que se ajuste a la secuencia de acciones necesarias.
El siguiente paso puede ser condicionar la llamada a una macro a un resultado u a otro (condicionalidad), o llamar de forma repetida a una macro para que una secuencia de acciones se repita un número determinado de veces (iteración). Sin escritura de script desde el IDE no podemos hacer nada de eso.
El tercero y último (para no extenderme más), es incluir dentro de la misma macro esas estructuras cíclicas o condicionales de las que hablamos antes.
Para todo ello necesitamos trabajar desde el IDE y con OOo Basic, y especialmente para la tercera, saber descifrar el código que genera Grabar macro, lo que equivale a leer y entender código OOo Basic.
A explicar estos procedimientos que ahora sólo he enunciado dedicaré las siguientes entradas.
oDoc = ThisComponent.CurrentSelection.getByIndex(0).End
oDoc.String = "Texto que se desea escribir"
Script OOo Basic para automatizar la escritura de texto sin usar Grabar macro.
Contiene subrutina y script principal. El script se ha creado para facilitar interface con el usuario mediante InputBox(), pero puede prescindirse de ello sin alterar el funcionamiento del script.
Contiene subrutina (basada en matriz) y script principal. Ambos emplean una matriz para compartir datos masivos, La subrutina escribe el contenido utilizando un bucle for para automatizar el proceso.
Después de la introducción general al tema realizada en una [entrada anterior], disponemos ya de argumentos para tratar con más detalle esta cuestión: cómo transformar una macro simple en una subrutina.
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "On"
args1(0).Value = true
dispatcher.executeDispatch(document, ".uno:DefaultNumbering", "", 0, args1())
Sub msbIndiceNumerico()
Sub msbIndiceNumerico(bOpcion As Boolean)
args2(0).Value = bOpcion
El resultado...
Sub msbIndiceNumerico(bOpcion As Boolean)
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "On"
args1(0).Value = bOpcion
dispatcher.executeDispatch(document, ".uno:DefaultNumbering", "", 0, args1())
End Sub
... es una subrutina que puede ser llamada (2) desde una macro o script principal como alternativa a la llamada opcional a dos macros simples: la de aplicación y la de retirada del índice numérico (3).
Una variación del modelo anterior es la que incluye el uso de un bucle en el script desde el que se llama a la subrutina, generando así una secuencia de desarrollo o aplicación de la subrutina. Por ejemplo, podemos avanzar letra por letra (incluyendo los espacios en blanco) seleccionando o no los elementos que se recorren. [Esta subrutina es un ejemplo de ello].
También podemos utilizar este bucle dentro de la subrutina, afectando únicamente a los instrucciones de ejecución (dispatcher), [como en este ejemplo].
sub msbAvanPag(iNumPag As Integer)
Dim i As Integer
For i=0 To iNumPag
dispatcher.executeDispatch(document, ".uno:PageDown", "", 0, Array())
Next
end sub
La tercera forma de crear una subrutina a partir de una macro simple ya vulnera el criterio de macro simple, al menos en alguna de sus formulaciones, pero también puede ser una solución cuando el uso de dos parejas de macros simples sea requerido con cierta frecuencia.
Considero "parejas de macros simples" cuando éstas son complementarias una de la otra, como en el caso que sigue:
sub mcrBajarLinea
dim args1(1) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Count"
args1(0).Value = 1
args1(1).Name = "Select"
args1(1).Value = false
dispatcher.executeDispatch(document, ".uno:GoDown", "", 0, args1())
End Sub
Sub mcrSubirLinea
dim args1(1) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Count"
args1(0).Value = 1
args1(1).Name = "Select"
args1(1).Value = false
dispatcher.executeDispatch(document, ".uno:GoUp", "", 0, args1())
End Sub
sub msbLinea(bSelect As Boolean,sMov As String)dim args1(1) as new com.sun.star.beans.PropertyValueargs1(0).Name = "Count"args1(0).Value = 1args1(1).Name = "Select"args1(1).Value = bSelectIf sMov = "B" Thendispatcher.executeDispatch(document, ".uno:GoDown", "", 0, args1())MsgBox "He bajado una linea"ElseIf sMov = "S" Thendispatcher.executeDispatch(document, ".uno:GoUp", "", 0, args1())MsgBox "He subido una línea"ElseMsgBox "El valor de la variable 'sLinea' no es correcto"End IfEnd Sub
sub msbLinea(bSelect As Boolean,sMov As String)dim args1(1) as new com.sun.star.beans.PropertyValueargs1(0).Name = "Count"args1(0).Value = 1args1(1).Name = "Select"args1(1).Value = bSelectdispatcher.executeDispatch(document, sMov, "", 0, args1())End Sub
(1) Existen muchas otras macros simples que presentan esta estructura y que pueden ser convertidas en subrutinas siguiendo este mismo procedimiento. Una de ellas, y en la que su conversión en subrutina es especialmente recomendable, es la macro de escritura (también podemos hacer lo mismo con el script OOo Basic alternativo a la macro). Si ahora propongo esta macro de posicionamiento es precisamente para evitar utilizar siempre el mismo ejemplo, aunque posiblemente sea éste un ejemplo no tan explícito como al que sustituye.
(2) Recuerdo los dos modos de usar la subrutina desde la macro principal:
Aunque Grabar macro siempre será una funcionalidad útil, lo cierto es que su uso intensivo como recurso para automatizar un documento presenta limitaciones, especialmente si el documento es de cierta extensión y no presenta mayor complicación en términos de formato.
En la primera, el usuario simplemente debe activar Grabar macro y proceder a "escribir" y formatear el documento tal y como desea que se reproduzca automáticamente.
La segunda requiere el análisis de la secuencia de acciones a desarrollar para identificar qué cuantas son y en qué orden se producen, pero también requiere acceder al IDE para trabajar desde él y conocer el código que genera Grabar macro en cada una de las acciones posibles.
Es precisamente este enfoque modular, junto con la familiaridad en el uso del IDE y el conocimiento del código, lo que caracteriza esta estrategia que diferencia al usuario familiarizado con la creación de macros en un usuario capaz de dominar la creación de docap aun simples, pero funcionales, basados en el "lenguaje de macros" en sentido estricto.
Cierto que aun no dispone de herramientas para personalizar las macros que crea, pero la implementación de variables es un paso relativamente fácil de dar, si bien para ello se debe acercar a lo que implica Combinar correspondencia para intuir este concepto, con los riesgos que esto entraña; por ello siempre será mucho más útil y funcional acceder a este nivel de conocimiento mediante algún tipo de instrucción.
Las necesidades de estudio y aprendizaje se acentúan conforme se adentra uno en la creación de soluciones adaptadas al quehacer profesional.
Para finalizar esta entrada, te dejo enlace a los dos documentos, [el primero] basado en el uso lineal de Grabar macro y [el segundo] creado utilizando el enfoque modular. Recuerda que tienes que descargarlos y abrirlos desde Libre Office. Para una explicación detallada de las diferencias entre ambos puedes acceder a [este vídeo].
Ya hemos aprendido a crear una macro sencilla y es posible que te preguntes si el resultado merece el esfuerzo. En principio te diría que en macros como la creada en la entrada anterior, la respuesta dependerá de la frecuencia con la que la usemos: a menor frecuencia, menos "rentabilidad". Pero es que con una macro podemos hacer muchas más cosas... siempre que estemos dispuestos a seguir aprendiendo.
A pesar de esta diferencias y todo lo que derivan de ellas, es común en los soportes que admiten macros (servicios de suites ofimáticas) se emplee el concepto macro abarcando ambas realidades.
En principio, y en lo que a esta entrada se refiere, vamos a denominar macro al código que deriva de la aplicación de la grabadora de macros. El hecho de que estemos tratando este tema desde Writer no implica que no sea posible crear macros (según la definición anterior) en otros soportes (por ejemplo Calc), aunque es en los procesadores de texto donde, posiblemente, más utilidad tenga trabajar con macros por la variedad de posibilidades que éstas tienen en el trabajo con documentos de texto.
Para trabajar con macros es necesario que conozcas unas cuantas cosas que mejor que yo te puede explicar la [documentación oficial de LibreOffice], así que lo dejo en sus manos. Es un documento muy recomendable, aunque encontrarás en él la (para mi) confusión que antes te apunté entre macro y script.
Además puede que te encuentres con que LibreOffice se resiste a dejarte acceder a las macros. Esto es debido al sistema de control de seguridad que tiene activado y a la consideración de las macros como elementos potencialmente peligrosos. Pero como aquí estamos hablando de macros de confianza, [este documento] te permitirá actuar en consecuencia (y en conciencia). El resto queda en tus manos.
Una vez que ya hayas superado las dos fases anteriores, lo mejor que podemos hacer en poner en práctica eso de que la mejor forma de aprender es haciendo, planteamiento que, en términos generales, es más que dudoso, pero que en este caso se acerca bastante a la verdad: aprendamos a trabajar con macros creando una. El [vídeo] que sigue te muestra cómo crear una macro simple.