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

martes, 3 de diciembre de 2024

Documentos. LibreOffice

Textos desde macros

También podemos crear textos y trabajar con ellos utilizando macros. En este caso el planteamiento inicial es crear el texto desde la página en blanco, aunque también es posible (aunque más laborioso) trabajar con un documento formalizado, incluso en formato tabla, como es el caso del dictamen de escolarización.


La utilidad Grabar macro está pensada como recurso para capturar las pulsaciones del teclado (y algunos clic del ratón). Debemos activarla desde Herramientas | Macros | Grabar macro y proceder como ya quedó dicho en las entradas en las que se ha tratado este tema, como [por ejemplo]. En realidad es una utilidad que se ajusta bien al objetivo para el que está pensada y hacer uso de ella es una forma interesante de iniciarse en la programación, especialmente si posteriormente trabajamos sobre el código generado desde el IDE, [como ya vimos].

En lo que al trabajo con textos se refiere, y cuando el objetivo es crear documentos-aplicaciones [incluso de cierta complejidad], el código que genera esta funcionalidad nos puede resultar útil, incluso en fases más avanzadas, en las que predomina la creación de script desde OOo Basic, ya que es posible combinar el código macro con el código creado directamente desde el IDE.

Centrándonos en el trabajo con y sobre texto, la mayor utilidad de Grabar macro es que podemos automatizar la composición de documentos con tan sólo activar la macro creada previamente, la cual sirve a modo de plantilla, sin que sea necesario que el documento contenga una sola palabra. Cierto es que para ello deberemos componer el texto que nos servirá de base y cierto también que para sacar el máximo provecho a este procedimientos deberemos saber identificar en el código la posición de las variables y, mejor aun, trabajar con variables mediante OOo Basic. Una vez alcanzado este nivel, especialmente si sabemos manejar también colecciones de datos (matrices), incluso podemos idear procedimientos que funcionen de forma similar a como hacemos con Combinar correspondencia, con todo lo que esto implica de automatización de procedimientos sencillos de creación de documentos personalizados repetidas veces.

Estoy pensando, como se puede deducir, en el trabajo con documentos en blanco, pero, como también dije antes, también podemos hacerlo sobre documentos-modelo. En este tipo de documentos deberemos prestar especial atención al movimiento del cursor por el documento, acción que debe ajustarse con precisión a lo necesario para ubicarnos en la posición deseada, ya que Grabar macro va a hacer justamente lo que se espera que haga: grabar cada una de nuestras acciones. 

Un tercer ejemplo de uso de macros es la combinación del uso de un diálogo (1) como recurso input sobre un documento en blanco. Se trata de un procedimiento de cierta complejidad, desarrollado en un nivel ya avanzado de trabajo con OOo Basic, pero que utiliza fundamentalmente código macro modificado desde el IDE. Como ejemplo tenemos en nuestro listado el [Informe de solicitud de becas NEAE] del que te hablo en [esta entrada], que puedes encontrar más abajo en esta misma sección del blog.

Como puedes ver, el uso de macros nos permite ya automatizar procedimientos, pero (y eso es para mi lo más importante) nos permite dar el paso definitivo del recurso a utilidades a iniciarnos en la programación: sólo debemos perder miedo al IDE y acercarnos al código que crea automáticamente Grabar macro (2).

NOTAS

(1) Recordarás que se trata de una modalidad de formulario emergente que se crea directamente desde el IDE y a cuyos controles se accede mediante código.
(2) Realmente trabajar desde el IDE nos puede resultar extraño y un tanto desconcertante al principio, pero la mayor dificultad que nos podemos encontrar en este momento es comprender las líneas de código que encontramos escritas. Aunque con un poco de atención enseguida le cogeremos "el truco", para avanzar realmente en la línea deseada es conveniente que prestes atención a lo que se explica en la sección [OOo Basic] de este blog. El camino se te va a hacer más corto y más llano.


lunes, 15 de julio de 2024

Procedimientos. Macros.

Vincular macros o script a un objeto (2)

Además de un comando o a una hoja, también podemos asignar una macro/script a un objeto figura o imagen. Aunque aquí nos basemos en Calc, esa posibilidad activar un script no se limita a este servicio, ya que es posible insertar una forma o una imagen en cualquiera de los servicios LibreOffice.



Después de implementar una forma (Insertar | Forma) y/o una imagen (Insertar | Imagen) en la hoja, hacemos clic derecho sobre ella para seleccionara. Automáticamente se despliega un menú de opciones, dentro de las cuales tenemos la opción Asignar macro.


Haciendo en ella accedemos a un submenú donde se diferencia una ventana superior donde se identifica la única opción de evento disponible (Botón del ratón presionado). En la ventana inferior se encuentran los subdirectorios que contienen las distintas ubicaciones de macros posibles (Macro de). Deberemos hacer clic en aquella que contenga la macro que deseamos asociar a la forma/imagen y seleccionarla en Macros existentes.


Una vez seleccionada la macro/script deberemos hacer clic en el comando Asignar (lateral derecho de la ventana) y después en Aceptar (marco inferior). Estas dos acciones son necesarias para que se realice correctamente la asignación de la macro/script al objeto forma/imagen.


El documento Calc que ejemplifica este proceso consta de dos hojas: en la primera he implementado una figura y en la segunda una imagen. Los script (podemos decir, de ida y vuelta) permiten acceder uno a Hoja2 y otro a Hoja1. De este modo, al hacer clic en el cuadrado azul (Hoja1) nos desplazamos a Hoja2 (previamente se muestra esta hoja y después se oculta Hoja1). El proceso que desarrolla el script asociado a la imagen situada en Hoja2 realiza el proceso contrario.

Documento. En [este libro Calc] puedes encontrar ejemplificado el proceso descrito en la entrada, incluyendo los dos script que se activan desde los objetos gráficos insertados en sus dos hojas.





Procedimientos. Macros.

Vincular macros o script a un objeto (1)

Una vez que hemos creado una macro o un script, necesitamos hacer que funciones. La primera alternativa consiste en utilizar las opciones de la interface del servicio (Herramientas | Macros | Ejecutar macro), solución simple y funcional pero poco atractiva a día de hoy. La segunda consiste en asignar la macro/script a un comando de formulario (botón), que es la forma que más se asemeja al modo standard de trabajar con las interfaces visuales. Pero aun hay otras opciones.


Una
forma un tanto especial y específico de las hojas de cálculo, consiste en asociar el script a la propia hoja. Para ello nos posicionamos en el navegador inferior de Calc y hacemos clic derecho sobre el nombre de una de las pestañas, la que representa la hoja a la que queremos asignar el script. 


Se visualiza la ventana emergente con el menú que vemos en la imagen superior y seleccionamos la opción Eventos de hoja. Haciendo clic en ella, accedemos a una ventana de selección de opciones de vinculación (eventos) (1)


Seleccionamos uno de estos eventos y  hacemos clic en Macros. A continuación podremos seleccionar la macro/script que nos interesa vincular a la página, seleccionarla y hacemos clic en Aceptar.


 
Nos devuelve a la ventana anterior (ahora con la macro seleccionada identificada en la columna Acción asignada) y volvemos a hacer clic en Aceptar.

De este modo la macro/script queda vinculada a la página en función del evento que hayamos escogido.

En el ejemplo que desarrollo como concreción del proceso anterior, he elegido el evento Activar documento y la macro Main. Esto implica que cuando Hoja1 sea la hoja activa se pondrán en marcha las instrucciones que contiene este script.

Sub Main

Dim oHoja As Object

oHoja = ThisComponent.getSheets.getByIndex(1)
oHoja.isVisible = True
Wait 500
oHoja = ThisComponent.getSheets.getByIndex(0)
oHoja.isVisible = False
Wait 500
oHoja = ThisComponent.getSheets.getByIndex(2)
oHoja.isVisible = True
Wait 500
oHoja = ThisComponent.getSheets.getByIndex(1)
oHoja.isVisible = False
Wait 500
oHoja = ThisComponent.getSheets.getByIndex(3)
oHoja.isVisible = True
Wait 500
oHoja = ThisComponent.getSheets.getByIndex(2)
oHoja.isVisible = False

End Sub

En resumen, se visibiliza (mostrar) una hoja, se espera 500 msg y se oculta la hoja precedente (2), con lo que la hoja visible pasa a ser también la hoja activa (3).

Documento. Este [libro Calc] contiene el código anterior asociado a Hoja1. Al abrir este documento, nos encontramos posicionados en Hoja4. Si nos desplazamos "manualmente" a Hoja1 se desarrollará el proceso esperado (4). 

NOTAS

(1) Si comparas los eventos posibles con los que se despliegan cuando trabajamos con el control de formulario Botón (Comando), verás que los eventos de hoja son mucho más limitados.
(2) Esto es así por trabajar con el índice de las hojas, lo que facilita la secuencia Mostrar-Ocultar.
(3) Este script contiene la instrucción Wait cuyo uso merece más atención de la que se le presta aquí. Será necesario analizarla específicamente en una entrada específica.
(4) Dado que se ocultan todas las hojas (menos Hoja4), para volver al estado inicial deberemos mostrar todas las hojas (Hoja | Mostar la hoja, seleccionamos todas las que se nos muestran y clic en Aceptar), pero mantendremos Hoja4 como hoja activa. Si guardamos el documento posicionándonos en Hoja1, de modo que al volver a activarlo estemos posicionados en ella, no se activará el script.

sábado, 13 de julio de 2024

Procedimientos. Datos

Ocultar hojas mediante macro

Cuando nos interese por cualquier motivo que las hojas de un libro Calc no sean directamente accesibles podemos ocultarlas para después mostrarlas selectivamente. Para ello disponemos de las funcionalidades pertinentes desde el menú Datos (1).


También podemos ocultar una hoja mediante una macro que oculta la hoja activa (2). Es muy sencilla; te la muestro a continuación:

Sub OcultarHoja

dim document   as object
dim dispatcher as object

document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

dispatcher.executeDispatch(document, ".uno:Hide", "", 0, Array())

End Sub

No explico las cuatro primeras líneas por ser sobradamente conocidas, así que la tarea se simplifica aun más: la función dispatcher.executeDispatch() lanza la orden ".uno:Hide" sobre el objeto asignado a la variable document. Dicha orden consiste en atribuir al objeto el atributo "Oculto" (Hide), lo que equivale al uso del submenú Hoja | Ocultar hoja. Proceso finalizado (3)

Documento. Este [libro Calc] contiene la macro explicada en la entrada.

NOTAS

(1) También podemos hacerlo desde el menú que se despliega cuando hacemos clic derecho sobre el nombre de la hoja en el navegador inferior de Calc.
(2) Y mediante Grabar macro es la única opción disponible, que yo sepa.
(3) Esta macro es tan simple que poco podemos hacer para instrumentalizarla. Podemos, eso sí, modificar la macro, convirtiendo en variables públicas las de objeto (document dispatcher), creando después un script de asignación de los objetos correspondientes a dichas variables (VarSis, en mi caso) y llamar a ese script desde el inicio de la macro OcultarHoja; pero no podemos convertir esta macro en una subrutina, aunque sí utilizarla como script auxiliar a emplear (llamar) desde otros que impliquen en su algoritmo la ocultación de la hoja activa.

Procedimientos. Datos

Macro para desplazarse por las hojas

Cuando el número de hojas que contiene nuestro libro Calc es elevado, desplazarse por ellas mediante el navegador inferior puede resultar poco práctico. Como alternativa podemos crear una macro que nos facilite este desplazamiento. Además así podremos ir a la hoja que deseemos desde un comando.


Una vez [creada la macro] según lo que ya sabemos toca estudiarla para sacar de ella todo el rendimiento posible.

Sub macroIrHoja2

dim document   as object
dim dispatcher as object

document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Nr"
args1(0).Value = 2
dispatcher.executeDispatch(document, ".uno:JumpToTable", "", 0, args1())

End Sub

Una ver eliminados los comentarios sobradamente conocidos, y en su sustitución, paso a explicar el funcionamiento de esta macro. El objetivo que se persigue con ella es desplazar a la hoja llamada "Hoja2", por lo que se supone que nos encontramos en otra hoja diferentes (1)

Apreciamos, en primer lugar, la sintaxis común a todas la macros:

  • La declaración de las variables objeto document   y dispatcher, y la asignación de esos objetos a las variables:

document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

  • Observamos que la matriz args1(0) cuenta con dos dimensiones (Name y Value) (2): el primero toma el valor "Nr" que identifica que trabajaremos con el número de la hoja y el segundo, Value (valor) al que se asigna el dato (integer) concreto (2) (3)
  • Finalmente, el ejecutor de la macro (dispatcher.executeDispatch) nos muestra la instrucción que ejecuta la orden de saltar a la hoja señalada en args1(0).Value (".uno:JumpToTable"(4)
Una vez comprendido el código de esta macro, por ejemplo, puedes añadir más hojas a tu libro y construir un navegador implementado comandos asociados a macros. Esta que te comento a continuación no es la mejor opción, pero sí muy práctica: es suficiente con que copies y pegues la macro original las veces que desees, des nombres diferentes a los script creados y cambies el parámetro de args1(0).Value = 2 , sustituyendo así el número de orden de la hoja.

Pero también puedes transformar esta macro en una subrutina y ahorrarte un montón de líneas de código; de este modo será suficiente con llamar a la subrutina script.

Observa cómo convertí la macro original en una subrutina ( MovHoja (iH As Integer)). El script (IrHoja2) es ahora mucho más sencillo y, eso sí, tienes que repetirlo (con los cambios que corresponden) las veces que sea necesario si quieres aplicarlo a más hojas:

Sub IrHoja2 'Script

MovHoja (2)

End Sub


Sub MovHoja (iH As Integer) 'Subrutina

dim document   as object
dim dispatcher as object

document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Nr"
args1(0).Value = iH
dispatcher.executeDispatch(document, ".uno:JumpToTable", "", 0, args1())

End sub

El funcionamiento del conjunto es así de sencillo: desde el script se llama a la subrutina, pasando como argumento el id numérico de la hoja (6). La subrutina ejecuta el procedimiento ya visto antes en la macro, sustituyendo el contenido de args1(0).Value empelado en la macro por el identificador del parámetro que se define en la declaración de la subrutina (= iH) (7)

Documento. En [este libro Calc] encontrarás el código explicado en la entrada.

NOTAS

(1) Perogrullada: de no ser así no apreciaríamos el efecto de la macro.
(2) Como puedes ver, hasta ahora nada de especial en cuanto a la sintaxis de una macro
(3) Esto ya nos da una pista de cómo podemos manipular esta macro mediante OOo Basic.
(4) En el lenguaje macro, las hojas se asimilan a tablas, de ahí la instrucción JumpToTable.
(5) Aunque no es la única opción; y menos aun si sólo vas a trabajar con una macro.
(6) Fíjate que en el caso de las macros, el índice de la hoja coincide con su orden numérico observable: la primera es 1, no 0. Esto no es así en un script o una subrutina creado directamente en OOo Basic, ya que en él la matriz de hojas del libro se inicia con el valor 0.
(7) Con lo que, como sabes, se está asignando el valor establecido en el script en la llamada a la subrutina.

viernes, 26 de abril de 2024

OOo Basic. Datos

Variables

Una orientadora, Mercedes, está colaborando con la Jefa de estudios del colegio elaborando informes escolares de una lista de alumnos y alumnas (el motivo ahora no es relevante). Mercedes piensa usar lo que estamos aprendiendo sobre LibreOffice y piensa crear un documento-base en Writer para elaborar los informes que recojan los datos de ese análisis. Veamos cómo lo podemos enfocar.


Después de investigar unos cuantos expedientes y una vez que se hace idea de cómo abordar el tema, Mercedes se plantea crear un documento-modelo para recoger toda la información. Hace un informe a modo de "ejemplo" y, después de revisarlo y reajustarlo, se plantea utilizarlo como base para construir los restantes. 

Aunque una Mercedes real posiblemente actuara de otro modo (1), nosotros vamos a suponer que quiere poner en práctica lo aprendido hasta ahora: crear macros y script.

Puesta a la tarea, Mercedes crea una primera macro a la vez que va escribiendo su documento. Supongamos que este texto es parte del inicio del documento:

Juan es actualmente alumno de 4º de E. Primaria en el C.P. Aurelia Sánchez (Santullano)

Activa Grabar macro, escribe el texto, finaliza la grabación, prueba su macro y observa que funciona según lo previsto. Pero ahora se le presenta un dilema: si quiere hacer ahora el informe de Luis se encuentra conque o utiliza su documento como documento-base y sustituye Juan por Luis o tiene que crear una macro para cada alumno. Evidentemente esta segunda opción no es razonable, ya que no le quita trabajo (2).

Supongamos que, a pesar de ello, crea una segunda macro, ahora con este otro texto:

Luis es actualmente alumno de 2º de E. Primaria en el C.P. Aurelia Sánchez (Santullano)

Comparemos ambos textos:

  • Observamos que varían dos datos: el nombre del alumno y el curso.
  • El resto permanece igual
Esos datos que varían (Juan - Luis y 4º - 2º) son las variables. Ambos pertenecen a dos conjuntos, el conjunto nombre y el conjunto curso, por lo que podemos entender que una variable, además de lo obvio (un dato que varía) también se puede entender como la denominación genérica de un conjunto de datos.

Pero desde la perspectiva de la programación, una variable es, en realidad, un identificador de un espacio de memoria RAM a cuyo contenido se accede utilizando ese identificador.

En todo caso, y con independencia de con qué conceptualización nos quedemos, usar variables nos va a permitir resolver de forma sencilla el problema de Mercedes: es suficiente con que sustituya el nombre concreto por un identificador como sNombre y el curso por sCurso para que no necesite cambiar en el texto ni el nombre ni el curso. Pero aun no sabemos cómo se hace eso.

Vamos a ver qué dice las macros que ha creado Mercedes. Para ello accedemos al IDE como sigue: 
  • Herramientas | Macros  | Editar macros.
  • Si no estamos ya en nuestro documento, Biblioteca Standard, Módule1 (por ejemplo), repetimos la selección que implica llegar hasta aquí...
  • Y nos encontramos con el código siguiente:

sub InfoEscolar1
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Text"
args1(0).Value = "Juan es actualmente alumno de 4º de E. Primaria del C.P. Aurelia Sánchez (Santullano)"

dispatcher.executeDispatch(document, ".uno:InsertText", "", 0, args1())

end sub

sub InfoEscolar2
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Text"
args1(0).Value = "Luis es actualmente alumno de 2º de E. Primaria del C.P. Aurelia Sánchez (Santullano)"

dispatcher.executeDispatch(document, ".uno:InsertText", "", 0, args1())

end sub

Tenemos dos macros (Sub InfoEscolar1 y Sub InfoEscolar2) que son exactamente iguales, a excepción de la diferencia de nombre y curso que ya identificamos antes. Poca opción nos da esto para ahorrar tiempo. ¿Cómo podemos usar variables en este caso?.

Con el tiempo aprenderemos que una macro en realidad  hace uso de variables, pero por ahora las que emplea no nos resuelven el problema. Y esta es la principal limitación de las macros, motivo por el que necesitamos aprender a trabajar con OOo Basic, incluso para mejorar (y simplificar) el uso de macros.

Como ya sabemos crear un script en OOo Basic, en esta entrada vamos a avanzar lo suficiente para resolver el problema a Mercedes:
  • A continuación de la expresión dim dispatcher as object vamos a crear una línea en blanco (Intro) (en realidad dos líneas).
  • Y escribimos Dim sNombre As String en la primera y Dim sCurso As String en la segunda (3). Ya tenemos creadas nuestras variables.
  • A continuación buscamos línea...

args1(0).Value = "Juan es actualmente alumno de 4º de E. Primaria del C.P. Aurelia Sánchez (Santullano)"

  • Y sustituimos  "Juan es actualmente alumno de 4º de E. Primaria del C.P. Aurelia Sánchez (Santullano)" por sNombre & " es actualmente alumno de " & sCurso & " de E. Primaria del C.P. Aurelia Sánchez (Santullano)" (es importante respetar el uso de las comillas y los espacios iniciales)
Con esto la segunda macro ya no es necesaria, así que la podemos borrar.

Mercedes dispone ya de variables en sustitución de los datos (nombre y curso), pero aun no puede sacar todo el partido posible de su descubrimiento: necesita un medio para introducir los datos concretos (Juan y Luis, por ejemplo). Para ello tiene que aprender a dar valor (asignar contenido o datos) a las variables, para ello...
 usar una función OOo Basic llamada InputBox(), asociándola a cada una de sus variables. Vemos cómo.
  • A continuación de Dim sCurso As String generamos un salto de línea (mejor dos para que el código sea más visible) y escribimos estas dos líneas:

sNombre = "Juan"
sCurso = "4º" 

Con ellas estamos diciendo a OOo Basic que almacene en el espacio de memoria RAM identificado como sNombre el dato "Juan", de modo que cuando aparezca la expresión sNombre acceda a ese espacio de memoria, recupere su contenido (el dato "Juan" en este caso) y haga con él lo que corresponda (en nuestra "macro" escribir Juan antes de la cadena " es actualmente..."). Y lo mismo con sCurso.

Usar este procedimiento no es la mejor opción posible, ya que obliga a Mercedes a acceder al IDE y realizar las asignaciones pertinentes para cada informe, así que mejor buscamos otra solución más funcional: usaremos la función OOo Basic llamada InputBox(), asociándola a cada una de las variables. Vemos cómo:

  • Sustituimos  sNombre = "Juan" por sNombre = InputBox("Nombre del alumno"
  • Y hacemos lo mismo con sCurso
Ahora Mercedes ya no tiene que acceder al IDE, es suficiente escribir el nombre (y el curso) del alumno en espacio disponible en la ventanita emergente que genera la función InputBox() y que tendrá a su disposición de forma automática una vez que llame a la macro (Herramientas | Macros | Ejecutar macro)

Aunque parezca poco, en esta entrada hemos avanzado mucho:
  • Hemos accedido a una macro e identificado en ella la información que nos interesa.
  • Hemos aprendido a crear (declarar) y usar (asignar valor y sustituir el dato concreto por la variable) variables.
  • Y hemos automatizado y generalizado la creación de un documento combinando una macro con unas variables, lo que equivale a decir que hemos aprendido (de momento empezado a aprender) cómo superar las limitaciones de las macros mediante su tratamiento con OOo Basic.
  • Además hemos utilizado una función que facilita la fase Input del proceso básico de un script (Input - Procesamiento - Output) (4)
Evidentemente lo aprendido hasta ahora sobre las variables no es más que el principio, pero en las entradas que siguen seguiremos aprendiendo mucho más sobre ella. Por el momento te dejo para que descargues el documento [loPrimero.ods] con la macro modificada (InfoEscolar) según los pasos seguidos en esta entrada para que puedas estudiarla y crear tú las réplicas que te parezca (5).

NOTAS

(1) Una Mercedes real posiblemente se quedara aquí y se limitara a marcar los espacios de los datos que varían, manteniendo el resto del contenido, a modo de texto mutilado. No es mala opción y a la altura del proceso de aprendizaje en que nos movemos es posible que incluso sea la mejor opción. Excepción hecha del uso de la funcionalidad Combinar correspondencia, siempre que el documento no sea muy complejo. De todos modos (posiblemente sin saberlo) Mercedes está trabajando "manualmente" con variables (y constantes). No obstante nosotros vamos a darle más recorrido el tema y hacerlo un poco más complejo. Complicar lo sencillo es, a veces, una buena forma de aprender. 

(2) En realidad, aun en esta caricaturización de la situación crear una macro sí supone un ahorro de tiempo. Si el documento tiene cierta extensión, se aprecia la ventaja (relativa, pero real) que tiene Grabar macro: crear una macro que le dé forma y contenido evita tener que escribirlo todo desde cero. También es más estable, seguro y manejable que trabajar con un documento-modelo. Es necesario, eso sí, utilizar (por ejemplo) Editar | Buscar y reemplazar para ir modificando los datos que varíen (quedémonos con esto: datos que varían)

(3) También podemos escribir Dim sNombre As String, sCurso As String, pero por ahora nos interesa diferenciar ambas expresiones. Además seguramente habrás pensado que "alumno" no es un término correcto cuando tengamos que hacer el informe de Rosa, con lo que también podría ser considerada una variable. Pero, por didáctica nos limitaremos a las dos variables dichas.

(4) Como sin duda Mercedes es inteligente, se habrá dado cuenta además que, limpia de texto irrelevante, la sintaxis de la macro le permite crear todos los textos que se imagine, siendo suficiente con sustituir el párrafo de nuestra macro por cualquier otro texto, el cual puede haber creado previamente (copiar y pegar) o crearlo directamente sobre en el IDE. Esto incluye el uso de todas las variables que le interese. Sólo necesita copiar la macro, cambiar su nombre (Sub NuevoNombre) para no perder la macro original y realizar en args1(0).Value = a sustitución que propuse antes. Y todo ello sin necesidad de usar de nuevo Grabar macro. Eso sí que es un ahorro de tiempo.

(5) Para mayor claridad del ejemplo he borrado de la macro original todos los comentarios, que ahora son innecesarios, aunque es buena praxis comentar el código. Ya aprenderemos cómo. Originalmente esta macro se llamaba InfoEscolar1, pero como ahora no necesitamos crear una macro por cada informe que queramos crear, pasa a llamarse InfoEscolar.

jueves, 25 de abril de 2024

OOo Basic

Primero, las macros.

El lenguaje OOo Basic se anuncia como lenguaje de macros, pero aunque esta consideración sea correcta en el sentido amplio que se da al término "macro", en sentido estricto y también práctico, puede dar lugar a confusión y conlleva un reduccionismo que afecta negativamente a la valoración de la potencialidad que tiene el conocimiento del lenguaje.




Por eso prefiero considerarlo simplemente como un lenguaje de programación orientado y delimitado a la creación de script dentro de la suite ofimática LibreOffice (1). De hecho uno puede trabajar con macros desde la funcionalidad Grabar macros y desconocer absolutamente OOo Basic, aunque lo que genera esa funcionalidad es precisamente una forma particular de código de este lenguaje.

El término "macro" es una simplificación de "macroinstrucción", que se puede entender como la ejecución unitaria y sucesiva de un conjunto de órdenes o instrucciones. Aunque también podemos entenderla instrumentalmente como lo que resulta de hacer uso de la funcionalidad Grabar macro

Es por eso considero que decir que OOo Basic es un  lenguaje de macros resulta insuficiente cuanto menos. 

Cierto es que el resultado de grabar una macro no deja de ser automatizar la ejecución de una serie de instrucciones que se presentan individualizadas e independientes cuando trabajamos directamente con el servicio (Writer, por ejemplo); pero OOo Basic es mucho más: permite hacer mucho más y resulta mucho más complejo, también útil y eficiente.

De hecho, mientras que para crear una macro no hace falta más que tener clara la secuencia de acciones que deseamos automatizar y activar la funcionalidad Grabar macro (2), crear un script, una subrutina o una función ni es posible desde Grabar macro ni se puede prescindir de conocer el lenguaje con el que se va a trabajar (en nuestro caso y como primera opción, OOo Basic).

Así que pasar de  crear una macro a crear código (script) es pasar de utilizar una funcionalidad avanzada incorporada al servicio (3) a adentrarse en el mundo de la programación. Para ello, como sabemos, hace falta lógica de programación y conocimiento del lenguaje. A facilitar lo primero dedicamos la sección [Programación] de este blog (también ésta en la que estamos) y la actual a iniciarnos en el conocimiento del lenguaje OOo Basic. En realidad ambas son complementarias.

Pero volvamos a las macros, porque a pesar de sus limitaciones (4) generan un abanico de posibilidades que posiblemente pasen desapercibidas al principio, cuando sólo somos usuarios de Grabar macro. Estas posibilidades se esconden en el IDE, espacio de trabajo que queda oculto a primera vista, especialmente si la propia funcionalidad Grabar macro permanece también oculta.

Esa posibilidad no es de descartar, ya que no tiene por qué estar activada en la configuración inicial de LibreOffice, así que será mejor que empecemos rasgando estos velos.

Sabemos que para acceder a Grabar macro debemos activar el menú Herramientas | Macros. La primera de sus opciones es precisamente Grabar macro, pero cabe la posibilidad de que no aparezca (5). En ese caso, lo primero que tenemos que hacer es hacerla visible. Para ello:
  • Activamos la opción Herramientas | Opciones.
  • Dentro de las que se nos ofrecen activamos LibreOffice | Avanzado
  • Y en Opciones Java (a la derecha del menú anterior) encontramos Funcionalidades opcionales.
  • La funcionalidad Activar grabación de macros (limitada) se encontrará no seleccionada. 
  • La seleccionaremos (clic en el check list correspondiente) y haremos clic en Aplicar y en Aceptar para cerrar la ventana del menú.
Ahora Grabar macro estará disponible y se visualizará como primera opción de Macros, lo que nos permite activar la llamada grabadora de macros, que consiste en una pequeña ventanita emergente...


... en cuyo botón Finalizar grabación deberemos hacer clic cuando hayamos finalizado la secuencia de acciones que queremos automatizar. Lo que obtenemos como resultado es algo que resulta ciertamente confuso al no iniciado: visualizamos sin saberlo un acceso temporal al IDE, pero si no sabemos nada de su existencia es fácil que nuestra macro termine perdida sin que sepamos cómo acceder a ella cuando la necesitamos. Es necesario, por tanto, comprender el proceso a seguir.

Para ello vamos a simular que creamos una macro desde un nuevo documento. Por defecto, este documento no dispone aun de espacio propio para archivar la macro que creemos, algo que resulta imprescindible si deseamos que las macros queden vinculadas al propio documento (6).

Si creamos una macro activando Grabar macro y finalizamos el proceso tal y como expliqué antes, emerge automáticamente una ventana (una de las visualización del IDE, en realidad) que, por defecto, posicionará nuestra macro no en el documento desde el que la estamos creando, sino en Mis macros. Podemos guardarla ahí, pero es posible que después no sepamos cómo recuperarla, así que, al menos para empezar, es preferible guardarla en el propio documento.

Para ello, antes de finalizar el proceso, nos posicionaremos en el icono que representa nuestro documento (se sitúa al final del listado de componentes) y hacemos clic en Módulo Nuevo, aunque es suficiente con hacer clic en Guardar, ya que al no existir ningún módulo (ni carpeta o directorio), LibreOffice lo crea por defecto (Module1), después de crear el directorio Standard.

Ahora nuestro archivo consta (en el IDE) de una carpeta Standard y un módulo Module1 donde está guardada nuestra primera macro. Las siguientes que grabemos lo será en esta ubicación, pero deberemos tener cuidado de darles un nombre propio, ya que de no hacerlo asume Main (principal) como nombre por defecto para esta nuestra segunda macro (7)

Hasta aquí ya sabemos crear macros, pero hace falta usarlas, cosa que requiere un nuevo ajuste en el funcionamiento que por defecto tiene LibreOffice. Me refiero al nivel de seguridad con el que está inicialmente configurado, que impide la activación de macros (8). Como seguramente este será nuestro caso (en estos momentos), deberemos modificar esa configuración inicial. Para ello:
  • Volvemos al menú Herramientas | Opciones
  • Seleccionamos ahora Seguridad y (a la derecha) hacemos clic en Seguridad de macros.
  • Se activa una ventana emergente que nos da cuatro opciones.
  • Personalmente opto por Medio, por el control que me da sobre la activación o no de las macros. No recomiendo la opción Bajo por los riesgos que comporta ni Alto por lo que complica el uso de macros personales, que es nuestro objetivo.
  • Sólo nos resta hacer clic en Aceptar para finalizar este proceso.
A partir de este momento, cuando carguemos en memoria un documento que contenga macros, antes de darnos acceso a él, LibreOffice nos informará que el documento contiene macros y nos dará la doble opción de activarlas no inhibirlas. Dado que pretendemos trabajar con nuestro código o con código de confianza (y sólo en esos dos casos) lo lógico es que permitamos la activación de macros, pero siempre será nuestra decisión y responsabilidad.

Toca ahora acceder a las macros que acabamos de crear para probar su funcionamiento. Para ello seguimos trabajando meramente con las funcionalidades de LibreOffice, ajenos aun a la creación de código y al código que, sin saberlo, hemos creado. Para ello:
  • Seleccionamos la opción Herramientas | Macros | Ejecutar macro
  • En la ventana emergente Selector de macros nos posicionamos en el icono que representa nuestro documento y hacemos clic en la crucecita que precede al icono.
  • Se despliega su estructura de carpetas (biblioteca o librería Standard, es como se denomina a lo que aparece a continuación) y hacemos de nuevo clic en la crucecita que precede a Standard (9).
  • Se muestra el contenido de Standard, en estos momentos únicamente Module1.
  • Haciendo clic en Module1 se muestra en Nombre de macro (ventana a la derecha de Biblioteca) el listado de las macros que hayamos creado.
  • Haciendo clic en una de las macros esta se activará y ejecutará en el documento la secuencia de acciones que hayamos grabado.
Estaremos un rato entretenidos grabando y activando macros; es necesario para familiarizarse con esta funcionalidad y con las posibilidades que tiene generar nuestras propias macros, pero aunque resulte entretenido y útil para determinadas necesidades, no tardaremos en descubrir también sus limitaciones (10). Por suerte OOo Basic no sólo nos permite superar esas limitaciones; también nos va a permitir integrar las macros como parte de nuestro propio código, con lo que lo hecho hasta ahora no es sólo un inocente divertimento (los hay mucho mejores, claro está) ni tiempo perdido.

Hasta aquí hemos aprendido a crear macros mediante la funcionalidad Grabar macro de LibreOffice, demostrando saber usar funcionalidades complejas de la suite; hemos activado esa opción (si no se encuentra disponible); sabemos guardar nuestras macros en el documento desde el que las creamos; sabemos también regular el nivel de seguridad con el que queremos trabajar en LibreOffice y, finalmente, somos capaces de activar nuestras macros para que trabajen por nosotros. 

No son pocas las habilidades que hemos desarrollado en tan poco tiempo, pero lo verdaderamente interesante y útil está aun por llegar. De momento, podemos dar un formato complejo a un texto, crear tablas, listados y contenido, pero también hemos podido comprobar que si queremos dirigir un documento a una persona concreta, citar por su nombre a un niño o a un profesor, informar de una hora y un lugar concretos o comentar los resultados del alumno en un área del currículo nos vemos obligados bien a crear una macro específica para cada caso, situación o contenido concreto... o a modificar el texto que crea la macro sustituyendo unos datos por otros. En estas circunstancias, Grabar macro es de relativa ayuda... o de ninguna. 

Como ya dije, OOo Basic nos permite superar esas limitaciones. Por eso es importante que aprendamos ahora los elementos básicos de este lenguaje. Una vez que los hayamos aprendido, podremos volver sobre nuestras macros (11) para aprovechar mucho y bien lo que nos aportan. Pero, de momento, deberemos hacer un alto en este camino y recorrer otro más largo, pero necesario y sumamente interesante. No se trata precisamente de la travesía de ningún desierto, aunque se requiere paciencia, estudio, práctica y esfuerzo. Merece la pena.

NOTAS

(1) También, y primeramente, OpenOffice. 

(2) Para los amigos: secuencia Herramientas | Macros | Grabar macro.

(3) Crear macro no es la única ni quizá la más útil de esa categoría de funcionalidades. Desde la perspectiva del usuario, particularmente interesante me parece Combinar correspondencia o el uso de formularios, ya que permiten dotar a los documentos de recursos muy interesantes de cara al trabajo de los profesionales de los SEO. No obstante, Grabar macro es la puerta lógica de acceso a la programación mediante OOo Basic, y eso nos permite ir mucho más allá en la creación de recursos ajustados a nuestras necesidades de lo que podemos avanzar con aquellas.

(4) De por sí, una macro no aporta gran cosa de utilidad, salvo quizá en procesos complejos de formato y la automatización de la escritura de contenido invariable. Es necesario recurrir al uso de variables para personalizar el contenido textual, algo que requiere conocimiento del lenguaje de programación. 

(5) En ese caso, la primera opción visible será Ejecutar macro, pero el usuario no iniciado en el uso de macros no obtendrá ninguna utilidad de ella, ya que no se pueden ejecutar macros que no se han creado. 

(6) Tendremos ocasión de comprobar que ésta no es la única opción, pero por el momento eso no nos interesa ni nos resuelve nuestro problema actual; al contrario, puede resultar engañoso.

(7) La primera es posible que haya sido guardada por defecto como Macro1. Si no queremos sustituirla por la segunda macro no la seleccionaremos. Hay que observar que en Nombre de macro consta aquella en que se ubica la funcionalidad Grabar macro, pero podemos cambiar ese nombre por cualquier otro (sin espacios en blanco), de modo que no sustituyamos una macro ya creada por la nueva.

(8) Esto es debido al riesgo que comporta el uso de código no seguro, categoría en la que se considera están las macros, dado que potencialmente pueden haber sido pensadas como software malicioso. Dado que somos nosotros quienes creamos macros en nuestro beneficio, este no es el caso, pero LibreOffice no lo sabe y cautelosamente no lo presupone.

(9) Como dije antes (7), y ahora concreto más, al crear nuestro Module1 se crea automáticamente este directorio que, por su naturaleza de contender de código, se denomina Biblioteca en español, pero que se conoce más como Librería por esa fea costumbre que tenemos los hispanos de traducir literalmente los términos ingleses (Library).

(10) En cuanto a utilidad estoy pensando en el formateo de documentos o en su estructuración, por ejemplo. Las limitaciones son evidentes, pero Grabar macro no deja de ser una buena solución definitiva en ciertos casos, provisional en otros y complementaria en tercer lugar.

(11) En ese momento, no muy lejano, sobre su código, que por ahora nos es completamente desconocido.