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

domingo, 14 de julio de 2024

Procedimientos. datos.

Posicionarse en una hoja mediante OOo Basic

Con OOo Basic podemos trabajar sobre cualquier hoja del libro Calc con independencia de que sea sobre la hoja activa o sobre cualquiera de las demás. Eso supone una importante ventaja a la hora de crear un docap; pero muchas veces necesitamos posicionarnos visualmente sobre una hoja determinada. Mediante macros ya sabemos resolver este problema, pero también es conveniente hacerlo desde un script. En esta entrada vamos a aprender cómo.


Ya hemos visto [cómo trabajar con las hojas] de un libro Calc, pero esta opción no nos facilita visualizar la hoja (convertirla en la hoja activa), salvo que estemos trabajando sobre ésta. Para resolver esta dificultad hemos recurridos hasta ahora a una subrutina basada en macro, pero necesitamos hacerlo directamente desde un script OOo Basic. Veamos cómo esto es posible.

En principio podemos hacerlo identificando la hoja que deseamos visualizar (convertir en hoja activa) bien por su nombre, bien por su índice. El procedimiento es muy similar, en lo fundamental, así que explicaré una de las dos formas (por el nombre) y, sobre ese mismo script, indicaré las modificaciones que hay que realizar para acceder por el índice de la hoja.

Sub Ir_Hoja2Nombre ' Por el nombre

Dim DocCalc As Object
Dim Hoja As Object
DocCalc = ThisComponent
Hoja = DocCalc.getSheets().getByName("Hoja2")
DocCalc.CurrentController().SetActiveSheet(Hoja)
End Sub

Declaramos dos variables (DocCalc y Hoja), ambas de tipo Object, para asignar respectivamente el objeto documento Calc a la primera (DocCalc = ThisComponent) y el objeto Hoja a la segunda (Hoja = DocCalc.getSheets().getByName("Hoja2")); además identificamos es ésta a la hoja por su nombre mediante el método getByName() (.getByName("Hoja2")) (1)

Ya sólo nos falta convertir esa hoja seleccionada del libro en HojaActiva; para ello está la instrucción DocCalc.CurrentController().SetActiveSheet(Hoja). Con ella...
  • mediante el método CurrentController() del objeto DocumentoActual (ThisComponent) que hemos asignado a la variable DocCalc (DocCalc.CurrentController())...
  • implementamos a su vez el método SetActiveSheet(), que permite asignar la condición de HojaActiva al valor del parámetro asignado, que no es otro que el contenido en la variable objeto Hoja (SetActiveSheet(Hoja))
Si queremos realizar esta misma operación a partir del valor índice de la hoja, modificaremos la asignación de objeto a la variables Hoja, sustituyendo el método getByName() por el método .getByIndex() (2)

Documento. En [este libro Calc] encontrarás el código explicado en la entrada. En realidad contiene dos script: uno basado en el nombre de la hoja y otro en su valor índice.

NOTAS

(1) En nuestro caso, la hoja llamada Hoja2. Sin duda te habrás percatado de la posibilidad de convertir este script en una subrutina, transformado el nombre de la hoja en su parámetro. 
(2) Al que pasamos un valor numérico como parámetro, en nuestro caso, por mantener la similitud con el script anterior, ese valor es 1.

viernes, 12 de julio de 2024

Procedimientos. Datos.

Calc. Uso de funciones dentro de los script.

Sabemos que Calc cuenta con un número elevado de funciones que podemos utilizar en este servicio para trabajar con datos, numéricos o alfanuméricos. Podemos reemplazar estas funciones mediante código OOo Basic, pero también tenemos la posibilidad de incluirlas en nuestros script, aprovechando así toda su potencia y ahorrándonos trabajo (1). 


Encontré el código que explicaré en esta entrada buscando precisamente cómo aprovechar las funciones Calc  en el código OOo Basic y, por lo que parece, no fui el único que se planteó una pregunta parecida (2). Cierto que no me ayudó a resolver el problema que tenía planteado, pero me ha parecido una solución muy interesante y de mucha utilidad, así que la comparto (3).

La base fundamental de este procedimiento consiste en hacer referencia en los script a las funciones Calc, pero no es la denominación con que se nos presentan en el servicio en su Asistente de funciones, sino en inglés; detalle éste importante para que funciones el código (4).

Se plantean dos opciones básicas: la que incorpora la función Calc en el script y la que lo hace mediante una función OOo Basic. Esta diferencia conlleva mucho más, como podremos ver más adelante, pero como primer criterio de diferenciación es relevante para que nos vayamos poniendo en situación.

Estas dos formas de trabajo se ejemplifican en los siguientes script. En el primero llamamos a una función para que "escriba" su resultado en una celda y después accedemos al contenido de esa celda para aprovechar el resultado de la función.

Sub PruebaFuncionCalc1a

Dim oHoja As Object
Dim dResulta As Double

oHoja = ThisComponent.CurrentController.ActiveSheet
oHoja.getCellRangeByName("B12").Formula = "=SUM(A1:A12)"

dResulta = oHoja.getCellRangeByName("B12").Value

MsgBox dResulta

End Sub

Tras declarar dos variables (oHoja dResulta) y acceder al objeto Hoja (oHoja = ThisComponent.CurrentController.ActiveSheet), implementamos la fórmula (=SUM(A1:A12)) en la celda B12. Para ello añadimos al identificador de la celda el identificador Formula (oHoja.getCellRangeByName("B12").Formula = "=SUM(A1:A12)")

Una vez que la fórmula actúa y entrega su resultado en la celda establecida, accedemos a dicho resultado asignándolo a la variable dResulta (dResulta = oHoja.getCellRangeByName("B12").Value) (5). En este caso, lo que hacemos con el valor obtenido es mostrarlo mediante MsgBox (MsgBox dResulta), pero podríamos utilizarlo de cualquier otra forma, dependiendo del algoritmo de nuestro script.

El segundo modo de trabajo implica el uso de una función (FuncionCalc()) que es llamada desde un script (PruebaFuncionCalc2). Empecemos explicando el script:

Sub PruebaFuncionCalc2

Dim oHoja As Object
Dim dSuma As Double
oHoja = ThisComponent.getSheets().getByName("Hoja1")
dSuma = FuncionCalc( "SUM", Array(oHoja.getCellRangeByName("A1:A12")) )
MsgBox dSuma
 
End Sub

Tras declarar las dos variables necesarias (oHoja y dSuma) y acceder al objeto Hoja (oHoja = ThisComponent.getSheets().getByName("Hoja1")) recurrimos a la función (FuncionCalc()), asignando el dato que devuelve ésta a la variable dSuma. Dado que se trata de una función, cuenta (en este caso) con dos parámetros, que son los que pasamos por valor en la formulación de la llamada a la función (FuncionCalc( "SUM", Array(oHoja.getCellRangeByName("A1:A12")) )):

  • El primero es el nombre de la función Calc (en inglés) ("SUM")
  • Y el segundo, mucho más complejo, es la matriz de datos formada por el contenido del conjunto de celdas A1:A12, esto es: los datos que requiere la función Calc (Array(oHoja.getCellRangeByName("A1:A12"))) (6)

Después utilizamos el resultado devuelto por la función para mostrarlo en pantalla mediante MsgBox (MsgBox dSuma) (7)

 Veamos a continuación el código de la función FuncionCalc():

Function FuncionCalc( Nombre As String, Datos() )

Dim oSFA As Object

oSFA = createUnoService( "com.sun.star.sheet.FunctionAccess" )

FuncionCalc = oSFA.callFunction( Nombre, Datos() )

End Function

Observa que la función tiene dos parámetros, uno de tipo texto y otro una matriz (Nombre As String, Datos()): son los mismos a los que damos valor desde el script (( "SUM", Array(oHoja.getCellRangeByName("A1:A12")))).

Además, la función cuenta con una variable de tipo objeto (oSFA) a la que se asigna el objeto UnoService de acceso a las funciones de Calc FunctionAccess. (createUnoService( "com.sun.star.sheet.FunctionAccess")) Esta asignación se basa en la estructura típica de acceso a las funciones nucleares de la suite LibreOffice, que, como sabes, está escrita en parte en Java, esto es: en un lenguaje orientado a objetos (POO)

Siguiendo la sintaxis de las funciones, asignamos al identificador de la actual el resultado de aplicar la función nombrada a la matriz de datos; como recordarás, ambos han sido pasados por valor desde el scriot (FuncionCalc = oSFA.callFunction(Nombre, Datos())). De este modo la función devuelve al script, el resultado de dicha función. (8)

Dado que sólo he sabido manejar adecuadamente el primer modo de trabajo (ver nota 8), me limitaré a exponer cómo transformarlo para trabajar con otras funciones. Llamo a estos script PruebaFuncionCalc1bPruebaFuncionCalc1c respectivamente. En el primero empleo una función Calc que actúa sobre un dato unitario (la función RAIZ()) y en el segundo trabajo con una función que trabaja con datos alfanuméricos, posicionados en una colección del celdas (no una matriz) (la función CONCATENAR()) (9).

Empecemos por el primer script y la función RAIZ()

Sub PruebaFuncionCalc1b

Dim oHoja As Object
Dim sResulta As Double

oHoja = ThisComponent.CurrentController.ActiveSheet
oHoja.getCellRangeByName("B15").Formula = "=SQRT(A15)"

dResulta = oHoja.getCellRangeByName("B15").Value

MsgBox dResulta

End Sub

 Como ves hay poco que añadir a lo visto en la explicación del script de base (PruebaFuncionCalc1a): únicamente sustituimos la expresión de la función anterior (SUM()) por la actual (SQRT()) (en inglés), con lo que no tienes mayor dificultad que recurrir al Asistente para funciones de Calc y traducir el nombre de la función al inglés. Los cambios de parámetros van incluidos en el procedimiento: para SUM() era necesaria una matriz de datos ("=SUM(A1:A12)") y para SQRT() únicamente una referencia a celda ("=SQRT(A15)")

El script PruebaFuncionCalc1c muestra la validez universal del procedimiento de sustitución que te acabo de explicar:

Sub PruebaFuncionCalc1c

Dim oHoja As Object
Dim sResulta As String

oHoja = ThisComponent.CurrentController.ActiveSheet
oHoja.getCellRangeByName("B20").Formula = "=CONCATENATE(A20;A21;A22)"

dResulta = oHoja.getCellRangeByName("B20").String

MsgBox dResulta

End Sub

De nuevo, es suficiente con escribir la sintaxis de la función Calc en la posición adecuada dentro del script para obtener el resultado deseado. 

Pero aun hay más: podemos combinar varias funciones dentro de la misma expresión, del mismo modo que es posible construir una combinación de funciones Calc. El script PruebaFuncionCalc1d es una prueba de ello.

Sub PruebaFuncionCalc1d

Dim oHoja As Object
Dim dResulta As Double

oHoja = ThisComponent.CurrentController.ActiveSheet

oHoja.getCellRangeByName("B13").Formula = "=SQRT(SUM(A1:A12))"

dResulta = oHoja.getCellRangeByName("B13").Value

MsgBox dResulta

End Sub

Aquí combinamos las funciones SQRT() y SUM() para obtener una función combinada en la que sobre la suma resultante de la matriz de datos A1:A12 solicitamos el cálculo de su raíz cuadrada ("=SQRT(SUM(A1:A12))"). El resultado se escribe en la celda B13. Como puedes comprobar, la sintaxis de la instrucción únicamente varía en la forma en que se llaman a ambas funciones, que es la misma que escribimos sobre la Línea de entrada de fórmulas de Calc.

Por tanto resulta evidente la ventaja de este modo de implementar funciones Calc en los script OOo Basic: es suficiente con escribir la fórmula según su sintaxis Calc, sustituyendo el nombre de la función por su equivalente en inglés. Es además importante establecer correctamente la referencia a los datos con los que trabajarán dichas funciones.

Documentos.

Pongo a tu disposición dos documento. El primero [FormulCalc.ods] es el documento Calc en el que puedes encontrar los ejemplos explicados en la entrada. El segundo [WIKI de OpenOffice] el enlace a la web donde encontrarás el listado de funciones Calc en inglés y en español.

NOTAS

(1) En algunas ocasiones esto puede ser así, pero en otras es preferible generar procedimiento propios, basados en OOo Basic, ya que son mucho más potentes y flexibles. No obstante, no es de despreciar lo que el uso de las funciones Calc nos puede ayudar a resolver problemas (especialmente de cálculos complejos) para los que no dispongamos de solución en un momento concreto. Toda ayuda es bienvenida.

(2) El material procede en primera instancia de la Web OpenOffice (en español), aunque los autores reconocen el mérito a Mauricio Baeza, del que son deudores. Y yo de ambos.

(3) A lo que aportan los autores anteriores añado de mi parte mi explicación del funcionamiento del código. Esta explicación no está disponible al menos en la primera de las referencias.

(4) Una contribución que añado para facilitarte el trabajo: el listado de funciones Calc en inglés y en español, cortesía de la WIKI de OpenOffice.

(5) Utilizamos .Value por tratarse de un resultado numérico. En caso de emplear una fórmula que devuelva un contenido alfanumérico emplearíamos .String

(6) Si tienes curiosidad, puedes comprobarlo escribiendo esa misma función en la Línea de entrada (de fórmulas) de Calc.

(7) Observa que, a diferencia del modo anterior, ahora no escribimos el resultado de la función en ninguna celda; no como paso previo para acceder a su resultado. Podríamos hacerlo, pero sería ya una decisión a posteriori, equivalente a mostrarlo por pantalla, que es la solución por la que optamos en este caso. 

(8) En principio podríamos sustituir la función SUM() por cualquiera otra que utilice como datos una matriz similar a la que emplea ésta, pero no resulta tan sencillo trabajar con funciones que actúan sobre otro tipo de estructuras. Al menos yo no he sabido hacerlo. Supongo que habrá forma de hacerlo y cuando lo averigüe lo expondré. 

(9) Te sugiero que, antes de seguir, refresques tu memoria haciendo uso de ambas funciones desde Calc. Así te resultarán familiares y comprenderás mejor los script en los que se incluyen.

viernes, 26 de abril de 2024

OOo Basic

Primer script

En esta entrada vamos crear nuestro primer script con OOo Basic, el típico script con el que comienza toda andadura por el aprendizaje de los lenguajes de programación. Pero para ello deberemos saber dónde.


Al crear una macro nos hemos acercado al IDE, pero no terminamos de entrar en él porque no era necesario. Ahora sí.

El IDE (Entorno de Desarrollo Integrado) es la utilidad que nos permite trabajar con un lenguaje de programación. El ser OOo Basic un lenguaje de script interno y delimitado por la suite LibreOffice, su IDE se ubica y es accesible desde el propio entorno LibreOffice; desde la interface general y/o desde las interfaces de cada uno de sus servicios.

Nosotros vamos a trabajar (de momento) desde Writer, así que empezaremos creando un nuevo documento. Le daremos nombre (loDocumento1) y lo guardaremos en una carpeta que previamente habremos creado en nuestro Escritorio (1). De este modo empezaremos desde cero, que es la mejor forma de empezar.

Y lo haremos accediendo a Herramientas | Macros | Organizar macros | BASIC (2). Este es nuestro primer paso porque, al partir de un nuevo documento, como ya sabes, aun no se definido en él un espacio específico para nuestras macros y script.

En la ventana emergente hacemos clic (de nuevo) en Organizador y en la nueva ventanita seleccionamos el icono de nuestro documento (loPrimero.odt), en la crucecita que precede al nombre, y después en a que precede a la carpeta (Biblioteca) Standard  y hacemos clic en Nuevo (3). Surge una nueva ventanita que contiene un campo de texto con la palabra Module1 y tres botones: hacemos clic en Aceptar y automáticamente se crea Module1 dentro de Standard. Clic en Cerrar.

