lunes, 30 de octubre de 2023

OOo Basic. Writer

 Script y subrutinas de escritura

  • Código básico:

oDoc = ThisComponent.CurrentSelection.getByIndex(0).End
oDoc.String = "Texto que se desea escribir"

Script OOo Basic para automatizar la escritura de texto sin usar Grabar macro.

Contiene subrutina y script principal. El script se ha creado para facilitar interface con el usuario mediante InputBox(), pero puede prescindirse de ello sin alterar el funcionamiento del script.

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

Contiene subrutina (basada en matriz) y script principal. Ambos emplean una matriz para compartir datos masivos, La subrutina escribe el contenido utilizando un bucle for para automatizar el proceso.

viernes, 27 de octubre de 2023

OOo Basic. Datos

 Variables, parámetros y argumentos

En las funciones y subrutinas las variables presentan un comportamiento específico que es necesario conocer tanto para entender estas unidades de programación como para diferenciar la una de la otra.



Al 
igual que un script o una macro, las subrutinas y las funciones suelen contar con variables que permiten asignar los valores o datos necesarios para su correcto funcionamiento. Pero subrutinas y funciones cuentan, además, con al menos una variable con una función específica: facilitar su comunicación con el script. Se trata de la variable (o variables) que se declara dentro del paréntesis con el que se identifica la propia subrutina como tal (y también la función).


En OOo Basic al crear un script (o una macro) es suficiente con identificar el componente y nombrarlo mediante Sub NombreMacro. Además hay que cerrarlo mediante End Sub (1). Pero para crear una subrutina es obligatorio escribir un paréntesis tras el identificador o nombre e incluir dentro un identificador de variable y su tipificación: sub NombreSubrutina(NombreVar As TipoVar)

La subrutina puede contar (o no) con variables declaradas dentro de ella, pero mientras que éstas son denominadas variables sin más, la o las que se declaran dentro del paréntesis son denominadas específicamente parámetros, por lo que el contenido queda identificado como sigue (o cualquier otra formulación, incluyendo varios parámetros):

Sub NombreRutina(IdParametro As TipoVariable)

Dim NombreVar 1As TipoVar, NombreVar2 As TipoVar (Opcionales)

NombreVar2 = NombreVar1 operador IdParametro (Operaciones)

If  NombreVar2 Operador X Then (por ejemplo...)
ProcesoAejecutar1
Else
        ProcesoAejecutar2
End If 

End Sub

Esta denominación (parámetro) lo es desde el punto de vista de la función o subrutina, pero como ésta ha de ser activada (llamada, si se prefiere) desde un script principal, el valor que se pasa equivalente y/o como concreción del parámetro  recibe el nombre de argumento.

Sub ScriptPrincipal

...
NombreRutina(argumento) (llamada a subrutina)
...

End Sub 

También el modo en que se utilizan parámetros y argumentos son diferentes en función de que estemos hablando de una subrutina (que ejecuta una acción) o una función (que devuelve un valor), aunque esta diferenciación de nombre es pertinente en Basic, pero no necesariamente en otros lenguajes (2).

Las denominaciones (parámetro(s), argumento(s)) se mantienen, pero las estructuras, su denominación (3) y el modo de usarlas cambian, aunque estas diferencias corresponden a otro tema, expuesto ya en otra [entrada a la que remitopara no repetir contenidos. 


NOTAS

(1) Algunos programadores utilizan por costumbre  y asociación a las subrutinas el paréntesis al final del nombre, pero lo mantienen vacío (sub NombreMacro())

(2) Por ejemplo en Python se denomina función a ambas, aunque la diferencia de funcionamiento es la misma que en OOo Basic: existen funciones que no devuelven nada (ejecutan una acción) y otras que sí (las que en OOo Basic son funciones propiamente dichas)

(3) Posiblemente ya saber que en OOoBasic las subrutinas no reciben una denominación específica, pero las funciones sí, tanto para iniciarlas como para finalizarlas: Function... End Function. 


Opinión. Evaluación.

Sobre la reclamación de calificaciones.

Recientemente me he encontrado con una documentación de apoyo al profesorado, proporcionada por SIE de la Consejería de Educación de Asturias que he de reconocer me ha dado que pensar. Tanto en positivo como en negativo. Me limito a la documentación para E. Primaria, pero los soportes dan respuesta a todas las etapas y opciones educativas.


Es mucho lo que de positivo que tiene esta documentación, y no renuncio a comentarlo, pero también de negativo hay, aunque cierto es que más por lo que implica (esa documentación) que por lo que propiamente de negativo tiene ella misma.

Pero antes de nada empezaré por decir que lo que presento aquí son impresiones personales, no análisis documental o temático. Eso, de hacerlo, será en otro momento; por ahora tan sólo comparto impresiones.

Las positivas:

  • Es de agradecer que el SIE se involucre, dentro de su función de asesoramiento, proporcionando documentación rigurosa y fundamentada en derecho administrativo para facilitar el abordaje de una cuestión tan compleja que no en pocas ocasiones acentúa los conflictos que la hacen necesaria.
  • Cierto es que esta documentación pretende también formalizar el procedimiento, simplificando a posteriori la toma de decisiones que corresponda a la Consejería de Educación y al propio SIE, pero esto no tiene nada de negativo, al contrario, es un beneficio para todos los implicados, empezando por el propio profesorado y las familias involucradas.
  • También es positivo que la documentación en sí recoja el conjunto de procedimiento y de respuesta a esos dos contextos o situaciones en los que se puede presentar en E Primaria(cursos pares, con sus implicaciones de promoción de ciclo y cursos impares): el tratamiento minucioso y sistemático del procedimiento que subyace permite que la documentación de respuesta integral al mismo, no dejando partes del procedimiento sin atender.
  • El propio formato facilita que sea (formalmente) accesible: al estar soportado sobre documentos Word se facilita tanto la accesibilidad como el manejo de la documentación. 
  • El hecho de incluir una redacción en la que se identifican con claridad los elementos a complementar de los opcionales facilita la cumplimentación de la propia documentación.
  • Aunque sólo como potencial desarrollo/aplicación de lo que aquí emerge, esta documentación facilita concretar la colaboración/asesoramiento del SIE a los centros y, en particular a los equipos directivos, vía para que éstos lo puedan hacer de las familias y los equipos educativos.
Pero también las negativas, empezando por las formas...

  • Sería deseable que la forma en que se presenta la documentación incluyera procedimientos de (semi)automatización de cumplimentación de la misma, y mejor aun, de integración del procedimiento en los recursos de gestión documental de los procedimientos administrativos (léase en el caso de Asturias desarrollo de SAUCE en esa línea).
  • También sería de agradecer que se proporcionaran ejemplos concretos de formalización del proceso y de cumplimentación de la documentación; un "a modo de" casuística. Cuanto menos esta documentación debería estar disponible para que el SIE oriente/asesore a los equipos directivos y/o docentes.
Con todo, lo que más llama mi atención son las siguientes cuestiones que expreso como "temores":

  • Me temo que la complejidad jurídico-administrativa que expresa la documentación presentada supere con mucho la capacidad de gestión de los centros, y más aun de los equipos docentes: entender no tanto la documentación como el procedimiento que subyace y su naturaleza jurídico-administrativa implica y pone de manifiesto la consolidación de una tendencia para nada positiva de hacer compleja innecesaria y hasta contraproducente la labor educativa...
  • .. así como la consolidación aun más negativa de la "cultura" de la queja y de la primacía del derecho (del alumnado y de sus representantes legales)  como "consumidores/usuarios" imponiéndose a la función educativa de la institución escolar y del profesorado con todos sus significados. 
  • No sin cierto cinismo por mi parte, lo reconozco: resulta "curioso" que la reclamación se entienda necesariamente ligada a una calificación negativa o una decisión de no promoción, pero no sobre una calificación positiva indebida o una petición de no promoción como opción de la familia.
  • Desde luego no es lo que se concreta en el texto real de la documentación, pero sí lo que aparenta el título de (algunos) los documentos: el profesorado es quien debe justificar su calificación/decisión que se supone (aparentemente) susceptible de ser modificada. Esa es la solución (aparentemente) "preferente".
Resumo: mucho me temo que lo que esta documentación trasluce (y con ello no quiero matar al mensajero) es el cambio de perspectiva que tan bien representa la imagen que ilustra esta entrada: el mundo en el que el alumno es cliente que debe ser satisfecho no es el mundo en el que el alumno lo es por derecho (y obligación) a la educación. 

En este tránsito, el profesorado ha pasado de ser el responsable y guía de ese proceso educativo a ser responsabilizado del fracaso del alumnado en el logro de los objetivos de aprendizaje. Curiosa realidad ésta en la que el éxito siempre es del que aprender y el fracaso (del que aprende) no se considera opción y de darse se entiende "razonablemente" responsabilidad del que enseña.

La Escuela así entendida no sólo es un parque de atracciones (que también), es una manifestación más del mercado. Y ya se sabe que el cliente siempre tiene la razón, y si no la tiene se le da, que de lo verdaderamente importante ya nos ocuparemos cuando corresponda.

Para que no falte asesoramiento y guía en estos procedimientos, siempre están prestos los primeros interesados y beneficiarios. Están en su derecho y es su negocio. ¿Cuál es el tuyo como padre o madre?.

Postdata 1Para que no quede la menor duda: me encantaría descubrir que estoy totalmente equivocado.
Postdata 2: Nada de lo anterior debe prejuzgar mi opinión sobre las calificaciones (y menos aun las negativas) y sobre la "repetición de curso". Me reservo el derecho a tratar sobre estos temas cuando lo considere oportuno.
Postdata 3. Esta entrada de "opinión" deberá tener continuidad en otra de análisis y sería conveniente que hubiera una tercera de propuestas. Espero que sea posible, si dispongo de tiempo y y datos... aunque obligación ninguna.

jueves, 26 de octubre de 2023

Python. Aplicación.

Documentos específicos mediante Python

Python nos ofrece también la posibilidad de crear mediante script documentos genuinamente específicos de servicios ofimáticos. Esto es posible mediante el uso de bibliotecas de módulos o paquetes de funciones que previamente deben ser instalados e importados. Me refiero concretamente a la creación desde script Python de documentos Word, Excel o Acrobat. Los dos primeros son accesibles desde Libre Office gracias a la compatibilidad que esta suite mantiene con MSO, por lo que crear un documento Word o Excel es equivalente a crear un documento accesible desde LO-Writer y LO-Calc respectivamente. Y lo es en sentido pleno: LO puede trabajar con esos documentos como si fueran propios.


Así que mantengo como icono de esta entrada el mismo que en las anteriores referidas al uso de Python como herramienta para el trabajo con recursos ofimáticos, aunque en este caso una representación más adecuada del planteamiento de trabajo sería la siguiente:


Ésta no es una representación totalmente satisfactoria del modo 1A2, ya que no lo es al completo, al faltar formatos como .pdf, pero también otros que no explicité en el esquema inicial (como .cvs, por ejemplo), ni lo es en sentido estricto, ya que en esta entrada me voy a limitar a exponer cómo desarrollar la rama superior de esta representación (documento de texto), dejando para una posterior entrada el trabajo sobre  la rama inferior (hoja de cálculo) Esta división, que facilita la coherencia con otra documentación (1), está justificada por la complejidad de la temática que aborda, que exige realizar cuanto menos un primer acercamiento a temas como el uso de bibliotecas externar en Python, incluyendo su instalación y uso dentro de los script a crear. También parece una exigencia lógica que deriva de la complejidad de la propia biblioteca que facilita a Python  el trabajo con documentos Word.

En efecto, para desarrollar esta línea de trabajo (1A2) es necesario, en primer lugar, entender que Python, tal y como se instala en origen ofrece nada más que la punta de un iceberg de posibilidades, siendo posible (y necesario) implementar bibliotecas, paquetes de funciones o módulos, nuevas clases... (a gusto del consumidor) para desarrollar procesos específicos de trabajo, como es el caso de la creación de soportes ofimáticos (en este caso documentos MSO-Word).

Este proceso tiene cierta complejidad, aunque esta suficientemente simplificado gracias a los recursos disponibles en Python. A mí me ha servido parta entenderlo, además de la lectura de documentación, la explicación que proporciona Errodinger en este vídeo. Considero que es una buena síntesis de las opciones disponibles y de cómo proceder. No es el único recurso disponible, pero sirve para empezar.



En síntesis, la opción básica de instalación es el comando pip install NombreLibreria aplicado desde el cmd, tal y como te muestro en este vídeo que grabé mientras instalaba la librería para trabajar con documentos .docx. Para su visualización recomiendo la opción Pantalla completa


La instrucción completa es pip install python-docx, a escribir tras la cadena que genera Símbolo del sistema (consola o cmd) C:\Users\NombreUsiario>

Una vez instalada la librería python-docx, existen dos formas de saber si forma parte de las librerías instaladas, podemos utilizar indistintamente pip freeze o pip list (ambas desde Símbolo de sistema,cmd o consola) que listan todas las librerías, paquetes (de módulos) o clases instaladas y su versión (2)

Además, y ahora desde el IDE, podemos comprobar si un paquete está correctamente instalado (esto es, si funciona) utilizando la instrucción import NombreLibreria: si funciona correctamente no obtendremos ninguna respuesta (el intérprete queda a la espera), pero si no funciona obtendremos un mensaje de error. Por ejemplo, import doc devuelve...

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import doc
ModuleNotFoundError: No module named 'doc'

        Otra instrucción que nos interesa conocer, también a aplicar desde IDE, es dir(NombreLibreria), que nos devuelve el conjunto de funciones o métodos de que dispone la librería en cuestión. Por ejemplo, dir(docx) devuelve...

        ['Document', 'ImagePart', 'RT', 'TYPE_CHECKING', 'Type', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', 'annotations', 'api', 'blkcntnr', 'dml', 'document', 'drawing', 'enum', 'exceptions', 'image', 'opc', 'oxml', 'package', 'parts', 'section', 'settings', 'shape', 'shared', 'styles', 'table', 'text', 'types']

        Saber cuáles son los componentes de la librería es útil como síntesis, pero no  es suficiente cuanto estamos iniciando el aprendizaje del funcionamiento de un paquete, así es conveniente disponer de información más detallada, sobre componentes, funcionamiento y ejemplos. Para ello es recomendable consultar los siguientes enlaces (3):

        Pasemos ahora a la crear un documento Word. Únicamente es una ejemplificación de esta opción para constatar su funcionalidad tal y como se representa en este esquema del modo externo (modo 1)


        El script ha sido creado desde el IDE estándar de Python y modificado desde bloc de notas. Con esto quiero significar que, al menos para elaborar recursos básicos no es necesario trabajar con IDE complejos ni especializados. Este es el script...

        from docx import Document #-> Acceso a la librería docx para importar el método Document

        document = Document() # -> Creamos un documento mediante la función Document()

         # Escritura del encabezado del documento mediante la función add_heading()

        document.add_heading('Escritura de texto en formato Word. Modo 1A2')

         # Siguen a continuación tres modos de escribir contenido (párrafos)

        paragraph = document.add_paragraph('Primer párrafo: Texto escrito directamente mediante asignación de contenido a variable.')

        p = document.add_paragraph('Segundo párrafo: Texto plano seguido de texto en ')
        p.add_run('negrita').bold = True
        p.add_run(' y texto en ')
        p.add_run('itálica.').italic = True

        texto_parrafo3=input("Escribe el tercer párrafo")
        paragraph = document.add_paragraph(texto_parrafo3)

         # Finalizamos  guardando el documento creado mediante la función save()

        document.save('textopruebaword.docx')

        ... y este el resultado (captura de pantalla del documento Word). Te recomiendo que descargues el script Python, analices y repliques el proceso. Aunque no es obligatorio, te sugiero que guardes el script en la unidad D:
         

        Con lo anterior he desarrollado el proceso representado en el esquema precedente hasta el punto en que se crea un documento Word. Aquí puede finalizar el proceso, pero también podemos continuarlo accediendo al documento desde LO-Writer.


        Efectivamentea diferencia de los modos 1A1 y 2B, en 1A2 el uso de LibreOffice no es necesario salvo como recurso para visualizar el contenido del documento y como alternativa a MSO-Word, dada la posibilidad que ofrece LO por su compatibilidad con las extensiones MSO. 

        También es posible implementar macros OOo Basic, pero a diferencia del modo 1A1, considero que esta opción sólo se debe contemplar de forma excepcional, ya que deberíamos ser capaces de generar un documento final mediante Python.

        NOTA 1. De este modo la estructura de contenidos de estas entradas se asimila a la que planteo en OBpO, blog en el que diferencio estrategias de trabajo OOo Basic para crear documentos de texto de las propias para el trabajo con fuentes de datos. Además facilita también que se mantenga cierta coherencia con los vídeos YouTu.be de la lista de reproducción Python para orientadores.

        NOTA 2. Eso en Windows; para Linux y Mac ver enlace

        NOTA 3. Conforme vayamos incorporando otras bibliotecas iré ampliando el listado de enlaces a la documentación de las mismas.

        martes, 24 de octubre de 2023

        Python. Aplicación.

         Python desde dentro de Libre Office

        No hace mucho descubrí un vídeo en Youtu.Be en el que se explicaba que Excel había incorporado Python como lenguaje de macros. Creí que se trataba de un vídeo de una (¿nueva?) biblioteca que permitía generar documentos Excel desde Python, pero no: se trataba del uso de Python como lenguaje "interno" para crear funciones. Este video data del 30 de agosto de 2023 y hace referencia a una nueva funcionalidad de Excel, así que es novedad. ¡Qué cosas! LibreOffice dispone de esta misma funcionalidad, para todos sus servicios desde que tengo memoria de haberlo utilizado, y de eso ya van unos cuantos años...

        No quiero decir con esto que la implementación de Python en Excel funcione exactamente igual que como funciona en LibreOffice, ya que, al parecer el objetivo es mucho más concreto y posiblemente el resultado sea también más funcional, pero resulta cuanto menos curioso que MSO-Excel "copie" una funcionalidad disponible en LibreOffice (genérico), disponiendo como se dispone de librerías específicas que permiten a Python trabajar con y para Excel (también para Word, como hemos identificado en el modo 1A2 en nuestro esquema. Algo tiende de específico y especial  este modo que en ese mismo esquema denominé Modo interno 2B.


        Si por algo se caracteriza este modo es precisamente por su similitud con las formas de uso de OOo Basic, sin duda el lenguaje de "macros" preferente de LO (igual de lo es VBA para MSO), así que Python se presente como alternativa a VBA desde Excel viene a corroborar lo que Maurico Baeza ya planteó hace tiempo respecto a LO: la utilidad de Python para extender las funcionalidades de LO, derivada de la versatilidad y potencia del lenguaje.

        Esto no implica que OOoBasic pase a ser obsoleto, ya que, hoy por hoy sigue presentando (a mi entender) varias ventajas respecto a Python, por lo que (opino (1)) es conveniente seguir aprendiendo y trabajando con OOo Basic en sus dos formas (2): a partir de Grabar macro y directamente desde el IDE creando script.
        • De facilidad de aprendizaje.
        • De facilidad de generación, incluyendo la funcionalidad Grabar macro, no disponible para Python.
        • Y la facilidad de aplicación o uso de las macros o script, que se concreta en una mayor capacidad de integración en los servicios LO.
        Parece ser que la posibilidad de utilizar Python desde (dentro de ) LibreOffice no hay que darla por echa, siendo necesario comprobar que es posible mediante un sencillo procedimiento que consiste en lanzar una "macro" desde un documento Writer (yo hablaré de script) de comprobación (3):
        • Desde Herramientas/Macros/Ejecutar macro->
        • Selector de macros -> Biblioteca "Mis Macros" ->
        • Carpeta "HolaMundo-> script HelloWorldPython-> Ejecutar
        Si se escribe en el documento el texto "Hello World (in Python) es que tienes Python disponible como lenguaje de "macros". En caso contrario deberás realizar los cambios pertinentes en la configuración de LibreOffice, pero si trabajas desde Windows es poco probable que no esté ya correctamente configurado.

        Superada la primera dificultad  toca ahora afrontar la segunda: si estás acostumbrado a trabajar con OOoBasic te sorprenderán las dificultades para para gestionar los script Python, ya que sólo es posible ejecutar los que están disponibles desde Mis Macros o desde Macros de la aplicación, pero no parece posible crear y grabar script propios en ninguna de las tres ubicaciones conocidas (añadiendo a las dos anteriores el propio documento).

        Existen modos de sortear estas dificultades (4), pero por el momento me voy a limitar a explicar una solución sencilla, aunque no ideal: sigue esta ruta para acceder y grabar los script de Python...

        C:\Users\NombreUsuario\AppData\Roaming\LibreOffice\4\user\scripts\python (5)

        ... que estarán después accesibles desde Mis Macros. Este directorio es accesible desde Herramientas/Macros/Ejecutar macro o desde Herramientas/Macros/Organizar macros/Python, que son también las formas más simples de ejecutar un script.

        Bien, ya sabemos cómo activar un script Python desde LO-Writer (por ejemplo) y cómo guardar los que creemos nosotros, pero aun  nos queda aprender a crearlos.

        En efecto, sabemos que podemos crearlos desde el IDE de Python, y que podemos guardarlos en la ubicación que indica la dirección antes mostrada, incluso visualizarlos desde un documento (por ejemplo, desde Writer), pero no será reconocido sin más por LO como archivo válido si no cumple determinadas condiciones. Esto es lo que ocurre con el script que creamos para trabajar el modo 1A1...

        print("¿Cómo te llamas?")
        nombre=input()
        print(f"Me alegro de conocerte,{nombre}")

        ... que podemos guardar y visualizar, pero al que no podemos acceder desde Writer -> (...) Ejecutar/Organizar macro.

        Vamos a ver cuáles son esas condiciones que hacen posible el funcionamiento de un script Python llamado desde un servicio LO; y para ello nada mejor que explorar un ejemplo de script Python ubicado en ese subdirectorio, ya que sabemos que funciona, por ejemplo, mismamente HelloWorldPython.

        Si abrimos este archivo desde Bloc de notas (por simplificar), obtenemos un documento cargado de líneas comentadas (#) que por el momento podemos obviar, así que el script, sin comentarios, queda como sigue:

        def HelloWorldPython():

            desktop = XSCRIPTCONTEXT.getDesktop()
            model = desktop.getCurrentComponent()

            if not hasattr(model, "Text"):
                model = desktop.loadComponentFromURL(
                    "private:factory/swriter", "_blank", 0, ())

            text = model.Text
            tRange = text.End
            tRange.String = "Hello World (in Python)"
            return None

        Por comprobar que todo funciona correctamente, podemos probar a guardar este archivo libre de comentarios con un nombre alternativo al original (HelloWorldBis.py) y comprobar sí funciona llamándolo desde Writer (Herramientas/Macros/Organizar macros/Python). Como es de esperar el resultado es positivo: se escribe en el documento la esperada frase Hello World (in Python).

        Ya tenemos, pues, un script que no es reconocido y otro que sí y podemos ver que se diferencian en que en el segundo se utilizan instrucciones específicas, que sabemos forman parte de las propias de una librería especialmente diseñada en LO para hacer posible el uso de Python llamada PyUNO.
        • desktop.getCurrentComponent()
        • desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, ())
        Algunas de ellas no te resultarán extrañas, dada su similitud con las empleadas en OOoBasic. Otras son específicas de PyUNO:
        • XSCRIPTCONTEXT.getDesktop()
        He ahí una cuestión importante: si podemos utilizar Python desde LO es porque desde Python empleamos una librería específica, imprescindible que poder hacerlo. Esto es similar a lo que hacemos desde el modo 1A2 para crear documentos word o excel, como señalo en otra entrada (6)

        Para finalizar esta entrada, y aunque queda mucho por aclarar, paso a exponer el código de un script elaborado por mí a partir del código de los que se presentan como ejemplo. Incluye líneas de comentario (en rojo) para facilitar su comprensión.

        def texto_en_python():
            #Imprime un texto en un documento Writer situando el cursor al final del mismo.
            saludador = "Javier"
            texto_saludo = f"Saludos cordiales de parte de {saludador}, desde Asturias.\n"
          texto_contenido = f"Este escrito realizado por {saludador} es parte de un proyecto de aprendizaje del uso de python en LO\n"
           texto_explica = f"En este caso se trata de generar información textual en soporte writer desde cualquier servicio de LO"
            texto = texto_saludo + texto_contenido + texto_explica
        #Llamada a la aplicación de texto de Libre Office
            desktop = XSCRIPTCONTEXT.getDesktop()
            model = desktop.getCurrentComponent()
        #Entra en acción si la aplicación activa no es Writer
        #En ese caso deriva a la creación de un nuevo documento writer
            if not hasattr(model, "Text"):
                model = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, ())
            text = model.Text       #Llama a la subclase Text del componente actualmente activo
            tRange = text.End       #Ubica el puntero al final del documento
        #Y escribe el contenido de la variable (podría escribir directamente un string)
            tRange.String = texto

        Libre Office cuenta con otros ejemplos de código Python que son de interés para comprender las posibilidades del uso "interno" este lenguaje en la creación de script, así que en futuras entradas profundizaremos en la comprensión de estos ejemplo como paso previo para la creación de código propio. Pero por ahora es suficiente.

        NOTA 1. Propongo que al menos hasta alcanzar un nivel de competencia asimilable al que podemos haber adquirido en OOoBasic, que se manifieste en ser capaces de generar soluciones basadas en Python similares a los docap creados mediante OOoBasic. Es un límite asequible y fácilmente comprobable, por lo que no supone una generalidad inconcreta.

        NOTA 2Eso que en el esquema  se denomina modo interno 2A

        NOTA 3. Creo que se explica en el vídeo de Mauricio Baeza que enlacé antes.

        NOTA 4Incluyendo la instalación de extensiones que se pretenden simplificadoras de todas estas limitaciones (como la extensión APSO), pero son estos temas suficientemente complejos como para que lo más prudente en estos momentos iniciales los dejemos aparcados. Tiempo habrá de tratarlo más adelante.

        NOTA 5Users puede aparecerte directamente como Usuarios y debes sustituir NombreUsuario por tu verdadero nombre de usuario. Además es posible que cuando llegues a este punto no encuentres visible la carpeta AppData (no confundir con la nombrada como Application Data); esto es debido a que está oculta. En ese caso vas al menú Vista y activas la casilla  Elementos ocultos. A partir de ahí puedes seguir la ruta indicada tanto para acceder a los script ya creados como para copiar los que tu crees, en principio desde el IDE que proporciona Python por defecto, desde el mismo bloc de notas o desde cualquier programa de edición de código (Thonny, por ejemplo, por empezar por uno sencillo).

        NOTA 6. Ese modo de trabajo externo no ha sido explicado aun, dado que en este momento he priorizado la simplicidad a la secuencia de la categorización del esquema. Para mayor conocimiento de estos recursos acceder a la documentación de Foundation Wiki y la ayuda de LibreOffice y los enlaces a otros documentos que contienen estas dos referencias

        OOo Basic. Script

         Subrutinas creadas a partir de macros

        Después de la introducción general al tema realizada en una [entrada anterior], disponemos ya de argumentos para tratar con más detalle esta cuestión: cómo transformar una macro simple en una subrutina.




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


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

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

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

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

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

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

        Sub msbIndiceNumerico(bOpcion As Boolean)

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

        args2(0).Value = bOpcion

        El resultado...

        Sub msbIndiceNumerico(bOpcion As Boolean)

        dim args1(0) as new com.sun.star.beans.PropertyValue
        	 args1(0).Name = "On"
        args1(0).Value = bOpcion

        dispatcher.executeDispatch(document, ".uno:DefaultNumbering", "", 0, args1()) 

        End Sub

        ... es una subrutina que puede ser llamada (2) desde una macro o script principal como alternativa a la llamada opcional a dos macros simples: la de aplicación y la de retirada del índice numérico (3).

        Una variación del modelo anterior es la que incluye el uso de un bucle en el script desde el que se llama a la subrutina, generando así una secuencia de desarrollo o aplicación de la subrutina. Por ejemplo, podemos avanzar letra por letra (incluyendo los espacios en blanco) seleccionando o no los elementos que se recorren. [Esta subrutina es un ejemplo de ello].

        También podemos utilizar este bucle dentro de la subrutina, afectando únicamente a los instrucciones de ejecución (dispatcher), [como en este ejemplo].

        sub msbAvanPag(iNumPag As Integer)

        Dim i As Integer
        For i=0 To iNumPag
        dispatcher.executeDispatch(document, ".uno:PageDown", "", 0, Array())
        Next

        end sub

        La tercera forma de crear una subrutina a partir de una macro simple ya vulnera el criterio de macro simple, al menos en alguna de sus formulaciones, pero también puede ser una solución cuando el uso de dos parejas de macros simples sea requerido con cierta frecuencia.

        Considero "parejas de macros simples" cuando éstas son complementarias una de la otra, como en el caso que sigue:

        sub mcrBajarLinea

        dim args1(1) as new com.sun.star.beans.PropertyValue
        args1(0).Name = "Count"
        args1(0).Value = 1
        args1(1).Name = "Select"
        args1(1).Value = false
        dispatcher.executeDispatch(document, ".uno:GoDown", "", 0, args1())

        End Sub

        Sub mcrSubirLinea

        dim args1(1) as new com.sun.star.beans.PropertyValue
        args1(0).Name = "Count"
        args1(0).Value = 1
        args1(1).Name = "Select"
        args1(1).Value = false
        dispatcher.executeDispatch(document, ".uno:GoUp", "", 0, args1())

        End Sub

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

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

        sub msbLinea(bSelect As Boolean,sMov As String)

        dim args1(1) as new com.sun.star.beans.PropertyValue
        args1(0).Name = "Count"
        args1(0).Value = 1
        args1(1).Name = "Select"
        args1(1).Value = bSelect
        If sMov = "B" Then
        dispatcher.executeDispatch(document, ".uno:GoDown", "", 0, args1())
        MsgBox "He bajado una linea"
        ElseIf sMov = "S" Then
        dispatcher.executeDispatch(document, ".uno:GoUp", "", 0, args1())
        MsgBox "He subido una línea"
        Else
        MsgBox "El valor de la variable 'sLinea' no es correcto" 
        End If

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

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

        sub msbLinea(bSelect As Boolean,sMov As String)

        dim args1(1) as new com.sun.star.beans.PropertyValue
        args1(0).Name = "Count"
        args1(0).Value = 1
        args1(1).Name = "Select"
        args1(1).Value = bSelect
        dispatcher.executeDispatch(document, sMov, "", 0, args1())

        End Sub

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

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

        NOTAS

        (1) Existen muchas otras macros simples que presentan esta estructura y que pueden ser convertidas en subrutinas siguiendo este mismo procedimiento. Una de ellas, y en la que su conversión en subrutina es especialmente recomendable, es la macro de escritura (también podemos hacer lo mismo con el script OOo Basic alternativo a la macro). Si ahora propongo esta macro de posicionamiento es precisamente para evitar utilizar siempre el mismo ejemplo, aunque posiblemente sea éste un ejemplo no tan explícito como al que sustituye.

        (2) Recuerdo los dos modos de usar la subrutina desde la macro principal:

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

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

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