lunes, 2 de diciembre de 2024
Documentos. LibreOffice.
lunes, 20 de mayo de 2024
OOo Basic. Interface.
Formularios (c). Calc
Dim oDocumento As Object, oHojaActiva As Object, oCelda As Object
Dim sContenido As String
oDocumento = ThisComponent
oHojaActiva = oDocumento.getCurrentController.getActiveShee()
oCelda = oHojaActiva.getCellRangeByName("E3")
sContenido = oCelda.getString()
La repetición de las líneas 5-6 de este script (con la creación de tantas variables Object y String como controles-celdas tenga nuestro formulario, nos permitirá acceder al conjunto de datos introducidos por el usuario.
Aunque el procedimiento básico es así de simple, deberemos considerar, no obstante, las peculiaridades y/o posibilidades que presentan los distintos tipos de control, ya que lo anterior es válido para el control Cuadro de texto, y también para el resto, pero cada uno de los restantes presenta alguna peculiaridad que es necesario conocer.
El control Cuadro de lista permite en su configuración seleccionar, además de la celda enlazada, el contenido que mostrará dicha celda. Esta opción está disponible desde Datos | Contenido de la celda enlazada, pudiendo establecer bien La entrada seleccionada o bien la Posición de la entrada seleccionada (4). Aunque en este ejemplo y en la mayoría de los formularios con los que trabajemos, la opción preferente será la primera (La entrada seleccionada), tanto por funcionalidad como por facilidad de uso en el script (5), habrá ocasiones en las que sea conveniente trabajar con Posición de la entrada seleccionada precisamente por tratarse de un valor numérico (6). En este caso tanto la variable que asociemos al contenido de la celda, como el tratamiento posterior de esta variable (y su contenido) será muy diferente del que normalmente haremos con el texto resultante de la opción La entrada seleccionada (ver nota 4).
El o mejor aun, los controles Botón de opción y Casilla presentan también peculiaridades que es necesario conocer, aunque en este caso se trata tanto de la vinculación a las celdas como del tratamiento del resultado de la elección del usuario y su constatación en el contenido de las celdas.
Es necesario saber, en primer lugar, que cada botón o cada casilla se debe asociar con una celda diferente. Esto tiene sentido para las casillas, pero puede parecer paradójico para los botones, ya que éstos están vinculados y la elección de uno implica necesariamente la no elección del resto (7). No obstante, la lógica de la asociación control-celda impone que se vincule cada botón a una celda, ya que si vinculamos todos los botones a la misma celda lo que hacemos (por la bidireccionalidad explicada en nota 2) es precisamente equivalente a seleccionar todos los botones.
Lo segundo que debemos saber es que, en coherencia con la naturaleza de los botones y las casillas, lo que ambas devuelven (y queda escrito en las celdas enlazadas) en un valor booleano ("VERADERO" | "FALSO"), lo que conlleva repercusiones tanto para el acceso al contenido de dichas celdas como para el posterior tratamiento de estos datos. Se abren además diferentes opciones de trabajo para el desarrollo de este tratamiento. Veamos las implicaciones de lo anterior en nuestro formulario de ejemplo.
En él contamos con dos botones para la elección del sexo del alumno (por ejemplo), cada uno de ellos asociado a una celda (por las razones antes dichas), concretamente btnM está vinculado a F15 y btnF a F16. En ambos casos, en dichas celdas se escribe de forma simultánea VERDADERO y FALSO (o viceversa) según pulsemos en el primer o en el segundo botón (8). Ahora bien, a nosotros lo que nos interesa es lo que deriva de la elección del usuario, esto es: conocer si el sujeto referenciado es niño o niña (9) y nada de eso nos dice el contenido de F15 o de F16 (10). Para convertir VERDADERO | FALSO en niño | niña necesitamos emplear una estructura o función condicional, pudiendo optar por emplear las funciones Calc o por el tratamiento condicional (if) desde OOo Basic.
En el primer caso (que es lo que hacemos en nuestro ejemplo) construimos sobre la celda G15 la siguiente función: =SI(F15=1,"niño";"niña) (11). En el segundo accederemos mediante código al contenido de la celda F15 y construiremos una estructura condicional como se ejemplifica a continuación, y que cumple la misma función (12):
Dim oCeldaSexo As Objet
Dim sSexo As String
oCeldaSexo = oHojaActiva.getCellRangeByName("F15")
If oCeldaSexo.getValue = 1 Then (Ver nota 11)
sSexo = "niño"
Else
sSexo = "niña"
End If
También en Casilla sucede algo similar. En nuestro ejemplo se utilizan tres casillas, cada una de ellas asociada a una celda (F19, F20 y F21 respectivamente) que contienen valores booleanos VERADERO | FALSO. Y también en este caso disponemos de dos opciones para convertir estos valores en el resultado que nos interesa (en este caso la puntuación del ítem).
La opción basada en las funciones Calc se desarrolla en dos fases:
- En la primera puntuamos cada ítem mediante una función condicional (=SI(F19="";"";SI(F19=0;1;0))) sobre las celdas G19, G20 y G21.
- Y en la segunda calculamos el total de puntuación del ítem mediante la función Calc Suma() (=SUMA(G19:G21))
Dim oCeldaItem1 As Object,oCeldaItem2 As Object,oCeldaItem3 As Object
Dim iPuntos As Integer
iPuntos = 0
If oCeldaItem1.getValue = 0 Then
iPuntos = iPuntos + 1
End If
If oCeldaItem2.getValue = 1 Then
iPuntos = iPuntos + 1
End If
If oCeldaItem3.getValue = 1 Then
iPuntos = iPuntos + 1
End If
Puedes observar como, en esta modalidad u opción necesitamos tres variables Object, una para cada Casilla (oCeldaItem1, oCeldaItem2 y oCeldaItem3), además de una variable Integer para el sumatorio de la puntuación. Además, cada variable Ítem debe ser sometida al análisis condicional (vg. If oCeldaItem1.getValue = 0) y el cálculo de la puntuación total (el sumatorio) se realiza asignando repetidamente (tantas veces con ítem y condicionales) la propia variable a si misma más el punto que corresponde por acierto (iPuntos = iPuntos + 1) (13)
Documento.
NOTAS
(1) Sobre la implementación manual de un formulario en un documento ver [esta entrada]
(2) La asociación o vinculación entre el control y la celda es bidireccional; en consecuencia, lo que escribamos o seleccionemos en el control se escribe en la celda y viceversa. Lógicamente también lo que se modifique o se borre.
(3) Ver procedimiento en [esta entrada]
(4) En el primer caso mostrará en la celda asociada el texto seleccionado de la lista de opciones que tenga establecido Cuadro de lista (vg. 1º EP), y en el segundo, para esta misma elección del usuario, mostrará en la celda el valor numérico 2, ya que se trata del 2º elemento de la lista de opciones. La consecuencia es tanto para la visualización del resultado como para el procedimiento de acceso al contenido de la celda enlazada, ya que la variable receptora deberá ser (preferiblemente) de tipo numérico; pero también puede tener consecuencias para el posterior tratamiento del contenido de la variable con la que asociemos este dato.
(5) Esta opción tiene la ventaja de permitir un tratamiento directo del contenido textual, pero también la total similitud del proceso con el que realizamos con Cuadro de texto.
(6) En ejemplo de esto es cuando la elección del usuario implique valor cardinal u ordinal, como en el caso de las escalas tipo Likert. Estas escalas pueden construirse utilizando diferentes controles; Cuadro de lista es uno de ellos.
(7) Cosa que, como sabemos, no ocurre con las casillas, dado que es es posible seleccionar cada casilla de forma independiente de lo que hagamos con el resto. En este caso es lógico que cada casilla deba estar asociada a una celda distinta, pero el valor final de una elección entre varias opciones excluyente de un botón (entre varios), sólo puede arrojar un único dato.
(8) Esta simultaneidad es resultado de la vinculación entre ambos botones; es coherente con su lógica de funcionamiento y, en consecuencia, síntoma de una correcta configuración del conjunto.
(9) En el supuesto, por ejemplo, de que tal categorización tiene efectos en las formas gramaticales de un texto que describa el resultado de un análisis de datos o una comunicación personalizada con la familia, etc.
(10) Obviamente, a excepción de lo que nos permite la visualización directa del formulario; pero estamos hablando aquí de la automatización del análisis de los resultados, no del que podemos realizar manualmente visualizando los datos que se nos muestran en la hoja de cálculo.
(11) No es necesario trabajar con el contenido de la celda F16 dada la asociación que se establece entre los botones de opción. Ver explicación en el texto de la entrada, contenidos asociados a las notas 7 y 8, y en las propias notas. Observa que la expresión "VERADERO" es sustituida por 1. Esto es debido a la equivalencia entre 1 -> VERADERO y 0 -> FALSO cuando se trata de datos booleanos. Lo mismo sucede en el código alternativo OOo Basic (If oCeldaSexo.getValue = 1 Then)
(12) Queda a la tu decisión optar por una u otra opción, pero es necesario que conozcas ambas para que estés en posición de elegir. En ambos casos el resultado es el mismo. Mi recomendación es que, dado que optamos en este caso por acceder a los resultados mediante el acceso a las celdas (y no directamente a los controles), continúes con esa misma lógica y utilices las funciones Calc todo lo que te sea posible. Es necesario saber utilizar estas funciones y en este caso hacerlo no sólo mantiene la coherencia con el planteamiento de trabajo, además supone un ahorro de tiempo.
(13) Este proceso puede resolverse de otras formas, pero para los que nos interesa ahora es suficiente con la forma en que aquí se desarrolla. Respecto a la opción a elegir (el uso de funciones Calc vs. código OOo Basic remito a lo dicho en la nota 12.
domingo, 19 de mayo de 2024
OOo Basic. Interface.
Formularios (b)
Dim oTxtNombre As Object
Dim sDato As String
oTxtNombre = oFormulario.getByNa.me("txtAlNombre")
sDato = oTxtNombre.Text
- Primero creamos dos variables, la primera (oTxtNombre ) de tipo Object (recuerda que un control es un objeto en LibreOffice) y la segunda (sDato) de tipo String.
- El paso siguiente es acceder al objeto control (en este caso) por su nombre (una de las opciones que tenemos cuando configuramos el control) mediante la siguiente instrucción: oTxtNombre = oFormulario.getByName("txtAlNombre")
- Finalmente, recurriendo al atributo Text del control, accedemos al contenido introducido por el usuario. Asignamos este contenido a la variable String creada al inicio de del código (sDato = oTxtNombre.Text)
Dim oCurso As Object, oCursoVista As ObjectDim sCurso As StringoCurso = oFormulario.getByName("curso")oCursoVista = ThisComponent.getCurrentController.getControl( oCurso )sCurso = oCursoVista.getSelectedItem()
- Primero declaramos dos variables Object para acceder a los objetos control (oCurso) y listado del control (oCursoVista) y una tercera variable, esta de tipo String (sCurso)
- El uso de las dos variables Object es el siguiente:
- Mediante la primera (oCurso) accedemos al control como tal (oCurso = oForm.getByName("curso"))
- Y mediante la segunda (oCursoVista) a su listado de opciones (oCursoVista = ThisComponent.getCurrentController.getControl( oCurso ))
- Posteriormente asignamos la opción seleccionada (método getSelectedItem()) a la variable String, previamente declarada (Dim sCurso As String) haciendo uso de ese método (sCurso = oCursoVista.getSelectedItem())
oBtn1 = oFormulario.getByName("btn1")
oBtn2 = oFormulario.getByName("btn2")
iPuntos = 0
If oCasilla1.State() = 0 Then
iPuntos = iPuntos + 1
End If
NOTAS
(1) LibreOffice cuenta con un listado de controles de formulario mucho más amplio, pero estos cuatro cubren la mayoría de las necesidades que buscamos satisfacer con un formulario, de ahí que sean los de uso más frecuente y, por tanto, los que más interés tienen para la creación de un docap basado en Formulario.
(2) El manejo de Cuadro de texto requiere el mismo procedimiento de acceso que cualquier otro control de formulario, por lo que no es factible trabajar con él como con InputBox(). En términos de funcionalidad, Cuadro de texto permite opciones de configuración que no están disponibles en InputBox() (que en esto es muy limitado); destaco por su utilidad la posibilidad de configurarlo multirrenglón, además de los formatos de texto (incluido tamaño de letra). Estas opciones de configuración permiten un uso muchos más amigable y funcional como interface, si bien requiere un trabajo previo de configuración desde Propiedades del control.
(3) También en este caso deberemos tratar el valor devuelto mediante un condicional If.
(4) Se trata de un fragmento del script real. En él se ejemplifica el acceso a uno de los tres controles Casilla y a su posterior tratamiento mediante el condicional If. El script completo está disponible en el documento que ejemplifica el uso de los controles que se explican en esta entrada.
jueves, 16 de mayo de 2024
OOo Basic. Interface.
Formularios (a)
Además de las formas simples de interface (MsgBox e InputBox), LibreOffice cuenta con otros dos recursos de interface: los formularios y los cuadros de diálogo.
Los formularios son medios para facilitar la interacción usuario-programa, empleados fundamentalmente en la fase Input. A diferencia del cuadro de diálogo (en adelante, Diálogo, por brevedad), el formulario se puede emplear tanto como funcionalidad (1) como asociado a a un script; en ambos casos, el primer paso consiste en crear el formulario (funcionalidad) desde el documento, sea este un documento Writer o desde Calc.
El recorrido que deberemos hacer para acceder a un formulario depende del soporte (o servicio) en el que esté creado: no es lo mismo trabajar desde Writer que hacerlo desde Calc.
Un script que nos permita acceder a un formulario creado en un documento Writer requiere realizar el siguiente recorrido, en el que se diferencian cuatro pasos, que precisan contar con una serie de variables de tipo Object (5):
Dim oDocumento As Object, oCapaDib As Object, oForms As Object, oForm As Object
- Paso 1. Acceso al documento: oDocumento = ThisComponent
- Paso 2. Acceso a la capa gráfica: oCapaDib = oDocument.getDrawPage()
- Paso 3. Acceso al conjunto de formularios: oForms = oCapaDib.getForms()
- Paso 4. Acceso al formulario concreto por el índice o por el nombre:
oFormulario = oFormularios.getByIndex() -> Acceso por el índice
oFormulario = oFormularios.getByName("frmActua") -> Acceso por el nombre
El acceso a un formulario creado sobre Calc requiere también seguir una serie de pasos (cinco) que se basan en un conjunto de variables tipo Object por las mismas razones que expusimos antes (ver nota 5)
Dim oDocumento As Object, oHojaActiva As Object, oPaginaDibujo As Object
Los pasos a seguir son los siguientes:Dim oFormularios As Object, oFormulario As Object
- Paso 1. Acceso al documento: oDocumento = ThisDocument
- Paso 2. Acceso a la hoja activa:
oHojaActiva = oDocumento.getCurrentController.getActiveSheet()
- Paso 3. Acceso a la capa gráfica: oPaginaDibujo = oHojaActiva.getDrawPage()
- Paso 4. Acceso al conjunto de formularios: oFormularios = oPaginaDibujo.getForms()
- Paso 5. Acceso al formulario concreto, el cual puede ser por índice o por el nombre:
oFormulario = oFormularios.getByIndex() -> Acceso por el índice
oFormulario = oFormularios.getByName(""frmCalcEj") -> Acceso por el nombre
NOTAS
(1) Por funcionalidad entiendo cualquier recurso que puede ser desarrollado desde la interface general del servicio (Writer, por ejemplo), sin necesidad de acceder al IDE. En Writer los formularios se crean en la capa "Dibujo" del documento directamente desde éste. Para crear un Diálogo es necesario acceder al IDE y crearlo específicamente de forma directa. Desde esta perspectiva el formulario es un objeto más accesible y simple que un diálogo.
(2) Es posible que esta sea una de las causas de su escaso uso. Contribuye a ello que en los documentos prescriptivos (que no hacen otra cosa que seguir la costumbre consolidad por el uso) se empleen tablas como base para simular la apariencia de formulario.
(3) Este procedimiento implica activar el icono de la barra Controles de formulario. Este mismo icono está también disponible en la barra del Diseño de formulario. Activarlo también supone acceder a la definición del formulario y a otras utilidades, incluyendo la introducción de campos (comando Añadir campo), que también activa la barra Controles de formulario.
(4) Tanto en Writer como en Calc, los formularios se ubican en la capa gráfica ("de dibujo"), que se superpone a la capa en la que escribimos en el documento (en Writer) o en la que se encuentran las celdas (en Calc)
(5) Tanto el documento, como la capa gráfica y los formularios son objetos, dado que LibreOffice es un programa creado dentro del paradigma de la Programación Orientada a Objetos (POO)
sábado, 8 de julio de 2023
OOo Basic. Interfaz.
Formularios. Acceso al contenido de los controles.
Dim oDatos As Object, oCurso As ObjectDim sCurso As StringoDatos = ThisComponent.getSheets().getByName("Datos")oCurso = oDatos.getCellRangeByName("B2")sCurso = oCurso.getString()
Después de declarar las variables necesarias, asignamos a ellas los objetos principales: primero la hoja (en este caso por el nombre, pero podría ser también por índice), y después la celda (también por el nombre, pero podría ser por la referencia de posición). Posteriormente accederíamos a su contenido (que asignamos a la variable string sCurso) mediante el método getString(). Si quisiéramos escribir en la celda usaríamos setString("Texto")
... y, para finalizar, este [documento] en el que ejemplifico el procedimiento de acceso al contenido de celdas y de escritura en celdas.
OOo Basic. Interfaz
Formularios. CeckBox y OptionButtom
- Las casillas son independientes unas de otras, por lo que es posible seleccionar más de una puesto que no están vinculadas. Los botones sí lo están, por lo que sólo es posible seleccionar uno entre todos los que forman el conjunto de opciones.
- Los botones se asocian a la elección de la opción o contenido implícito; las casillas a la confirmación del valor True para la condición expresada en el control.
En este ejemplo, la casilla de verificación "Niño" se utiliza para identificar el sexo del sujeto, asociando el valor resultante a la celda B3 de la hoja "Datos" del libro Calc. En caso de estar seleccionada la casilla, en la citada celda se escribirá "Niño", y si no está seleccionada se escribirá "Niña".
Aunque este uso de la casilla de verificación puede considerarse sustitutorio del botón de opción (y de hecho es posible usarla también con esta función), sin embargo el procedimiento de uso crea un potencial problema: si se trata (en el ejemplo) de una niña, el usuario no marcará la casilla en la creencia de que es suficiente con abstenerse de marcarla para que se recoja la opción implícita (Niña). Pero el funcionamiento del control sólo escribirá "Niña" en Datos.B3 si primero se seleccionó la casilla y después se retira la selección. De no hacerlo no escribirá nada. Tenemos dos formas de evitar esto:
- Usando dos casillas, una para la elección Niño y otra para la elección Niña
- O usando dos botones de opción.