Si hacemos clic en Nuevo (ahora referido a macro/script, accederemos al contenido de las tres carpetas disponibles en el IDE: Mis macros y diálogos, Macros y diálogos de la aplicación y loPrimero.odt: ésta es la que nos interesa ahora. Seguimos el proceso ya conocido de selección y despliegue de componentes y terminamos accediendo a una pantalla  casi vacía: 

REM  *****  BASIC  *****

Sub Main

End Sub

Este será el "espacio" (documento) en el que crearemos nuestros script. Por el momento nuestro primer script, justo entre las instrucciones Sub Main y End Sub. Cuando finalicemos esto será lo que veamos:

Sub Main

    print "OOo Basic para orientadores"

End Sub

No es el típico saludo "Hola Mundo" pero cumple su misma función: anunciar(nos) que estamos empezando a aprender OOo Basic.

Ahora sitúa el cursos dentro del Sub y haz clic en la flechita verde situada encima de la palabra REM, o en Ejecutar | Ejecutar: obtendrás una ventana emergente que contiene la frase que hemos escrito. Este es nuestro primer script. Por ahora suficiente (4)



NOTA

(1) Es una sugerencia; tú puedes crearlo con el nombre que te parezca y guardarlo en donde creas oportuno. A tu cargo también la organización interna de esta carpeta y recordar dónde guardas tus archivos.

(2) Verás otras opciones de lenguajes, pero ahora no nos interesan, así que nos centramos en BASIC, que no es otra cosa que OOo Basic. Podemos nombrar nuestro módulo como deseemos, pero por ahora no nos vamos a detener en estos detalle, así que aceptaremos el nombre que se nos propone (Module1)

(3) Como vamos a crear un módulo, y es la opción por defecto, no me voy a referir ahora a las otras opciones (Diálogos y Bibliotecas)

(4) Cuando queras finalizar y acceder de nuevo al documento, sigue esta secuencia: Archivo | Guardar o Archivo | Cerrar. La segunda cierra el IDE sin guardar lo que hemos creado, así que te recomiendo que utilices la primera opción para no perder el trabajo realizado. Para finalizar del todo cerraremos nuestro documento loPrimero.odt de igual modo que cerramos cualquier otro documento Writer, guardando los cambios.

lunes, 30 de octubre de 2023

OOo Basic. Writer

 Script y subrutinas de escritura

  • Código básico:

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.

  • Subrutina de composición de varios párrafos (Código)

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.

martes, 24 de octubre de 2023

OOo Basic. Script

 Subrutinas creadas a partir de macros

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.




Por recordar brevemente lo dicho en su momento, una subrutina no devuelve un dato o valor (lo que la diferencia de una función), sino que desarrolla una acción. 


La subrutina realiza una acción, momento en el que el control de proceso pasa a ella. Esta imagen representa el proceso, incluyendo esa especie de corte en la ejecución del proceso principal, momento en que entra en acción la subrutina, la cual, una vez finalizado su cometido, devuelve el control a la macro o script principal.

Visto y recordado esto, nos centrarnos ahora en el tema que nos ocupa ahora: ¿ qué procedimiento o procedimientos podemos seguir para transformar una macro en una subrutina?.

Esta pregunta se responde en plural: existen varios procedimientos y diferentes variaciones de cada uno de ellos. Yo me voy a limitar a diferenciar y exponer tres de ellos, los que considero que se ajustan mejor a la macro originaria. Según este criterio serían tres las variaciones fundamentales entre las macros, lo que da origen a tres procedimientos básicos de conversión a subrutina: 
  • Las macros que contienen explicitación de parámetros (matriz nombre-valor argsX(y))
  • Las macros que son susceptibles de ser ejecutadas mediante estructuras cíclicas (for...Next), esto es: de repetir la acción que desarrollan.
  • Y las macros susceptibles a ser tratadas mediante la condicionalidad (If)
Veamos cada una de ellas, empezando por las macros más simples que incluyen parámetros y en las que tomo como ejemplo la macro de posicionamiento [listado numérico] (1): 
  • matriz desglosada clave+valor:
dim args1(0) as new com.sun.star.beans.PropertyValue
	args1(0).Name = "On"
	args1(0).Value = true
  • Orden o instrucción asociada a dispatcher:
dispatcher.executeDispatch(document, ".uno:DefaultNumbering", "", 0, args1())

Es el contenido o valor del componente .Value (en el ejemplo anterior true) el que podemos establecer como variable-parámetro en la creación de la subrutina basada en macros de este tipo, procediendo como sigue:

  • Denominamos la subrutina añadiendo un paréntesis al final de su enunciado
Sub msbIndiceNumerico()

  • Declaro la variable-argumento bOpcion, que es de tipo booleano, como corresponde en función del valor del elemento de la matriz args1(0).Value

Sub msbIndiceNumerico(bOpcion As Boolean)

  • Y sustituyo el valor true asignado en la macro simple original por dicha variable

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

Las macros mcrBajarLinea y mcrSubirLinea presentan una doble complementariedad: ambas pueden tener valora interno de args1(1).value true o false (se selecciona o no la línea) y ambas son complementarias entre sí (o subimos o bajamos de línea): uno:GoUp vs. uno:GoDown.

Existen varias formas de crear una subrutina, pero me voy a limitar a dos, que son variaciones sobre el mismo tema. La primera se basa en el uso del condicional If e implica en realidad usar dos ejecutores dispatcher dentro de la misma surutina... 

sub msbLinea(bSelect As Boolean,sMov As String)

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 = bSelect
If sMov = "B" Then
dispatcher.executeDispatch(document, ".uno:GoDown", "", 0, args1())
MsgBox "He bajado una linea"
ElseIf sMov = "S" Then
dispatcher.executeDispatch(document, ".uno:GoUp", "", 0, args1())
MsgBox "He subido una línea"
Else
MsgBox "El valor de la variable 'sLinea' no es correcto" 
End If

End Sub
 ... que es llamada desde el script (msbLineaBis(true,"B")) de forma simple (4)

La segunda forma simplifica la formulación de la subrutina...

sub msbLinea(bSelect As Boolean,sMov As String)

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 = bSelect
dispatcher.executeDispatch(document, sMov, "", 0, args1())

End Sub

... y pasa la responsabilidad de definir concretamente la instrucción a  ejecutar a la llamada desde el script (msbLineaBis(true,".uno:GoUp")(5)

Te dejo aquí enlace a la [segunda opción], ya que la considero la que mejor se ajusta al principio básico de conversión de macro simple en subrutina.

NOTAS

(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:

  • El más simple: incluir el valor deseado en la llamada a la subrutina de la macro (msbIndiceNumerico(true)). Este modo de uso, además de ser la más simple, es el más apropiado cuando la macro o script es a su vez sencillo.
  • Y el modo complejo que recomiendo cuando el script es complejo e interesa controlar los valores que se pasan a las subrutinas y a las funciones, y que consiste en lo siguiente:
    • En esa macro/script declaramos una variable del mismo tipo que la variable-parámetro de la subrutina, por ejemplo, Dim bIndice as Boolean
    • Damos valor a esa variable según lo que deseemos hacer (en esta caso, aplicar o eliminar el índice numérico): bIndice = true
    • "Llamamos a la subrutina incluyendo entre paréntesis la variable bIndice: msbIndiceNumerico(bIndice)
(3) Dado que estamos trabajando con estructuras basadas en macros, es necesario utilizar las variables de objeto y los objetos asociados a ellas. He concretado esto como script VarSis. Este script puede ser llamado desde la subrutina o desde el script o macro que la utilice. [Ver como ejemplo].

(4) Si se desea esta llamada puede plantearse de modo interactivo, mediante InputBox() u otra GUI. Aquí omito estas opciones por ser secundarias para el objetivo de la entrada.

(5) En este caso es aun necesario, o cuanto menos conveniente, descomponer el proceso de asignación del segundo valor en dos fases: en la primera se asigna valor (puede hacerse de forma interactiva como en 4) y en la segunda, mediante condicional, dar a la segunda variable de la llamada la expresión técnica precisa. De este modo se evita la comisión de algún error en la asignación del dato (vg, .uno:GoUp)

lunes, 18 de septiembre de 2023

OOo Basic. Script

Crear macros desde el IDE

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 cierto modo de este tema ya se ha hablado en este blog, pero no de forma tan explícita como pretendo ahora, siendo la causa de "retomar" este tema y plantear esta perspectiva, la colección de vídeos que estoy publicando en mi [canal You Tube] dentro de la lista [Competencia Digital Para Orientadores] (aunque sería apropiado que se titulara Ofimática Para Orientadores), en la que estoy presentando el proceso de creación de un docap (documento-aplicación) que automatiza la creación de un instrumento para la comunicación con familias.

Inicialmente genero un docap basado en macros simples empleadas desde un planteamiento modular, obviando la opción simple de crear una macro completa desde Grabar macro, pero haciendo un uso instrumental de esta funcionalidad.

Pretendo en esta entrada enlazar la fase previa, en la que se hace uso exclusivo de Grabar macro, y la estrategia de utilizar esta funcionalidad como ayuda en la creación de docap, aunque la creación de las macros individuales se realizar de forma directa desde el IDE.

Precisamente es esta una buena explicación de la diferencia entre ambas estrategias: 

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.
    • Este enfoque no requiere acceder al IDE y mucho menos entender el código generado por Grabar macro.
    • Incluso nuestro usuario se puede permitir  cometer errores, aunque cuantos menos mejor.
    • Y también favorece el buen desarrollo de la macro tener estudiada la sucesión de acciones a desarrollar.
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.

    • Al contrario del primer enfoque, en este la escritura de textos y la extensión de los mismos no constituye problema alguno, ya que combina el conocimiento del procedimiento (la sintaxis de la macro de escritura) con el copia-pega del texto, lógicamente donde corresponda.
    • Tampoco supone un problema la repetición de las mismas acciones, por frecuentes que sea ésta, ya que sólo necesita grabar una vez cada acción para reutilizarla tantas como sea necesario, haciendo uso del enfoque modular.   

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