miércoles, 27 de diciembre de 2023

Funciones Calc.

 Calc. Funciones propias (3). Números



Calc dispone de dos funciones para controlar si un dato es numérico o no lo es.  Estas funciones son ESNUMERO() y N(). La primera función devuelve VERDADERO si un dato es numérico y FALSO si no lo es.

Los datos numéricos que lo parecen, pero que no lo son, son los que resultan de escribir números como palabras, como, ñor ejemplo, cuando escribimos un numero dentro de una cadena ('"tengo 24 años"), pero también cuando utilizamos controles de formulario como Cuadro de texto para introducir datos numéricos y los asociamos a celdas.

Cuando usamos estos controles de formulario como forma de entrada de datos y asociamos la entrada a una celda, si en el cuadro de texto escribimos un texto no se produce ningún problema, pero si escribimos números, el resultado esperado puede no corresponderse con lo que obtenemos, presentando un comportamiento irregular.

  • Si aplicamos la función ESNUMERO() a esa celda, nos devolverá FALSO, 
  • pero si en otra celda recogemos el resultado de aplicar un operador aritmético al valor de la celda asociada al control, la función ESNUMERO() devuelve VERDADERO.
  • Ahora bien, si ese dato está incluido en un conjunto de datos, unos numéricos y otros string, y aplicamos funciones que suponen trabajar con el conjunto, como SUMA()PROMEDIO() y otras, ESNUMERO() devuelve VERDADERO, pero el cálculo excluye los valores no numéricos.

Lo que sucede en estos casos es que las citadas funciones (SUMA() y PROMEDIO()) realizan los cálculos respectivos sobre el conjunto de datos que sí son número sin tomar en cuenta los valores que se presentan como tales pero que no los son, como es el caso de los que proceden de los controles del formulario.

Si utilizamos controles de formulario como recurso de entrada de datos en sustitución de la entrada directa en celdas, y mediante funciones específicas trasladamos sistemáticamente estos valores a una tabla sobre la que realizamos cálculos, no es difícil imaginar el efecto que el comportamiento observado anteriormente va a tener en los resultados que obtengamos de tales cálculos. 

En estos caso, para evitar estos errores sugiero recurrir a multiplicar el valor original por 1 (D2*1), lo que convierte el dato en un número reconocido como tal por ESNUMERO() y por las funciones de cálculo del conjunto, como SUMA() y PROMEDIO().

Calc dispone de la función N(), que transforma un carácter en número, pero que puede ser que devuelva 0, convertido eso sí, en un valor numérico, tal y como revela ESNUMERO(), por lo que altera obviamente, nuestro cálculo.

jueves, 14 de diciembre de 2023

Procedimientos. Datos.

Calc. Cumplimentar documento.

Como dije en la [entrada anterior], es posible crear soluciones (que no (aun) docap) basadas en el uso de funciones Calc. Comentaba en ella la conveniencia de ejemplificar la afirmación anterior explicando la construcción de un soporte de esas características y recientemente [publiqué una entrada en OrientAsLO] que cumple este objetivo, quedando pendiente (en ese momento) complementar dicha entrada con la que ahora desarrollo aquí.



En esa entrada de OrientAsLO expliqué el test de referencia (Test de Weepman) y la estructura del soporte, por lo que no me voy a detener aquí en esos detalles. Me centraré, eso sí, en explicar con cierto detalle el uso de las funciones SI() y CONCATENAR() empleadas en la construcción del sencillo informe con el que finaliza el soporte (pág. Info). 

A este mismo efecto podría haber servido el test Palabras mágicas, ya que también en él se utilizan los mismos recursos con la misma finalidad, pero al exponer el test Weepman matamos dos pájaros de un mismo tiro: aumentamos los recursos publicados en el blog, complementando desde una doble perspectiva la evaluación de la discriminación auditiva (1), y exponemos un procedimiento de trabajo cuyo conocimiento puede considerarse "rentable" en términos de frecuencia de uso.

De hecho se trata de explicitar precisamente lo que podemos considerar la "prehistoria" del desarrollo del nivel competencial que facilita en estos momentos la creación de docap (2): profundizar en el uso de los recursos disponibles en los servicios e incrementar el campo de ámbitos de uso de uno (la hoja de cálculo Calc)  que es sabido no forma parte de lo que normalmente se suele emplear por parte de los SEO.

Con todo, lo más importante ahora es que con esta entrada complemento lo expuesto [en la precedente] referida a la función CONCATENAR() y sus similares (CONCAT() UNIRCADENAS()), a la vez que también complementa lo tratado en [otras entradas anteriores] referidas al uso de la función SI() (3), por lo que ahora abordamos su uso conjunto, el cual se revela así con toda su capacidad de automatizar la creación de textos (informes) básicos sin recurrir (aun) al uso de script OOo Basic.

La función condicional SI() ya se emplea con profusión en la puntuación de los ítem del Test (4)...

  • =SI(D7=E7;1;0) (base para el análisis cuantitativo)

... y el registro de los pares de fonemas en los que se presentan errores...

  • =SI(F7=0;B7;" ") (como base para el análisis cualitativo)
No obstante, es en la creación del informe (hoja Info) donde me voy a centrar ahora, ya que es en ella donde se utilizan las funciones SI() y CONCATENAR() de forma combinada, pero también donde se aprecia el "primitivismo" y las limitaciones de estas primeras formulaciones de la automatización basada en funciones nativas de Calc: incluso en el marco de esta delimitación  se aprecia que la solución se desarrolla en los inicios de la profundización en el conocimiento de las posibilidades de la hoja de cálculo (5).

El mencionado informe está dividido en cinco bloques, correspondiendo el primero a la descripción del test, sin que se emplee en él ningún procedimiento de personalización, limitándose a la escritura directa de un breve texto genérico e introductorio.

El resto de los párrafos sí incluyen el uso combinado de las funciones (básicamente la condicional SI() junto con CONCATENAR() y alguna otra de carácter complementario (y secundario para lo que nos interesa ahora) (6). La estructura básica es la que sigue:

SI(Condición a valorar... (se refiere a la valoración global del rendimiento del sujeto)

... Entonces -> CONCATENAR() -> datos + cadenas + datos

... En caso contrario ("Else") -> CONCATENAR() -> datos + cadenas + datos )

... (donde datos se concreta como referencia a celdas que contienen los datos) y que se concreta como sigue:

=SI($Id.C14="presenta dudas";CONCATENAR($Id.B6;" obtiene un porcentaje de acierto del ";TRUNCAR($Id.C12;2);"%, por lo que puede considerarse que su rendimiento en tareas de discriminación auditiva es  ";$Id.C14);CONCATENAR($Id.B6;" obtiene un porcentaje de acierto del ";TRUNCAR($Id.C12;2);"%, por lo que puede considerarse que su rendimiento en tareas de discriminación auditiva es";$Id.C14))

El párrafo siguiente se crea únicamente mediante concatenación de string y datos y sirve de entrada para exponer los pares de fonemas afectados por error (párrafos 4º y 5º), que también se crean mediante la función concatenar.

Son estos dos párrafos donde mejor se aprecia el arcaísmo y las limitaciones de uso de las funciones Calc: en ellos habría sido mucho más pertinente utilizar la función CONCAT() o UNIRCADENAS(), que se suponen una ejemplificación de la concatenación de un conjunto de celdas (G7:G46), así como del tratamiento de las celdas vacías y/o de la separación entre ellas. 

Si utilizo estas dos funciones como alternativa a la más primitiva (CONCATENAR()) obtengo un resultado más satisfactorio y de forma más simple (7), pero no del todo satisfactoria. De hecho la función que mejor funciona es UNIRCADENAS(), pero tampoco de forma totalmente satisfactoria en cuanto al manejo de los espacios que deja la no presencia de contenido en determinadas celdas del conjunto (G7:G46) y/o del carácter de separación (el que mejor funciona es " ").

Es entonces cuando el uso de otras dos funciones de tipo texto ayuda a mejorar los resultados. Me refiero a la función ESPACIOS(), que elimina los espacios sobrantes, y la función SUSTITUIR(), que empleo para sustituir los espacios en blanco que utilizo originariamente como separador y que ESPACIOS() respeta por considerarlos espacio propio entre palabras (que son los únicos que no elimina). De este modo consigo un resultado que se ajusta perfectamente al objetivo: generar un listado de los pares de fonemas afectados por error, ajustado a la longitud de la lista resultante y diferenciándolos claramente unos de otros. Como ejemplo...

G-D | S/C | C-G | C-T | E-O | C-P | BR-GR | T/R | P/N | C-T

... que resulta de la combinación de las tres funciones (8): 

=SUSTITUIR(ESPACIOS(UNIRCADENAS(" ";1;$It.G7:G46));" ";" | ")

NOTAS

(1) Con lo que proporcionamos dos recursos que se pueden considerar complementarios en cuanto a la forma de evaluar la discriminación auditiva, lo que permite desarrollar estrategias de evaluación que combinen ambos, si así se considera.

(2) O lo que es lo mismo, la (semi)automatización de soportes documentales en base a OOo Basic.

(3) Se trata de tres entradas aunque ahora sólo se enlace a la publicada en primer lugar. El resto están disponibles desde la página [DATOS] . Pdt. Añadir que en estas entradas no me limito a explicar el uso de las funciones condicionales de Calc. 

(4) Hoja It(em), columnas F para puntuación y G para recopilación de errores.

(5) El documento original fue creado hace más de 10 años sobre MSO-Excel y transformado recientemente a formato Calc sin revisión ni modificaciones, de ahí que se limite al uso de la función CONCATENAR() sin tener en cuenta otras opciones.

(6) También incluyen la referencia a celdas de diferentes hojas, aunque este es un procedimiento básico y muy frecuente en el uso de Calc o de Excel.

(7) De hecho no necesito crear dos párrafos, siendo ahora suficiente con uno.

(8) Te sugiero aplicar esta modificación al documento que puedes [descargar desde este enlace]

martes, 12 de diciembre de 2023

Funciones. Texto.

Concatenar cadenas.

Aunque no sólo, cuando creamos un texto cuyo contenido puede variar en función de características y/o resultados del procesamiento de datos, además de utilizar condicionales para crear recorridos posibles (mediante la función SI() y la estructura If), también necesitamos unir en un único texto cadenas de texto y variables. Para eso contamos en Calc con funciones como CONCATENAR(), pero también con procedimientos específicos en OOo Basic.


Aunque quizá no sea el servicio donde más utilidad se va a obtener de estos procedimientos, resulta que es en Calc donde tenemos disponibles tres funciones relacionadas con algo que en principio parece de mayor utilidad en Writer. Claro que hablo desde la perspectiva de la automatización de documentos y aun así esta aparente limitación no lo es tanto si pensamos en la creación de docap complejos que combinan Calc+Writer, como algunos que ya hemos creado.

En todo caso, ahora nos centraremos en la identificación y el análisis de estas funciones: CONCAT()CONCATENAR() y UNIRCADENAS() (1). Todas ellas se ubican dentro de la categoría Texto de funciones Calc, comparten el mismo objetivo y, en el caso de las dos primeras, una formulación o sintaxis muy similar y sencilla, consistente en una serie de entradas (directas y/o referencias a celdas) separadas por ; como, por ejemplo:

=CONCAT(B4;B5;B6;B$9:B$13)
=CONCATENAR("La casa de la Pradera ";"está en mitad del campo")

No obstante, en  lo relativo a la referencia a celdas CONCAT() resulta ser una evolución de desarrollo de CONCATENAR() (2), ya que...

  • Mientras  que CONCAT() admite referencias a celdas individuales, pero también a colecciones o intervalos de celdas
  • CONCATENAR() sólo admite referencias a celdas individuales (no a intervalos)

La función UNIRCADENAS() tiene una sintaxis ligeramente diferente, permitiendo trabajar mejor el formateo de la cadena resultante. Consta de:

  • Un delimitador, que es de uso obligatorio y que permite establecer una cadena de texto (incluyendo un  intervalo) que se usará como separadores de las cadenas entre sí.
  • Una variable booleana que permite omitir (1/True) o no (0/False) las cadenas vacías
  • Y las cadenas a unir, que pueden ser string en entrada directa (los números se admiten pero se convierten a string), cadenas vacías, referencias a celdas (con o sin contenido) e intervalos del celdas. A modo de ejemplo...

=UNIRCADENAS("--";1;1234; ;"adbd";B10;B4:B6)

... la función UNIRCADENA() especifica el string -- como separador, omite las cadenas vacías (valor 1 en el segundo parámetro) y contiene entradas directas desde teclado (número y string), pero también referencias a celdas individuales (B10) y a intervalos de celdas (B4:B6). El resultado es el que sigue:

1234--adbd--EEEE--PPPP--LLLL--MMMM (3)

El resultado de usar cualquiera de las tres funciones (4) es una única entrada de texto (los valores numéricos son tratados como texto) que puede ser todo lo larga que deseemos, por lo que es perfectamente válida para generar procesos de automatización de la composición de documentos, utilizándolas, claro está en combinación con otras funciones, como hemos hecho en algunos soportes (no docap) de trabajo sobre pruebas de evaluación (5)

Aunque realmente el uso de estas funciones puede ser más que suficiente para la automatización de un documento, sin que sea necesario recurrir a un script OOo Basic, lo cierto es que sí parece conveniente trabajar con esta segunda opción, no tanto para la concatenación en sentido estricto como para la generación de textos (string) a concatenar. Con frecuencia para ello es necesario utilizar estructuras condicionales anidadas complejas, con lo que, por la que ya vimos en una entrada anterior, un script OOo Basic resulta ser más legible, sostenible y funcional que su equivalente en funciones condicionales Calc (SI() principalmente). En ese contexto, una vez que se utiliza el IDE para una parte del proceso, no es infrecuente que se termine utilizando también para crear salidas de texto basadas en la concatenación mediante procedimientos OOo Basic.

Además la simplicidad con la que se concatenan cadenas de texto con variables, bien tipo String, bien numéricas, hace que sea sumamente sencillo realizar estos procesos desde OOo Basic, así que ya de puestos...

Ciertamente crear un contenido resultante de la concatenación de literales (datos introducidos directamente) y/o variables de diferentes tipo es sumamente sencillo. Básicamente se trata de enunciar esos contenidos enlazados bien con +, bien con &. Ambos caracteres cumplen, en la práctica, la misma función por lo que, salvo contadas ocasiones, se pueden usar indiscriminadamente y todas la veces que resulte necesario.

De hecho + sirve tanto para concatenar como para sumar, por lo que sólo cuando los literales (o las variables) son numéricos es conveniente diferenciar cuando nos interesa que se ejecute una suma y cuando una concatenación de dos números (6). Veamos ejemplos en un script cuya única función es de carácter didáctico:

dim txt As String
dim num1 As Integer, num2 As Integer
txt = "Hola Mundo"
num1 = 123
num2 = 893
MsgBox("Cadena1" + "cadena2")         (1)
MsgBox("Cadena1" & "Cadena2")         (2)
MsgBox("Cadena1 " + txt)                   (3)
MsgBox("Cadena1 " & txt)                   (4)
MsgBox("Cadena1 " + num1)               (5)
MsgBox("Cadena1 " & num1)               (6)
MsgBox(num1 + num2)                       (7)
MsgBox(num1 & num2)                       (8)
MsgBox(CStr(num1) & CStr(num2))     (9)

  • Se expresa la concatenación como salida por pantalla (MsgBox()), pero el procedimiento es exactamente igual si lo utilizamos para asignar como contenido de una variable.
  • (1) y (2) ilustran básicamente la concatenación de literales textuales y la igualdad del procedimiento + vs. &.
  • (3) y (4) combina literal con variable String. El comportamiento es el mismo que en el par anterior.
  • (5) y (6) son equivalentes al par precedente, sustituyendo la variable string por una variable Integer.
  • (7), (8) y (9) ilustran la diferencia operación (suma-> +) vs. concatenación (&) cuando empleamos dos variables numéricas. (8) y (9) dan el mismo resultados (concatenan dos expresiones numéricas) En realidad ambas operan sobre variables numéricas convertidas a String, (8) de forma implícita, (9) explicitando la conversión mediante el uso de la función CStr(). Aunque no resulte necesario, se recomienda utilizar este procedimiento cuando se desee tratar a un variable numérica como variable String. En buena lógica, lo mismo debería aplicarse en (5) y en (6)
Pensando en la claridad de la codificación, quizá lo más apropiado sea utilizar + únicamente como operador aritmético y emplear & para concatenar contenidos. De este modo no hay confusión posible. Este modo de proceder...
  • Eliminaría del listado las alternativas (1), (3), (5) y (8)
  • Exigiría utilizar CStr() en (6)
  • Eliminaría (7) o lo conservaría (7) como ejemplo de operador aritmético (no de concatenación)
  • Y mantendría (9) como alternativa a (8).

En la concatenación, o mejor sería decir  en el formateo de las cadenas resultantes de la concatenación también cabe utilizar algunos recursos que facilitan la composición de textos, como puede ser el uso del salto de línea (Chr(13)). Su repetición nos permite aumentar el número de saltos de línea (7).

NOTAS

(1) Ya sabes que lo que sigue después de este análisis es estudiar las alternativas OOo Basic y, en otro momento y entrada, el estudio del modo en que se resuelven problemas similares en Python. Pero aun queda para hacer todo este recorrido.
(2) CONCAT() es de creación más reciente que CONCATENAR()está disponibles desde la versión 5.2 de LibreOffice
(3) Este caprichoso resultado es el que deriva de la prueba realizada. Las dos primeras cadenas fueron introducidas directamente, la tercera es una cadena vacía que queda omitida por el uso de 1 en el segundo parámetro y el resto corresponden al contenido de la celda B10 y del intervalo B4:B6 respectivamente. 
(4) Hasta donde yo entiendo, sólo la necesidad de concatenar intervalos de celdas condiciona la elección de CONCAT() sobre CONCATENAR(). El uso de UNIRCADENA() vendrá dado por el interés que tenga especificar separadores de cadenas específicos y/o omitir cadenas vacías. No encuentro otras razones que justifiquen su uso. 
(5) En otro momento comentaré alguno de estos soportes que he empleado como recurso para el registro de datos en relación al uso de determinados test. Estos soportes contaban con una hoja que servía directamente de informe o indirectamente, tras su conversión a .pdf. 
(6) En realidad, cuando concatenamos dos números con &, de forma implícita OOo Basic convierte ambos números en String. Por claridad en la codificación, aunque no sea necesario, es conveniente realizar la conversión de número a String mediante la función CStr()
(7) Chr(10) parece cumplir la misma función que Chr(13): generar un salto de línea. De todas formas, aunque estos procedimientos son muy simples, en cuanto a formateo del texto Grabar macro permite enriquecer estas opciones de forma significativa, pero no entra dentro del contenido de esta entrada.

miércoles, 6 de diciembre de 2023

Procedimientos. Datos.

Calc. Función. Script como función

Hemos visto en entradas que preceden a la actual, diferentes aspectos de la configuración de la condicionalidad/opcionalidad/iteración y hemos opuesto el uso de funciones Calc (SI(), por ejemplo) al uso de script OOo Basic. Pero bajo determinadas condiciones, Calc asume como funciones propias los script creados con OOo Basic.


En esta entrada vamos a profundizar en esta posibilidad, en sus condicionantes y también en sus limitaciones.

Ya sabemos que accedemos a las funciones Calc bien desde la línea de entrada (de funciones), bien desde el icono que nos da acceso al Asistente para funciones. También sabemos que para acceder a un script debemos hacerlo desde el menú Herramientas/Macros/Ejecutar macro, o bien desde un botón de comando creado en la hoja como elemento de formulario y asociado previamente a la macro en cuestión.

Estos conocimientos nos van a seguir siendo útiles y lo que añado en esta entrada es una forma alternativa y de utilidad ciertamente limitada, pero de interés: acceder a ciertos script desde la línea de entrada de funciones Calc.

Estos script pueden presentarse identificados como subrutinas (Sub...End Sub) y van a funcionar (inicialmente al menos) de forma correcta, pero no recomiendo formularlos de ese modo, ya que pueden presentar un comportamiento un tanto errático. Estas subrutinas pueden serlo en efecto, pero también pueden presentar una formulación mixta entre el esperado en una subrutina y el propio de una función(1)

También, sean identificados como subrutinas o como funciones, pueden contener variables internas personalizables (esto es: que necesiten una entrada de datos desde, por ejemplo, InputBox()), pero personalmente tampoco recomiendo este tipo de construcción mientras LibreOffice-Calc no mejore su comportamiento al usarlas: se pueden generar insistentes demandas de entrada de datos (¿bucles?) que no vienen a cuento.

Ahora bien, existe un tipo de estructura que funciona perfectamente y sin que se observen inconvenientes, pudiendo ser empleadas desde rutinas que contienen su llamada (2) como desde la línea de entrada de funciones de Calc, y del mismo modo que se llama a una función propia de Calc (como la función condicional SI(), por ejemplo). Me estoy refiriendo a las funciones creadas con OOo Basic.

Recordemos que para escribir correctamente una función debemos seguir los siguientes pasos:
  1. Nombrarla siguiendo esta sintaxis: Function NombreFuncion(Var1 As Tipo[...]) As Tipo
  2. Declarar, si existen, variables propias o privadas de la función y darles los valores que corresponda.
  3. Formular la operación que incluye la(s) variable(s) indicadas entre el paréntesis de la función (parámetros). Aquí entra también el uso de las estructuras condicionales o cíclicas, simples o complejas, que sean necesarias.
  4. Asignar al nombre de la función la salida o resultado de la(s) operación(es) anteriores. Debe corresponder en tipología a lo indicado en la denominación de la función: NombreFuncion=Operación/VariableQueContieneElResultado 
  5. Y cierre de la función: End Function 
Un ejemplo muy sencillo:

Function multiplicados(Num As Integer) As Integer
Dim Multi As Integer, Resulta As Integer
Multi = 5
Resulta = Num * Multi
multiplicados = Resulta
End Function

La forma de llamar a estas funciones es la misma que a cualquier otra función Calc (desde Línea de entrada) o a cómo las llamamos desde un script:

 NombreFuncion(Valores/VariablesDeParametros) -> multiplicados(12)

Si lo hacemos (y de eso se trata ahora) desde Línea de entrada (de funciones) en Calc, obtendremos el resultado en la celda desde la que la llamamos...



... pero al contrario de lo que pasa con las funciones propias de Calc, nuestras funciones no se encuentran en los listados del Asistente para funciones, sino en la pestaña Estructura...

... desde donde también podremos llamar a la función (ventana Fórmula, tras el signo =), aunque posiblemente con algún mensaje de error que no se corresponde con tal, por lo que se puede eludir sin más complicación, pero que hace que esta forma de llamar a la función no sea mi preferida (3)

Estas nuestras funciones son accesibles desde Calc estando ubicadas en la misma hoja de cálculo (obviamente en una Biblioteca/Librería y en un Módulo) o en Mis macros y diálogos. En el primer caso estará disponible para la hoja que la contiene y en el segundo para cualquier hoja de cálculo en que deseemos usarla. Obviamente, salvo circunstancias especiales, es la segunda opción la más rendimiento nos va a proporcionar. 

NOTAS

(1) Recuerda que en OOo Basic se diferencia entre subrutina y función, incluso en  la forma de identificar cada una de ellas: Sub Nombre().... End Sub (subrutina) frente a Function Nombre()... End Function (función)
(2) Y por tanto activadas desde botones de comando o directamente desde Ejecutar macro.
(3) Llamar a la función desde Línea de entrada resulta ser más directo y más seguro, por lo que recomiendo utilizar esta opción. 

domingo, 3 de diciembre de 2023

OOo Basic. Datos

 Operadores de asignación, concatenación y de relación

Los operadores son expresiones breves (uno o dos signos) que permiten el trabajo con las variables. Podemos diferenciar tres tipos: el de asignación, los de concatenación y los relacionales o de relación (1).




Los operadores de concatenación son dos: & y +, que se pueden usar indistintamente cuando trabajamos con variables string o con variables string y de tipo numérico, aunque en ambos casos es preferible utilizar el concatenador & por ser el operador específico para esta operación (2).

Los operadores de relación son los más numerosos y complejos. Permiten comparar el valor de dos expresiones, confirmando conjuntamente (expresión 1 # operador # Expresión 2) una proposición. Como tal proposición puede tener valor V (1 o True) o F (0 o False)

La lista de operadores relacionales en OOo Basic es breve, pero suficiente para realizar las comparaciones necesarias entre expresiones (o entre variables) y generar las proposiciones básicas.

Aunque parecen priorizar las comparaciones entre variables (y expresiones) numéricas, también sirven para realizar comparaciones entre variables no numéricas, aunque en este caso con ciertas restricciones en términos de equivalencia/igualdad. 

El operador de asignación (=) tiene como función asignar contenido (del tipo que sea) a una variable. Su uso es aparente muy sencillo (sVar = "Casa", iNum = 323) pero presenta una dificultad que deriva del hecho de que OOo Basic utiliza el mismo signo para el operador de asignación y para la igualdad o equivalencia (uno de los operadores relacionales), lo que genera cierta confusión. Por ejemplo:

Siendo...

Dim A As Integer, B As Integer, C As Integer

 Decir...

A = 230

B = 540 

 ... es asignar el entero 230 a la variable A, y 540 a la variable B, pero también se puede entender que A vale 230 y B 540, por lo que...

C = A + B

... implica tanto asignar el resultado de la A+B (230+540 -> 770) a C como plantear que C es el resultante de la operación matemática +  aplicada sobre A y B

En este caso. ambos significados son equivalentes, pero si A y B son cadenas...

A = "Casa"

B = "Mesa"

... ahora es evidente que las respectivas cadenas no son "valores" de A y de B, sino contenidos asignados a los espacios de memoria RAM identificados como A y B, y si...

C = A + B (aunque es preferible A & B)

 ... C no resulta de sumar A + B, sino de concatenar ambas, siendo que asignamos a la cadena resultante "CasaMesa"

Una tercera circunstancia es cuando empleamos cualquier proposición en la que dos expresiones, dos variables o una expresión y una variable son comparadas mediante cualquiera de los operadores relacionales, como, por ejemplo...

A < 100

... pero también

A = 100

... en el marco de una estructura condicional (If...End If). En este caso no se está haciendo una asignación, sino expresando una comparación, concretamente que A es inferior a 100 (A<100) o que A es igual a 100 (A=100), pudiendo ser 100 asignado a B, con lo que A=100 es equivalente a A=B

En este caso (A = 100 equivalente A = B, para B =100) lo que pedimos de LibreOffice es que valore si esta proposición es cierta (V) o falsa (F) para proceder como corresponda en función de la bifurcación del algoritmo que contiene el condicional If.

NOTAS

(1) En realidad existe un cuanto tipo de operadores, los aritméticos, pero estos ya han sido expuestos [en esta entrada]

(2) Concatenar significa unir cadenas, lo que remite a datos de tipo string o que funcionan como tales. Aunque podemos usar el concatenador +, no es recomendable por la posible confusión con el operador aritmético de suma. Ver al respecto [esta entrada]

domingo, 5 de noviembre de 2023

Procedimientos. Docap.

DOCAP combinado Calc + Writer

También es posible crear docap complejos empleando dos archivos del mismo servicio: dos hojas de cálculo o dos documentos de texto). Pero tampoco tenemos por qué limitarnos a utilizar dos documentos.


Eso es precisamente lo que he hecho en esta ocasión: utilizar dos hojas de cálculo como componentes básicos del docap y opcionalmente un documento Writer; este último de cumplirse una condición. La imagen anterior representa la composición del modelo de docap complejo que expondré en esta entrada.

En ella me voy a limitar a explicar el funcionamiento de este modelo de docap y mostrar las instrucciones fundamentales de su código, pero si deseas saber qué objetivo se persigue con el docap concreto que utilizo de ejemplo, deberás leer [esta entrada]. También dispones de un vídeo en [YouTu.be] para visualizar su funcionamiento.

Veamos ahora la estructura de componentes del docap, empezando por visualizar su esquema general.



En este docap se pueden diferenciar tres fases:

Primera: Fase input mediante formulario sobre documento Calc Gestor. Como ya sebes de otros docap anteriores, los controles del formulario se asocian celdas directamente desde la configuración de los controles que lo componen.



... y mediante script accedo al contenido de estas celdas para asignarlos a una matriz. 

oHojaDatos = ThisComponent.getSheets().getByName("Datos")

For i = 1 To 3
oCelda = oHojaDatos.getCellRangeByName("B" & i)
sDatosPer(i-1) = oCelda.getString()
Next

Tomando parte de estos datos creo un listado a modo de base de datos. Esta base de datos es muy simple y se limita a unos pocos campos, pero el procedimiento que implica es de gran importancia, ya que nos puede servir de base para crear docap entrados en los procesos de evaluación grupal. De hecho, sin esta funcionalidad que ahora es complementaria, el docap puede considerarse referente básico para crear soportes para la aplicación de test estandarizados, pero el hecho de crear este listado-BD permite avanzar en la creación de soportes de evaluación que toman como referencia el grupo-clase y permiten crear baremos locales (1).

For i= 1 To 500
oCeldaInicio = oHojaLista.getCellByPosition(0,i)
sContenido = oCeldaInicio.getString()
If sContenido = "" Then
For a =0 To 4
oCeldaInicio = oHojaLista.getCellByPosition(a,i)
oCeldaInicio.setString(mListado(a))
Next
Exit For
End If
Next

El paso siguiente y con el que finaliza esta primera fase consiste en el acceso al documento Calc Ficha como plantilla y activando el uso de macros.

mOpciones(0).Name="AsTemplate"
mOpciones(0).Value=True
mOpciones(0).Name="MacroExecutionMode"
mOpciones(0).Value=4

sRuta = ConvertToUrl("D:\ModeloExpediente.ods")
oDoc = StarDesktop.loadComponentFromURL( sRuta, "_blank", 0, mOpciones() )

Segunda: La plantilla Ficha genera automáticamente el documento que concreta la ficha del alumno y que se archiva dentro de la carpeta Expedientes. Dentro de este archivo se concreta el doble proceso de traslado de datos al listado de campos y su asociación a un conjunto de celdas que muestras dichos datos en formato ficha (de ahí el nombre del documento.


Posteriormente se accede al contenidos de determinados campos...


For i=0 To 10
    oCelda(i) = oHojaDatos.getCellRangeByName( "A" & i+1 )
     sDatos(i) = oCelda(i).getString
Next

... para posteriormente analizar los datos que contienen y que se consideran relevantes (2).

If iTotalDif = 0 Then
sValorDif = " no existe diferencia en cuanto al númer de documentos, lo que indica que el expediente se ha mantenido actualizado hasta el momento."
ElseIf iTotalDif > 0 Then
sValorDif = "una reducción del número de archivos (" & ABS(iTotalDif) & " documentos)"
ElseIf iTotalDif < 0 Then
sValorDif = "un incremento del número de archivos (" & ABS(iTotalDif) & " documentos)"
End If

En función de este análisis se plantean diferentes opciones de documentación, incluyendo la creación de un tercer soporte (Writer) que denomino Informe.

If dPorcentajeDif > 25 Then
CrearInfo (sIdentificador,sNumDoc,sAnalisisTotal,sValoraPorcentaje)
Else
MsgBox ("ANÁLISIS DE RESULTADOS: " & Chr(13) & sIdentificador & Chr(13) & sNumDoc & " " & sAnalisisTotal & " " & sValoraPorcentaje)
End If

Tercera: Esta fase se desarrolla bien dentro de Ficha, cuando no se considera necesario crear un informe (3) o, y de forma más específica y compleja, a partir del propio documento Writer Informe. En este caso se puede (también es opcional) aplicar una macro de formato. Esta macro es universal, pero podría estar específicamente creada para formatear dicho documento, aunque necesariamente deberá ser ubicada en Mis macros (4)

dim args4(4) as new com.sun.star.beans.PropertyValue
args4(0).Name = "CharFontName.StyleName"
args4(0).Value = ""
args4(1).Name = "CharFontName.Pitch"
args4(1).Value = 2
args4(2).Name = "CharFontName.CharSet"
args4(2).Value = -1
args4(3).Name = "CharFontName.Family"
args4(3).Value = 5
args4(4).Name = "CharFontName.FamilyName"
args4(4).Value = "Verdana"
dispatcher.executeDispatch(document, ".uno:CharFontName", "", 0, args4())

NOTAS

(1) La relevancia de esta cuestión sobrepasa el objetico de esta entrada, por lo que ahora no seguiré tratando este tema, pero sí quiero señalar su gran importancia para la definición de un modelo de intervención de los SEO, diferenciado del modelo clínico aun predominante en la práctica profesional real.

(2) El análisis que se realizar en este docap en concreto está limitado conscientemente por la función que se pretende que cumpla, evitando entrar en procesos de mayor complejidad. En caso de ser empleado para desarrollar el uso de en test en concreto, sería necesario profundizar en el modelo de análisis.

(3) En este caso (cuando se incumple el criterio de una diferencia superior al 25%) se emite un breve informe soportado en MsgBox desde la propia ficha.

(4) Esto está relacionado obviamente por ser un documento creado desde el propio código del documento Ficha.

Documentos. Expediente

Mantenimiento del expediente SEO digitalizado.

En una entrada anterior hablaba yo de las carencias del proceso de informatización de los "expedientes" SEO del alumnado con NEAE y reclamaba la necesidad de profundizar en ella, así como de disponer de recursos para facilitar dicha informatización. Considero ahora también necesario contar con recursos que ayuden al mantenimiento de estos "expedientes", ya que se observa que con el tiempo tienden a degradarse a consecuencia de la falta de sistematización y de continuidad en su gestión. 


Propongo para ello elaborar un recurso que ayude al análisis de esta documentación que llamo impropiamente "expediente SEO" por facilitar la comprensión de su naturaleza, a sabiendas que sólo existe un expediente escolar y es el que se encuentra custodiado en los colegios. 

Salvando rigores de denominación, es necesario añadir a las deficiencias observadas en la entrada citada al inicio de la actual, la tendencia a la desorganización de estos expedientes derivada del paso del tiempo, la pluralidad de gestores y usuarios, pero también de la propia ausencia de sistematización de los expedientes.

Este recurso (docap) no evita dicho desorden pero ayuda a sistematizar y reorganizar el expediente, además de contribuir al análisis de los datos que derivan de dicha sistematización. Si satisface suficientemente estos objetivos ya contribuye sobradamente al fin último que se persigue en este blog: colaborar en el proceso de informatización de la documentación SEO, como medio de favorecer sus sistematización, mantenimiento y análisis.

La sistematización se concreta en el modelo de recogida de datos que se propone y que reflejan los formularios que se emplean. Cualquier modificación de los criterios subyacentes implica necesariamente una modificación de dichos formularios.


En mi propuesta opto por analizar la documentación inicial y final en función del soporte o tipo de documento, categorizar su tipología en función de tres variables de contenido: Actuaciones, Informes y MAD y, en paralelo y/o como subdivisión de las anteriores en categorías más cercanas al contenido real de los documentos (entrevistas, observaciones, informes, PTI...) Pero únicamente se trata de una propuesta y, además, provisional (1)

El cuanto al mantenimiento de los expedientes, la mayor contribución de este docap lo es en la creación de una ficha individual por alumno. Precisamente nació como herramienta para facilitar esta tarea, después de desarrollarla manualmente sobre un número suficiente de expedientes. Aunque los resultados son modestos, he comprobado que son satisfactorios en términos de ahorro de tiempo.

Finalmente, y también como último desarrollo del docap (es lo último que he implementado en él), he añadido un  procedimiento, sencillo y limitado, para facilitar la recogida sistemática de información que se concreta en la creación de una base de datos, como fuente para un posterior análisis de datos. Únicamente me quedo en esto (en la práctica), aunque apunto hacia ciertas posibilidades de concreción de dicho análisis. Para mis fines esto es más que suficiente, pero es posible que no si se desea utilizar como recurso con esta finalidad como principal objetivo (2)

Este docap va dirigido a facilitar el registro sistemático y actualizado del conjunto de documentos informatizados que conforman dicho expediente. De hecho nada impide que también se incluyan los documentos en soporte papel, aunque sería necesario, para ello, realizar las modificaciones que correspondan, tanto en el soporte de gestión (Gestor) como en el de almacenamiento (Ficha).

También es posible (y yo diría aquí que necesario) ampliar y mejorar los procedimientos de análisis que se ubican en el código del documento Ficha, a fin de mejorar la elaboración del documento Informe (Writer), ya que su redacción es actualmente muy básica. Mejorar este aspecto puede implicar desarrollar procesos de análisis y recogida de datos que no se plantean en estos momentos, aunque la mera formulación del informe ya permite un primer acercamiento a dicho análisis.

En cuanto al funcionamiento, aunque no me voy a detener en aquello que ya ha sido explicado en la entrada o en el vídeo complementario, sí quiero insistir  en algunas cuestiones:

  • El soporte de gestión (Gestor) utiliza el ya conocido recurso de asociar control-celda. Esto simplifica el funcionamiento del docap y justifica que se utilice Calc en la fase input.
  • Lo mismo puede aplicarse al segundo componente (Ficha) aunque aquí en sentido inverso: las celdas de Ficha a las que se trasladan los valores desde Gestor se asocian mediante procedimientos elementales Calc con otras celdas (vg. A1=B5), permitiendo así simular la visualización del contenido en formato "ficha".
  • El código OOoBasic no resulta novedoso, ya que es el mismo que se ha empleado en docap anteriores para acceder al contenido de las celdas (previo acceso al documento y a la hoja). La forma en que se concreta este código ha sido expuesta en una entrada que complementa a ésta  y está a disposición del interesado desde el IDE de los propios documentos originales (3)
  • Tanto en la creación de la base datos como en la ficha individual he reducido conscientemente la complejidad del análisis de los datos para eludir complicaciones que son de poca utilidad en estos momentos. No obstante una propuesta de trabajo real implica acordar a nivel de SEO la gestión y el tratamiento a dar a la información y, una vez acordado, proceder en consecuencia desarrollando procedimientos de análisis más complejos y ajustados a los objetivos que se establezcan.
  • Algo similar se puede decir respecto al texto del documento Informe, como cabe esperar en función de la relación que existe entre éste y el resultado del análisis de los datos individuales. De hecho, el con el uso (opcional) de este tercer componente en el docap  pretendo únicamente mostrar que es posible crear un proceso complejo de interacción entres diferentes componentes y servicios de LO, utilizando cada uno de ellos en la forma y para el fin en que resulte más conveniente y útil.

NOTA 1. Animo a plantear colectivamente una propuesta de estructuración de los contenidos del expediente SEO. Aunque únicamente sea provisional (como lo es mi propuesta) aplicarlo de forma sistemática, prolongada en el tiempo y suficiente en frecuencia permitirá apreciar las ventajas que aporta esta sistematicidad y aportará datos para formular propuestas más sólidas en futuro.

NOTA 2. En ese caso es necesario definir a priori el tipo de análisis que interesa, a fin de identificar los datos necesarios y proceso de análisis a llevar a desarrollar. En esta línea estoy trabajando sobre un proyecto de análisis, pero no lo vinculo a este docap para hacerlo más sencillo y poder ofrecerlo desde ahora como recurso, sin esperar a la conclusión del proceso de revisión y sobre todo de análisis de resultados. Entendiendo las limitaciones que esto conlleva, prefiero que pueda ser de inmediata utilidad aunque provisional. Tiempo habrá, si es que resulta pertinente, de ofrecer una herramienta más potente en términos de análisis de datos; por ahora es suficiente que lo sea para la creación de documentos de expediente.

NOTA 3Ver a continuación en Descarga.

Descarga. Documentos necesarios para el funcionamiento del docap.

  • Estos archivos se deberán descargar y copiar en la unidad D, directorio raíz. Cualquier cambio en esta ubicación implica modificar el código correspondiente.
  • En esa ubicación deberá crearse una carpeta llamada Expedientes. En ella se guardan automáticamente las fichas individuales y se recomienda guardar manualmente los informes. Ambos se crean de forma automática según el funcionamiento del docap.
  • En Gestor se deben cumplimentar TODOS los campos, no dando por cumplimentado ninguno, bien sea que aparezcan con un valor por defecto (0) o vacíos. No hacerlo provoca error en el funcionamiento del docap y su suspensión.
  • La macro de formato para informe deberá ser copiada dentro del directorio IDE Mis macros, librería Standard y activada desde la misma de forma directa ((Herramientas/Macros/Ejecutar macro)
Documentos: