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

lunes, 2 de diciembre de 2024

Documentos. LibreOffice.

Soluciones basadas en utilidades LO

Aunque no constituyen realmente una solución de automatización, entre otras cosas porque no implican el uso de código, contamos en LO con dos opciones que contribuyen al desarrollo de este proceso y que podría formar parte de eso que llamamos competencia ofimática en el nivel usuario avanzado. Me estoy refiriendo al uso de formularios y de la funcionalidad Combinar correspondencia.


La
creación de un formulario es un proceso que nos permite convertir un documento de texto en una herramienta de recogida de datos, pero también nos ayuda a formalizar, estandarizar y simplificar la elaboración de ciertos documentos de trabajo. Ejemplos de ellos los ofrece la propia Administración que, en esto sí que ha desarrollado ciertas iniciativas, como puede ser documentación que formaliza el proceso de derivación que llamamos Solicitud de evaluación (psicopedagógica), pero que tiene quizá como mejor exponente el documento-soporte Dictamen de escolarización, que no es más que un formulario complejo y de cierta extensión.

Estos ejemplos evidencian también los propios límites de ese esfuerzo (1), ya que se trata de soportes que en realidad no facilitan su propio uso en la medida en que esto podría ser posible. Ello es debido a que se formaliza el documento, pero no se emplean las herramientas realmente disponibles, recurriendo al uso de tablas (mayormente) en lugar de emplear controles de formulario.

Cierto que la parte más compleja del trabajo ya nos viene dada, pero falta dar ese segundo paso, que es el que realmente facilita el trabajo con el documento: la implementación de los controles de formulario. Gracias a ellos (y con independencia que el soporte definitivo se concrete como documento para ser usado desde el procesador de textos o como archivo pdf) podremos acceder a los campos que, dada la diversidad de opciones tipológicas disponibles, pueden ahorrar trabajo concretando las formas e incluso definiendo contenidos concretos mediante alguna forma de selección. Desde [este enlace] puedes acceder a un ejemplo de conversión de un documento tabulado en un formulario.

De todas formas, como dije, aun en su formulación más básica y menos eficiente, la presentación de un documento como formulario es ya un avance nada desdeñable para el desarrollo de la lógica de programación, así que trabajar en esta dirección (y hacerlo además empleando los controles de formulario) es dar pasos adelante en la misma dirección que en este blog se plantea.

Lo es por la sencilla razón de que al establecer un campo estamos definiendo la esencia de una variable, componente básico de todo script y tarea que deberemos desarrollar para crear soluciones basadas en programación. Falta mucho camino por recorrer y podemos quedarnos por el camino (y para prueba todos los botones que nos proporciona el Servicio de la Consejería con sus no demasiado elaborados modelos documentales), pero también podemos seguir trabajando y en ese trabajo lo aprendido con la creación de formularios nos va a ser muy útil.

No obstante, aunque facilite el trabajo y sea un aprendizaje necesario, de por sí, un formulario no nos permite avanzar en el objetivo de la semi-automatización de la documentación, cosa que se sí es posible mediante Combinar correspondencia, pero con importantes limitaciones.

supone automatizar la elaboración de documentos, ya que emplean explícitamente referencias a campos (variables) que se complementan (personalizan) directamente mediante su asociación a una tabla de datos (2). De este modo podemos automatizar la elaboración de múltiples documentos basados en un modelo único y hacerlo mediante un sólo clic. Pero tiene una limitación, una seria limitación, que hace que esta funcionalidad sea poco funcional, la cual deriva de la función (disculpas por tanta repetición del término) para la que está diseñada: mandar la misma información (formalizada) a múltiples destinatarios; algo así como crear etiquetas para sobres, mandar la misma carta, pero personalizada, a muchas personas y objetivos similares.

De esto se deriva que, además de lo que supone conectar el documento con la base de datos y de los fallos que se pueden producir (y se producen) en este proceso, sólo sea una solución viable para el trabajo con documentos sencillos y de escasa extensión; más allá de estas limitaciones, el trabajo se complica mucho y el rendimiento real del soporte suele ser muy inferior al esperado, y más aun si tenemos en cuenta el exigente trabajo previo que requiere. De todo esto se deriva que el uso de esta alternativa sea muy limitado (3).

No obstante, además de que de los errores también se aprender, este procedimiento también contribuye a desarrollar el pensamiento computacional, incidiendo también en el uso de variables, claramente diferenciadas aquí del cuerpo de información "constante". También ayuda a entender que, aunque la idea de extender el trabajo con variables a algo más que personalizar un documento sencillo es una buena idea, el procedimiento que permite Combinar correspondencia no es suficientemente flexible, siendo necesario buscar una alternativa que lo sea, y que de paso evitar las complicaciones que derivan de la conexión documento-fuente de datos.

NOTAS

(1) Para ser justos debo decir que de "ese pecado" no estamos libres tampoco los SEO, ya que no es infrecuente que reproduzcamos el mismo error: creamos "formularios .doc" basados en tablas y no se nos ocurre que podemos implementar controles de formulario que nos van a ahorrar mucho trabajo a la hora de usarlos. También de esto tenemos [algún ejemplo].
(2) La cual se puede basar en una tabla Calc o en una base de datos auténtica.
(3) Motivo por el que sólo te puedo [mostrar aquí un ejemplo], añadiendo como advertencia que no resulta fácil de manejar, ya que conexión del documento-base de datos se pierde al cambiar las condiciones originales en la que se estableció esa conexión. Desde esta entrada debes descargar dos componentes desde Documentos: el enlazado como Base de datos y el enlazado como Modelo A; y después reconstruir el enlace en tu ordenador. 


lunes, 20 de mayo de 2024

OOo Basic. Interface.

Formularios (c). Calc

También en LO.Calc podemos utilizar formularios sin necesidad de acceder a la capa gráfica (getDrawPage()). Esto es posible por permitir LibreOffice la vinculación de los controles de formulario (algunos) con las celdas.



Cuando implementamos un control en una hoja de cálculo podemos definir sus características desde Propiedades del control (1). Este menú consta de 2 ó 3 submenús, en el segundo de ellos (Datos) podemos incluir, si es que está disponible, la referencia a la celda (vg. A7) con la que vinculamos el control desde la opción Celda enlazadaEsta opción está disponible para los cuatro controles que vimos en la [entrada anterior], estos es, para los campos Cuadro de texto, Cuadro de lista, Botón de opción y Casilla.

Al establecerse esta asociación (2) podemos acceder al contenido creado por el usuario accediendo al contenido de la celda vinculada, evitando así el acceso a la capa gráfica del documento. Como sabemos (3) para acceder al contenido de una celda deberemos seguir lo pasos siguientes:

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))
Dadas las características propias de Casilla tenemos que tomar en cuenta la acción del usuario sobre cada una de las casillas que componen este elemento del formulario, siendo esta una diferencia con el tratamiento del control Botón. Por ese mismo motivo necesitamos realizar la segunda fase (el sumatorio), ya que el análisis de la casilla individual no nos permite acceder al resultado del conjunto. Esto también es válido para la opción basada en OOo Basic, como veremos a continuación.

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

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

Analizo ahora el acceso a los controles de uso más frecuente en un formulario desde OOo Basic, esté creado éste sobre un documento Writer o sobre una hoja de cálculo Calc. Esta entrada complementa, pues, la [entrada anterior] en la que explico la creación del formulario sobre el documento y el acceso a éste mediante código OOo Basic, este sí diferentes según el servicio (Calc o Writer) sobre el que esté implementado.




Los controles de uso más frecuente en un formulario son cuatro (1): Caja de texto, Cuadro de lista, Botón de opción y Casilla (de verificación). Los dos primeros para la entrada de datos y los dos últimos para facilitar la elección de una posible opción de respuesta.

Como ya sabemos, todos los controles de formulario deben ser implementados en el documento-soporte de forma manual (ver [aquísobre la implementación de un formulario Formulario), pero además necesario (o la menos conveniente) conformar la apariencia y forma de funcionamiento de cada uno de esos controles de forma específica. Para ello deberemos acceder a Propiedades del control, opción disponible a partir de la ventana emergente que activamos mediante Selección del control -> Clic derecho sobre el control seleccionado. Una vez dentro de este menú de opciones, podremos configurar nuestro control.

El control Cuadro de texto se comporta funcionalmente como un InputBox(); no obstante presenta características y posibilidades de uso diferentes que las que ofrece InputBox() (2). Para acceder a este control y a su contenido crearemos el código siguiente:

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)

El control Cuadro de lista se diferencia del anterior por sustituir la entrada de texto de escritura libre por una lista de datos, presentados como opciones de respuesta para la elección del usuario. Este listado puede crearse directamente desde Propiedades del control -> General -> Entradas de la lista o desde Propiedades del control -> Datos -> Tipos de contenido de la lista opción Lista de valores. Esta segunda forma también permite asociar el control a una tabla, una consulta o a otras opciones de base de datos.

Para acceder al control Cuadro de lista se sigue el mismo procedimiento que para hacerlo a Cuadro de texto, pero no así para el acceso al dato seleccionado por el usuario. Observa el código siguiente:

Dim oCurso As Object, oCursoVista As Object
Dim sCurso As String

oCurso =  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())
El control Botón de opción es en realidad un conjunto (de al menos dos controles del mismo tipo vinculados entre sí; ambos ofrecen al usuario la posibilidad de elegir uno de ellos como opción seleccionada (el o los otros se descartan), por lo que el conjunto presenta un comportamiento similar al del Cuadro de lista en el que el usuario opta por una de las opciones que se le presentan), aunque en su apariencia formal y su funcionamiento son muy diferentes.

También es diferente el modo en que se accede a la opción seleccionada, requiriendo Botón de opción un manejo similar al que hacemos del valor que devuelve la función MsgBox() (3).

        Dim oBtn1 As Boject, oBtn2 As Object
Dim sSexo As String
oBtn1 = oFormulario.getByName("btn1")
oBtn2 = oFormulario.getByName("btn2")
If oBtn1.State() Then
sSexo = "Niño"
End If
If oBtn2.State() Then
sSexo = "Niña"
End If
MsgBox "Sexo": " & sSexo

El acceso al "contenido" en Botón de opción es en realidad la captura de su pulsación por el usuario (oBtn1 = oFormulario.getByName("btn1")), y se requieren tantas variables como botones de opción contenga nuestro conjunto de opciones. Por ejemplo, en este caso, sólo dos (oBtn1 y oBtn2): el primero capturar la pulsación del botón btn1 (oBtn1 = oFormulario.getByName("btn1")) y el segundo la del botón btn2 (oBtn2 = oFormulario.getByName("btn2"))

Al hacerlo capturamos también sus métodos y propiedades, en concreto el método  State(), que presenta dos opciones (0|1), dado que es de tipo Boolean. Por ello es posible valorar el estado del botón mediante el condicional If. En función del resultado del análisis del estado (State()) de los diferentes botones que componen ese conjunto, asignamos un valor u otro a una segunda variable (en nuestro caso sSexo que es de tipo String) que es la que contendrá la información relevante para el desarrollo del script. En nuestro ejemplo se trata de determinar el sexo del alumno (sSexo="Niño" vs. sSexo="Niña"y de informar de ello mediante MsgBox (MsgBox "Sexo": " & sSexo)

Finalmente el control Casilla (de selección o de verificación) se diferencia de Botón de opción en su forma externa (se representa como un cuadradito en vez como círculo) pero se asemeja en el código necesario para acceder al control y a su estado (de nuevo el método State()). 

Otra diferencia entre ambos es que Casilla no es opcional-excluyente cuando se presenta en agrupamientos, lo que implica que el usuario puede marcar cada uno de estos controles de forma independiente, cosa que no sucede con los botones. De hecho una presentación posible de Casilla es como control único de confirmación del cumplimiento de una condición (Vg. ¿Es correcta esta contraseña?). Otra es, como dije, formando agrupamientos, como en el ejemplo que sigue (4).

        Dim oCasilla1 As Object, oCasilla2 As Object, oCasilla3 As Object
        Dim iPuntos As Integer

iPuntos = 0 

        oCasilla1 = oFormulario.getByName("Casilla1")

If oCasilla1.State() = 0 Then

 iPuntos = iPuntos + 1

End If

En este script, las tres casillas pueden ser seleccionadas independientemente una de otra. De hecho la respuesta correcta implica no seleccionar la primera y sí las otras dos. 

Por lo que se refiere al código de acceso al objeto Casilla como el tratamiento de su estado (State()) es igual que el Botón de opción, como puedes observar comparando ambas instrucciones.

Documentos. Ambos enlaces permiten la descarga del formulario sobre Writer y sobre Calc. Se trata de ejemplificar el uso y [acceso a los formularios], diferente en función del servicio, y a los controles de uso más frecuente (los tratados en esta entrada).


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.

(2El 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 (1como 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.




En esta entrada trataré sobre el acceso al formulario mediante código OOo Basic, útil para trabajar con Writer, Calc e Impress. Los formularios de Base (base de datos) quedan fuera de nuestros objetivos por su especificidad.

El primer paso es, como dije antes, es crear el formulario desde el documento. Es posible que esta funcionalidad no está directamente disponible (2), por lo que necesitaremos activar las opciones FormularioVer | Barra de herramientas | Diseño de formularios (que muestra sus controles) y Ver | Barra de herramientas | Controles de formularios, que muestra las herramientas de los Controles. A partir de aquí lo que debemos hacer es seleccionar el icono Modo diseño... (3)



Una vez creado el formulario, para trabajar sobre él mediante OOo Basic deberemos trabajar desde el IDE para acceder a la capa gráfica (getDrawPage()), que es donde se sitúan los formularios (4). 

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
Dim oFormularios As Object, oFormulario As Object

 Los pasos a seguir son los siguientes:
  • 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


Podemos 
 considerar lo anterior como primera fase del proceso, que finaliza con el acceso a los contenidos que introduce el usuario en los controles del formulario. Dedicaremos a ello la entrada siguiente.

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.

Tendiendo en cuenta que hemos basado el uso de controles de formulario en Calc en su asociación con celdas, es necesario explicar específicamente el modo de acceso al contenido de las celdas desde OOo Basic.



Son ya unos cuantos los docap en los que he usado este procedimiento, pero no está demás dejarlo plasmado en una entrada específicamente dedicada a ello, ejemplificado el procedimiento con un sencillo documento Calc.

La simplicidad del procedimiento (a estas alturas del blog, claro) facilita que la entrada sea breve: sólo un poco de código de ejemplo...

Dim oDatos As Object, oCurso As Object
Dim sCurso As String

oDatos = 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

Siguiendo con el uso de formularios en Calc, una vez que aprendimos a manejar cuadros de texto y cuadros de lista, podemos avanzar un poco más y aprender a usar casilla de verificación y botones de opción, por ser también ambos controles de uso frecuente.



Las casillas de verificación (CheckBox) son controles asociados a variables lógicas (Verdadero - Falso) empleadas para identificar si se cumple o no una determinada condición.

Los botones de opción (OptionButtom) son controles que permiten elegir una entre varias opciones disponible. Por ese motivo trabajan juntos como mínimo dos botones, aunque lo normal es que sean más. La elección de uno de ellos (de una opción) implica la no elección del resto.

La diferencia entre ambos controles radica en que 
  • 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.
Dado que este entrada está dedicada al uso del control en un documento Calc, suponiendo la asociación del control a una celda, en realidad las casillas de selección no ofrecen (en Calc) mayor dificultad, puesto que es posible realizar esa asociación sin mayor dificultad (igual, por ejemplo, que hacemos con un cuadro de texto.


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.

Dada la versatilidad de las casillas de selección perfectamente podemos utilizar un juego de dos casillas, asociadas ambas a la misma celda, obligando entonces al usuario a seleccionar una y otra según el valor que asuma la variable asociada. De este modo nos ahorramos trabajar con botones de opción.

Pero si preferimos "hacer las cosas bien" y usar los controles más ajustados al objetivo, en este caso deberemos admitir que corresponde hacer uso de los botones de opción.

Lo malo es que, por defecto, el menú Controles de formulario de Libre Office Calc no dispone de icono para los botones de opción (entiendo que esto se relaciona con la "irrelevancia" de la diferencia entre casilla y botón), siendo necesario "reconvertir" otro control a botón de opción.

Una vez hecha esta "reconversión" (que sí es perfectamente posible), nos damos cuenta que el funcionamiento de la pareja de botones de opción es exactamente el mismo que el de las casillas de verificación. Por ello, la solución primera (dos casillas de verificación) tiene la misma utilidad y funcionalidad que usar dos botones de opción (y viceversa). Queda a tu elección qué solución adoptar.

Resumiendo, aunque casillas y botones son dos controles teóricamente diferentes en cuanto a su naturaleza y funcionamiento teórico, en la práctica del uso de ambos controles en una hoja de cálculo en la que asociamos los controles a celdas, las casillas de opción cumplen también las funciones propias de los botones de selección.

Dado que las circunstancias lo permiten (y hasta sugieren), al igual que hice en [otra ocasión], para evitar hacer innecesariamente extensa esta entrada (su objetivo ya está cumplido), me abstendré de más desarrollo o ejemplificación, incluyendo formalizar las explicaciones previas en un supuesto formulario o repetirlas en un vídeo. 

Teniendo en cuenta lo que ya sabemos hacer a estas alturas, ninguno de los dos recursos van a aportar más a lo ya dicho aquí.