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

LENGUAJES. OOo Basic

Funciones Calc dentro de un script


Cuestiones introductorias

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 en ese momento, pero me ha parecido una solución muy interesante y de mucha utilidad, así que la comparto aquí (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, si no 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 y 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 dResulta, pero podríamos utilizarlo de cualquier otra forma, dependiendo del algoritmo de nuestro script.

El segundo procedimiento de trabajo implica el uso de una función FuncionCalc() que es llamada desde un script PruebaFuncionCalc2. Empecemos mostrando el script para explicarlo a continuación:



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


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 PruebaFuncionCalc1b y PruebaFuncionCalc1c 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 a su vez 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 dicho en la explicación del script de base PruebaFuncionCalc1a: únicamente sustituimos la expresión de la función anterior SUM() por la actual SQRT()) (ambas 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, realizamos 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 es el enlace a la web donde encontrarás el listado de funciones Calc en inglés y en español.
NOTAS
1
2
3
4
5
6
7
8
9
(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

LENGUAJES. OOo Basic

Primer script OOo Basic

Cuestiones introductorias

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 ser 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 de la suite; desde la interfaz 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 ha 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 la que precede a la carpeta (Biblioteca) Standard y hacemos clic enNuevo (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 la biblioteca. 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 última 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:



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

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

NOTAS
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 que se nos propone.
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].



sábado, 15 de julio de 2023

OOo Basic. Script

Macros. Programación modular

Además de utilizar las macros como resultado de la ejecución de Grabar macro también podemos utilizarlas como elementos discretos a modo de subrutinas. Este enfoque se encuentra a medio camino entre la creación de macros y la escritura de script o programación. Ambos procedimientos pueden ser, además, complementarios. En todo caso remite a [lo que expuse] sobre la programación lineal o imperativa y la programación modular.



Es importante remarcar esa idea de complementariedad, ya que en informática (también) las cuestiones pueden se resolver de diferentes maneras (aunque unas pueden ser mejores que otras), así que lo que no sepamos resolver mediante un script, podemos abordarlo mediante una macro.

Pues bien, si en la [entrada anterior] aprendimos a identificar el contenido de una macro secuencial y a diferenciar diferentes funciones, en esta entrada vamos a profundizar en el modo de trabajo que podemos llamar programación modular que podemos caracterizar por el uso de secuencias de acciones (macros unitarias o de función única) combinadas. 

Este modo de trabajo admite la combinación entre macros unitarias y script, combinación que permite desarrollar programas de cierta complejidad. Algunos ejemplos de ello podemos verlos en [aquí]

Para el correcto desarrollo de un docap basado en este tipo de macros es necesario posicionar correctamente las variables básicas de toda macro, así como crear una macro específica en la que dichas variables se asocien a sus contenidos. Esta macro deberá ser llamada desde las macros individuales, permitiendo así su reutilización, con el consiguiente ahorro de tiempo.

A parte de esto, es importante crear colecciones de macros individuales, necesariamente asociadas al servicio-soporte, las cuales pueden ser aplicadas modularmente cuando sea necesario.

Aunque puede considerarse que es este un modo un tanto rudimentario de "programar", podemos decir que es similar al enfoque funcional y que algunos programas de cierta complejidad (FileMaker, por ejemplo) disponen de recursos de "programación" que, en síntesis, no son otra cosa que una colección amplia de funcionalidades, algo similar en filosofía a lo que aquí se plantea.


lunes, 10 de julio de 2023

OOo Basic. Script

 Trabajar con macros

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.




Si recordamos, la secuencia de acciones que desarrollamos para crear la macro anterior fue la siguiente:

    • Nos situamos al inicio del documento
    • Seleccionamos tipo de letra
    • Seleccionamos tamaño de letra
    • Seleccionamos negrita
    • Seleccionamos color
    • Seleccionamos centrado
    • Escribimos una frase
    • Bajamos el cursor
    • Escribimos una segunda frase
    • Bajamos el cursor
    • Nos posicionamos al inicio de la línea
Además recordarás que cometí algunos errores y que los corregí sobre la marcha, de modo que en el resultado final no se aprecian, pero ahí están.

En efecto, todas y cada una de estas acciones han quedado grabada en nuestra macro, incluyendo los errores y su corrección, y ahora están a nuestra disposición para que las reutilicemos. 

Para ello debemos plateamos el uso de las macros desde una perspectiva que no es ni se limita a la que empleamos en la construcción de nuestra primera macro y que se acerca más a la programación.

Desarrollar esta segunda perspectiva pasa por enfrentarnos al código generado por la macro, identificar y eliminar los errores cometidos y diferenciar cada paso de la secuencia que desarrollamos para hacer de cada uno de ellos una herramienta reutilizable.

En [este enlace puedes acceder al documento] en el que se creó la macro.

OOo Basic. Script

 ¿Qué es una macro?

Las macros son tan antiguas como los procesadores de texto, pero han ido evolucionando en funcionalidad al igual que éstos, aunque arrastrando la mala fama que genera ser susceptibles a usos perniciosos.




Originariamente  una macro (macroinstrucción es su nombre completo) no era otra cosa que atajo de teclado para facilitar el trabajo, permitiendo la ejecución de un conjunto de acciones mediante la pulsación de una combinación de teclas. Hoy en día macro y script tiende a confundirse, aunque opino que son dos cosas radicalmente diferentes, tan diferentes como es su proceso de creación: la macro mediante la activación de una funcionalidad llamada Grabar macro y el script mediante la generación de código escrito en un lenguaje de programación desde un programa especial denominado IDE.

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.


sábado, 11 de marzo de 2023

Documentos. Acreditación

Acreditación -7. Docap complejo (d1)

Iniciando con lo prometido nos adentraremos ahora en el análisis del conjunto de script  que conforman esta docap.


Podemos ver en la imagen que sigue los tres módulos que componen la biblioteca Standard y los script individuales que contienen. 


  • Tenemos, en primer lugar, un módulo con script auxiliares cuyas funciones indican sus propios nombres. Dado que no se trata de script centrales del docap actual, no nos detendremos a explicar su funcionamiento.
  • El módulo CapturaDatos reúne los script cuyo cometido es recopilar la información que aporta el usuario o usuaria (fase input)
  • Y el módulo CreaDocum contiene el script que se ocupa de trasladar los datos anteriores al documento Writer que nos sirve de base para crear la acreditación.  

Además del módulo auxiliar, esta estructura revela la existencia de un proceso dividido en dos partes: el acceso a los datos y su ubicación controlada en celdas del soporte Calc y la captura del contenido de las celdas y su traslado al documento Writer.

En esta entrada nos centraremos en los script que forman parte del módulo CapturaDatos: DadosDocum y DatosAlumn; esto es, en la captura de datos del usuario 

Documentos: