<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.openoffice.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mauriciobaeza</id>
	<title>Apache OpenOffice Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.openoffice.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mauriciobaeza"/>
	<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/wiki/Special:Contributions/Mauriciobaeza"/>
	<updated>2026-06-29T22:52:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.14</generator>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Talk:ES/Documentation&amp;diff=227837</id>
		<title>Talk:ES/Documentation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Talk:ES/Documentation&amp;diff=227837"/>
		<updated>2013-06-11T16:10:29Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Discusión o silencio */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Información desactualizada y duplicidad de caminos ==&lt;br /&gt;
Esta página tiene enlaces a páginas en inglés que ya disponen de su equivalente en español.&lt;br /&gt;
Considero que debería existir una sóla página desde la cual surja toda la documentación de la wiki en español, y que esa página debería ser [[ES]]&lt;br /&gt;
Por ello sugiero:&lt;br /&gt;
&lt;br /&gt;
* Agregar en la página [[ES]] aquellos enlaces que sí tiene esta página y que todavía no existe equivalente en español&lt;br /&gt;
* Sustituir su contenido por una redirección a [[ES]] con un comando&lt;br /&gt;
:: &amp;lt;nowiki&amp;gt;#REDIRECT [[ES]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Plantilla ==&lt;br /&gt;
Por otra parte opino que sería bueno crear una plantilla con este contenido...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;border: 1px solid rgb(140, 45, 6); margin: 0px 5px 5px; padding: 1px; float: right; width: 300px; &lt;br /&gt;
  background-color: rgb(255, 255, 255);&amp;quot; id=&amp;quot;contrib&amp;quot;&amp;gt;&amp;lt;div style=&amp;quot;padding: 2px; background-color: rgb(140, 45, 6); &lt;br /&gt;
  color: rgb(255, 255, 255); font-weight: bold; text-align: center;&amp;quot;&amp;gt;Quieres ayudar?&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
*[[ES/Participar|Cómo participar]] &lt;br /&gt;
*[[ES/AyudaWiki|Cómo contribuir]] &lt;br /&gt;
*[[ES/AyudaWiki|Politicas de edición]] &lt;br /&gt;
*[[ES/PanelDelProyecto|Panel del proyecto]]&lt;br /&gt;
| &lt;br /&gt;
*[[Documentation/Wishlist|Lista de Deso]] &amp;lt;--------------- No sé muy bien qué es esto&lt;br /&gt;
*[[:Category:ES/AyudaWiki/Ayuda|Página que necesitan ayuda!]] &lt;br /&gt;
*[[:Category:ES/AyudaWiki/Pendientes|Páginas pendientes]]&lt;br /&gt;
*[[:Category:ES/AyudaWiki/Candidatas|Páginas candidatas]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...con los enlaces correctos a las páginas actuales en español.&lt;br /&gt;
Esta plantilla:&lt;br /&gt;
* podría ser agregada a todas las páginas en español que incluirían en su encabezado una plantilla general en la que se podría enlazar fácilmente cualquier mensaje que se quiera transmitir sin realizar más que unos simples cambios, por ejemplo  &amp;lt;nowiki&amp;gt;{{EncabezadoES}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* se crearán las plantillas/categorías (si no existen ya) para enlazar a las páginas que necesitan ayuda, páginas pendientes, páginas candidatas.&lt;br /&gt;
* Veo acertado incluir también un panel del proyecto donde para cada apartado pueda indicarse quienes han sido los colaboradores que han ayudado a realizarlo, o a quienes se les ha asignado-encargado su realización o mantenimiento.&lt;br /&gt;
&lt;br /&gt;
== Discusión o silencio ==&lt;br /&gt;
Entenderé que si tras &amp;lt;del&amp;gt;15 días&amp;lt;/del&amp;gt; 72 horas a partir de la fecha de esta discusión nadie comenta nada, se sobreentiende que es aceptado el cambio por la comunidad.&lt;br /&gt;
Saludos&lt;br /&gt;
&lt;br /&gt;
--[[User:Salva|Salva]] ([[User talk:Salva|talk]]) 10:56, 11 June 2013 (UTC)&lt;br /&gt;
&lt;br /&gt;
Totalmente de acuerdo&lt;br /&gt;
--[[User:mauriciobaeza|mauriciobaeza]] ([[User talk:mauriciobaeza|talk]]) 11:08, 11 June 2013 (UTC)&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Talk:ES/Documentation&amp;diff=227836</id>
		<title>Talk:ES/Documentation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Talk:ES/Documentation&amp;diff=227836"/>
		<updated>2013-06-11T16:09:39Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Discusión o silencio */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Información desactualizada y duplicidad de caminos ==&lt;br /&gt;
Esta página tiene enlaces a páginas en inglés que ya disponen de su equivalente en español.&lt;br /&gt;
Considero que debería existir una sóla página desde la cual surja toda la documentación de la wiki en español, y que esa página debería ser [[ES]]&lt;br /&gt;
Por ello sugiero:&lt;br /&gt;
&lt;br /&gt;
* Agregar en la página [[ES]] aquellos enlaces que sí tiene esta página y que todavía no existe equivalente en español&lt;br /&gt;
* Sustituir su contenido por una redirección a [[ES]] con un comando&lt;br /&gt;
:: &amp;lt;nowiki&amp;gt;#REDIRECT [[ES]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Plantilla ==&lt;br /&gt;
Por otra parte opino que sería bueno crear una plantilla con este contenido...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;border: 1px solid rgb(140, 45, 6); margin: 0px 5px 5px; padding: 1px; float: right; width: 300px; &lt;br /&gt;
  background-color: rgb(255, 255, 255);&amp;quot; id=&amp;quot;contrib&amp;quot;&amp;gt;&amp;lt;div style=&amp;quot;padding: 2px; background-color: rgb(140, 45, 6); &lt;br /&gt;
  color: rgb(255, 255, 255); font-weight: bold; text-align: center;&amp;quot;&amp;gt;Quieres ayudar?&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
*[[ES/Participar|Cómo participar]] &lt;br /&gt;
*[[ES/AyudaWiki|Cómo contribuir]] &lt;br /&gt;
*[[ES/AyudaWiki|Politicas de edición]] &lt;br /&gt;
*[[ES/PanelDelProyecto|Panel del proyecto]]&lt;br /&gt;
| &lt;br /&gt;
*[[Documentation/Wishlist|Lista de Deso]] &amp;lt;--------------- No sé muy bien qué es esto&lt;br /&gt;
*[[:Category:ES/AyudaWiki/Ayuda|Página que necesitan ayuda!]] &lt;br /&gt;
*[[:Category:ES/AyudaWiki/Pendientes|Páginas pendientes]]&lt;br /&gt;
*[[:Category:ES/AyudaWiki/Candidatas|Páginas candidatas]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...con los enlaces correctos a las páginas actuales en español.&lt;br /&gt;
Esta plantilla:&lt;br /&gt;
* podría ser agregada a todas las páginas en español que incluirían en su encabezado una plantilla general en la que se podría enlazar fácilmente cualquier mensaje que se quiera transmitir sin realizar más que unos simples cambios, por ejemplo  &amp;lt;nowiki&amp;gt;{{EncabezadoES}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* se crearán las plantillas/categorías (si no existen ya) para enlazar a las páginas que necesitan ayuda, páginas pendientes, páginas candidatas.&lt;br /&gt;
* Veo acertado incluir también un panel del proyecto donde para cada apartado pueda indicarse quienes han sido los colaboradores que han ayudado a realizarlo, o a quienes se les ha asignado-encargado su realización o mantenimiento.&lt;br /&gt;
&lt;br /&gt;
== Discusión o silencio ==&lt;br /&gt;
Entenderé que si tras &amp;lt;del&amp;gt;15 días&amp;lt;/del&amp;gt; 72 horas a partir de la fecha de esta discusión nadie comenta nada, se sobreentiende que es aceptado el cambio por la comunidad.&lt;br /&gt;
Saludos&lt;br /&gt;
&lt;br /&gt;
--[[User:Salva|Salva]] ([[User talk:Salva|talk]]) 10:56, 11 June 2013 (UTC)&lt;br /&gt;
&lt;br /&gt;
Totalmente de acuerdo&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos&amp;diff=222960</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos&amp;diff=222960"/>
		<updated>2013-05-24T04:29:58Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Referencia a varios rangos de celdas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE: Referencia a rangos}}&lt;br /&gt;
&lt;br /&gt;
Seguro que sabes, si eres usuario habitual de una hoja de calculo, que el trabajo con rangos es esencial en estos documentos, por lo mismo, el trabajo con rangos desde código es igualmente importante, ya vimos como aseguramos que estamos trabajando en una hoja de calculo, así que dejo a tu criterio esta validación. En la siguientes secciones nos centraremos en aprender como hacer referencia a distintos tipos de rangos para después poder manipularlos, darles formato o hacer con ellos lo que queramos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a celdas individuales ==&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a las celdas de una hoja de calculo de varias maneras, principalmente por su nombre o por su posición, pero muy importante, primero tienes que acceder a la hoja donde están las celdas que te interesa manipular, como acceder a hojas es un tema que ya hemos tratado, pero en cada ejemplo podrás notar que repasamos estos conocimientos, la forma más simple de hacer referencia a una celda es por su nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    # Referencia a la celda E5&lt;br /&gt;
    celda = activa.getCellRangeByName(&amp;#039;E5&amp;#039;)&lt;br /&gt;
    # Mostramos el contenido de la celda&lt;br /&gt;
    msgbox (celda.getString())&lt;br /&gt;
    # Mostramos direccion de esta celda&lt;br /&gt;
    ca = celda.getCellAddress()&lt;br /&gt;
    message = u&amp;#039;Columna: %s\nFila: %s\nHoja: %s&amp;#039; % (ca.Column, ca.Row, ca.Sheet)&lt;br /&gt;
    msgbox (message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como comprobamos en la ultima linea, que efectivamente hemos hecho referencia a la celda que nos interesa, es decir a la celda E5, que en columna y fila es la 4, por que recordamos que los números de columna y fila empiezan en 0, observa la estructura &amp;lt;idl&amp;gt;com.sun.star.table.CellAddress&amp;lt;/idl&amp;gt;, esta, es muy importante pues a muchos métodos para manipular celdas, se les tienen que pasar estructuras como esta, solo tiene tres propiedades, la hoja (valor tipo &amp;#039;&amp;#039;&amp;#039;integer&amp;#039;&amp;#039;&amp;#039; que también empieza en 0) donde esta la celda referenciada, la columna (&amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;) y la fila (&amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;) de esta celda.&lt;br /&gt;
&lt;br /&gt;
Ahora accedemos a una celda por su posición, recuerda que los índices de inicio desde código empiezan en 0, por lo que para hacer referencia a la celda E5, tenemos que poner la columna 4 y fila 4, el primer valor es para la columna y el segundo para la fila, no esta de más comentarte que tengas cuidado de no establecer una posición fuera de la hoja, pues te dará un error, si el valor de la fila y columna se la solicitas al usuario, “deberías” de validar que los valores proporcionados son correctos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    &lt;br /&gt;
    col = 9&lt;br /&gt;
    fil = 14&lt;br /&gt;
    if col &amp;lt; activa.getColumns().getCount() and fil &amp;lt; activa.getRows().getCount():&lt;br /&gt;
        celda = activa.getCellByPosition(col, fil)&lt;br /&gt;
        msgbox (celda.getString())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Valores incorrectos&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es frecuente que el acceso por nombre a una celda se use para establecer valores preestablecidos, como títulos de campos por ejemplo, y el acceso por posición es muy útil para realizar ciclos, como el ejemplo siguiente que inserta el año como titulo en la celda A1 y los meses del año de la celda A2 a la A13.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import datetime&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
        &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa.getCellRangeByName(&amp;#039;A1&amp;#039;).setString(datetime.date.today().year)&lt;br /&gt;
    for i in range(1,13):&lt;br /&gt;
        activa.getCellByPosition(0, i).setString(datetime.date(2013, i, 1).strftime(&amp;#039;%B&amp;#039;))&lt;br /&gt;
&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que hemos estado usando el método &amp;#039;&amp;#039;&amp;#039;getString()&amp;#039;&amp;#039;&amp;#039; para obtener el contenido de una celda y &amp;#039;&amp;#039;&amp;#039;setString(cadena)&amp;#039;&amp;#039;&amp;#039; para establecerlo, más adelante veremos todas las posibilidades que tenemos para introducir u obtener datos de las celdas de nuestra hoja de calculo, así como sus diferencias.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a un rango de celdas ==&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a un rango de celdas por su nombre, usando el mismo método usado para acceder a una celda.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;A1:E5&amp;#039;)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para acceder a un rango de celdas por su posición, hay que usar un método diferente: &amp;#039;&amp;#039;&amp;#039;getCellRangeByPosition&amp;#039;&amp;#039;&amp;#039;, que requiere de cuatro argumentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    # Seleccionamos el rango B1:C10&lt;br /&gt;
    rango = activa.getCellRangeByPosition(1, 0, 2, 9)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que este nuevo método requiere cuatro argumentos: la columna y fila donde empieza nuestro rango y la columna y fila donde termina, recuerda que los números de fila y columna empiezan en 0, algunos piensan que los dos últimos argumentos son el ancho y alto del rango a usar, no es así, estos argumentos también son números de índices de columna y fila respectivamente y tienes que tener la precaución de establecer los segundos iguales o mas grandes que los primeros, sino, te dará un error en tiempo de ejecución y por supuesto sin sobrepasar el máximo de filas y columnas de la hoja de calculo. Observa también, como en la ultima línea seleccionamos el rango referenciado.&lt;br /&gt;
&lt;br /&gt;
Otra posibilidad, es usar nombres definidos de rangos, es decir, aquellos que establecemos desde el &amp;#039;&amp;#039;&amp;#039;Cuadro de nombre&amp;#039;&amp;#039;&amp;#039; en la hoja de calculo, ya sabes, ese cuadro de lista desplegable (combobox) que esta al lado de la barra de formulas, que también puedes establecer desde el menú &amp;#039;&amp;#039;&amp;#039;&amp;#039;Insertar | Nombres | Definir...&amp;#039;&amp;#039;&amp;#039;&amp;#039; cuya teclas de acceso rápido son {{Key|Ctrl|F3}}. En el siguiente ejemplo, seleccionamos el rango de celdas llamado Datos. Toma nota de que si el rango no existe en la hoja desde donde se intenta referenciar, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;Datos&amp;#039;)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Este método no es sensible a mayúsculas o minúsculas. Observa como primero obtenemos una referencia a la interfaz &amp;lt;idl&amp;gt;com.sun.star.sheet.XNamedRanges&amp;lt;/idl&amp;gt; y dado que esta hereda la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XNameAccess&amp;lt;/idl&amp;gt; podemos usar el método &amp;#039;&amp;#039;&amp;#039;getElementNames&amp;#039;&amp;#039;&amp;#039; para obtener todos los nombres con rango en el documento. Si el usuario es el que proporciona el nombre del rango, como siempre, es mejor validar que el rango exista.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nr = doc.NamedRanges&lt;br /&gt;
    nombre = &amp;#039;Datos&amp;#039;&lt;br /&gt;
    nombres_rangos = nr.getElementNames()&lt;br /&gt;
    &lt;br /&gt;
    if nombre in nombres_rangos:&lt;br /&gt;
        rango = nr.getByName(nombre).getReferredCells()&lt;br /&gt;
        doc.getCurrentController().select(rango)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe el rango: %S&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No confundas estos nombres de rangos, con los que puedes establecer en el menú &amp;#039;&amp;#039;&amp;#039;Datos | Definir rango...&amp;#039;&amp;#039;&amp;#039;, ya que estos últimos se refieren a rangos considerados como una tabla de datos, de hecho, puedes tener un mismo nombre para un rango de celdas y para un rango de datos, pero son dos cosas diferentes, los segundos, los veremos más adelante.&lt;br /&gt;
&lt;br /&gt;
De los rangos de celdas, también es posible obtener información, para ello se hace uso de la estructura &amp;lt;idl&amp;gt;com.sun.star.table.CellRangeAddress&amp;lt;/idl&amp;gt; a través del método &amp;#039;&amp;#039;&amp;#039;getRangeAddress&amp;#039;&amp;#039;&amp;#039; que te devuelve información de: la hoja donde esta el rango, la columna y fila donde comienza y la columna y fila donde acaba.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;Datos&amp;#039;)&lt;br /&gt;
    ra = rango.getRangeAddress()&lt;br /&gt;
    &lt;br /&gt;
    message = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    El rango esta en la hoja: %s&lt;br /&gt;
    Columna inicio: %s&lt;br /&gt;
    Fila Inicio: %s&lt;br /&gt;
    Columna final: %s&lt;br /&gt;
    Fila final: %s&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; % (ra.Sheet, ra.StartColumn, ra.StartRow, ra.EndColumn, ra.EndRow)&lt;br /&gt;
    &lt;br /&gt;
    msgbox(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta estructura (&amp;#039;&amp;#039;&amp;#039;getRangeAddress&amp;#039;&amp;#039;&amp;#039;) también es usada por varios métodos para manipular rangos que veremos más adelante, por lo que es importante que la tengas presente.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a varios rangos de celdas ==&lt;br /&gt;
&lt;br /&gt;
Cuando en la interfaz del usuario, hacemos la selección de un rango y mantenemos presionada la tecla {{Key|Ctrl}} y hacemos un segunda selección de un rango y así sucesivamente, estamos hablando de un conjunto de rangos que tiene sus características particulares para su control y manejo. Para seleccionar varios rangos desde código, primero debemos crear el &amp;#039;&amp;#039;&amp;#039;contenedor&amp;#039;&amp;#039;&amp;#039; de estos rangos, veamos como.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    #~ Creamos el contender para los rangos&lt;br /&gt;
    rangos = doc.createInstance(&amp;#039;com.sun.star.sheet.SheetCellRanges&amp;#039;)&lt;br /&gt;
    #~ Creamos la estructura CellRangeAddress necesaria&lt;br /&gt;
    dir_rango = activa.getCellRangeByName(&amp;#039;A1:B2&amp;#039;).getRangeAddress()&lt;br /&gt;
    #~ Y lo agregamos al contenedor de rangos&lt;br /&gt;
    rangos.addRangeAddress(dir_rango, False)&lt;br /&gt;
    #~ Aquí solo hacemos referencia al rango&lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;E1:G2&amp;#039;)&lt;br /&gt;
    #~ Y lo agregamos al contenedor de rangos, nota como tenemos que usar&lt;br /&gt;
    #~ el método getRangeAddress para pasarle el argumento correcto&lt;br /&gt;
    rangos.addRangeAddress(rango.getRangeAddress(), False)&lt;br /&gt;
    #~ Aquí agregamos un rango directamente al contenedor&lt;br /&gt;
    #~ toma en cuenta que se van acumulando &lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;D4:E5&amp;#039;).getRangeAddress() , False)&lt;br /&gt;
&lt;br /&gt;
    #~ Comprobamos que están correctos seleccionándolos&lt;br /&gt;
    doc.getCurrentController().select(rangos)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No te confundas, las tres líneas donde se agrega el rango con el método &amp;#039;&amp;#039;&amp;#039;addRangeAddress()&amp;#039;&amp;#039;&amp;#039; son iguales, lo que cambia es la forma en que hacemos referencia a la dirección del rango, si vas empezando a programar, te recomiendo ir desglosando cada línea, con el tiempo y la experiencia, podrás concentrar código de forma más natural, por ahora, usa todas las líneas que consideres pertinentes para que tu código lo entiendas con solo verlo.&lt;br /&gt;
&lt;br /&gt;
Por supuesto, también de estos rangos podemos obtener información, por ejemplo, los nombres de los rangos que contiene,&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    #~ Creamos el contender para los rangos&lt;br /&gt;
    rangos = doc.createInstance(&amp;#039;com.sun.star.sheet.SheetCellRanges&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    #~ Agregamos los rangos que queramos&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;A1:A2&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;B4:B5&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;C7:C8&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;D10:D11&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;E13:E14&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
&lt;br /&gt;
    #~ Mostramos las direcciones de los rangos&lt;br /&gt;
    msgbox(rangos.getRangeAddressesAsString())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota como los rangos es una cadena larga de las direcciones de los rangos separados por un &amp;#039;&amp;#039;&amp;#039;;&amp;#039;&amp;#039;&amp;#039;, si lo quieres mejor presentable, reemplaza los puntos y comas por un salto de línea con el siguiente código.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    #~ Mostramos las direcciones de los rangos&lt;br /&gt;
    message = rangos.getRangeAddressesAsString().replace(&amp;#039;;&amp;#039;, &amp;#039;\n&amp;#039;)&lt;br /&gt;
    msgbox(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los rangos también se pueden remover de la colección.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    #~ Creamos el contender para los rangos&lt;br /&gt;
    rangos = doc.createInstance(&amp;#039;com.sun.star.sheet.SheetCellRanges&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    #~ Agregamos los rangos que queramos&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;A1:A2&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;B4:B5&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;C7:C8&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;D10:D11&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;E13:E14&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
&lt;br /&gt;
    #~ Comprobamos que estén los rangos&lt;br /&gt;
    msgbox(rangos.getRangeAddressesAsString().replace(&amp;#039;;&amp;#039;, &amp;#039;\n&amp;#039;))&lt;br /&gt;
    &lt;br /&gt;
    #~ Removemos el rango deseado&lt;br /&gt;
    rangos.removeRangeAddress(activa.getCellRangeByName(&amp;#039;D10:D11&amp;#039;).getRangeAddress())&lt;br /&gt;
&lt;br /&gt;
    #~ Volvemos a verificar que se haya removido  &lt;br /&gt;
    msgbox(rangos.getRangeAddressesAsString().replace(&amp;#039;;&amp;#039;, &amp;#039;\n&amp;#039;))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cuidado, si el rango que quieres remover no existe en la colección, te dará un error en tiempo de ejecución, lo mejor es validar antes que existe...&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # Validamos que el rango a remover exista en la colección&lt;br /&gt;
    if rangos.hasByName(&amp;#039;Hoja1.D10:D11&amp;#039;):&lt;br /&gt;
        rangos.removeRangeAddress(activa.getCellRangeByName(&amp;#039;D10:D11&amp;#039;).getRangeAddress())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El código anterior tiene un problema que tal vez te pueda causar un pequeño inconveniente, cuando consultamos con &amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039; si el rango existe, observa que le pasamos el nombre del rango como texto &amp;#039;&amp;#039;&amp;#039;(&amp;#039;Hoja1.D10:D11&amp;#039;)&amp;#039;&amp;#039;&amp;#039; y que incluye el nombre de la hoja donde esta el rango, pero observa como al método &amp;#039;&amp;#039;&amp;#039;removeRangeAddress&amp;#039;&amp;#039;&amp;#039;, le pasamos un objeto (&amp;#039;&amp;#039;&amp;#039;activa&amp;#039;&amp;#039;&amp;#039;) que no necesariamente tiene que corresponder con el nombre de hoja (&amp;#039;&amp;#039;&amp;#039;Hoja1&amp;#039;&amp;#039;&amp;#039;), siempre garantiza que se corresponde uno con el otro, es decir, que el objeto que apunta a la hoja, efectivamente corresponda en nombre con el rango pasado.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a filas y columnas ==&lt;br /&gt;
&lt;br /&gt;
Las filas y columnas de una hoja de calculo siguen siendo rangos de celdas, lo único que las caracteriza, en función de hacer referencia a ellas, es que abarcan la totalidad de celdas que contienen, como en.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]]&lt;br /&gt;
[[Category:Manuales]]&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos&amp;diff=221910</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos&amp;diff=221910"/>
		<updated>2013-05-22T03:58:13Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Referencia a varios rangos de celdas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE: Referencia a rangos}}&lt;br /&gt;
&lt;br /&gt;
Seguro que sabes, si eres usuario habitual de una hoja de calculo, que el trabajo con rangos es esencial en estos documentos, por lo mismo, el trabajo con rangos desde código es igualmente importante, ya vimos como aseguramos que estamos trabajando en una hoja de calculo, así que dejo a tu criterio esta validación. En la siguientes secciones nos centraremos en aprender como hacer referencia a distintos tipos de rangos para después poder manipularlos, darles formato o hacer con ellos lo que queramos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a celdas individuales ==&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a las celdas de una hoja de calculo de varias maneras, principalmente por su nombre o por su posición, pero muy importante, primero tienes que acceder a la hoja donde están las celdas que te interesa manipular, como acceder a hojas es un tema que ya hemos tratado, pero en cada ejemplo podrás notar que repasamos estos conocimientos, la forma más simple de hacer referencia a una celda es por su nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    # Referencia a la celda E5&lt;br /&gt;
    celda = activa.getCellRangeByName(&amp;#039;E5&amp;#039;)&lt;br /&gt;
    # Mostramos el contenido de la celda&lt;br /&gt;
    msgbox (celda.getString())&lt;br /&gt;
    # Mostramos direccion de esta celda&lt;br /&gt;
    ca = celda.getCellAddress()&lt;br /&gt;
    message = u&amp;#039;Columna: %s\nFila: %s\nHoja: %s&amp;#039; % (ca.Column, ca.Row, ca.Sheet)&lt;br /&gt;
    msgbox (message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como comprobamos en la ultima linea, que efectivamente hemos hecho referencia a la celda que nos interesa, es decir a la celda E5, que en columna y fila es la 4, por que recordamos que los números de columna y fila empiezan en 0, observa la estructura &amp;lt;idl&amp;gt;com.sun.star.table.CellAddress&amp;lt;/idl&amp;gt;, esta, es muy importante pues a muchos métodos para manipular celdas, se les tienen que pasar estructuras como esta, solo tiene tres propiedades, la hoja (valor tipo &amp;#039;&amp;#039;&amp;#039;integer&amp;#039;&amp;#039;&amp;#039; que también empieza en 0) donde esta la celda referenciada, la columna (&amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;) y la fila (&amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;) de esta celda.&lt;br /&gt;
&lt;br /&gt;
Ahora accedemos a una celda por su posición, recuerda que los índices de inicio desde código empiezan en 0, por lo que para hacer referencia a la celda E5, tenemos que poner la columna 4 y fila 4, el primer valor es para la columna y el segundo para la fila, no esta de más comentarte que tengas cuidado de no establecer una posición fuera de la hoja, pues te dará un error, si el valor de la fila y columna se la solicitas al usuario, “deberías” de validar que los valores proporcionados son correctos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    &lt;br /&gt;
    col = 9&lt;br /&gt;
    fil = 14&lt;br /&gt;
    if col &amp;lt; activa.getColumns().getCount() and fil &amp;lt; activa.getRows().getCount():&lt;br /&gt;
        celda = activa.getCellByPosition(col, fil)&lt;br /&gt;
        msgbox (celda.getString())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Valores incorrectos&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es frecuente que el acceso por nombre a una celda se use para establecer valores preestablecidos, como títulos de campos por ejemplo, y el acceso por posición es muy útil para realizar ciclos, como el ejemplo siguiente que inserta el año como titulo en la celda A1 y los meses del año de la celda A2 a la A13.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import datetime&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
        &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa.getCellRangeByName(&amp;#039;A1&amp;#039;).setString(datetime.date.today().year)&lt;br /&gt;
    for i in range(1,13):&lt;br /&gt;
        activa.getCellByPosition(0, i).setString(datetime.date(2013, i, 1).strftime(&amp;#039;%B&amp;#039;))&lt;br /&gt;
&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que hemos estado usando el método &amp;#039;&amp;#039;&amp;#039;getString()&amp;#039;&amp;#039;&amp;#039; para obtener el contenido de una celda y &amp;#039;&amp;#039;&amp;#039;setString(cadena)&amp;#039;&amp;#039;&amp;#039; para establecerlo, más adelante veremos todas las posibilidades que tenemos para introducir u obtener datos de las celdas de nuestra hoja de calculo, así como sus diferencias.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a un rango de celdas ==&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a un rango de celdas por su nombre, usando el mismo método usado para acceder a una celda.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;A1:E5&amp;#039;)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para acceder a un rango de celdas por su posición, hay que usar un método diferente: &amp;#039;&amp;#039;&amp;#039;getCellRangeByPosition&amp;#039;&amp;#039;&amp;#039;, que requiere de cuatro argumentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    # Seleccionamos el rango B1:C10&lt;br /&gt;
    rango = activa.getCellRangeByPosition(1, 0, 2, 9)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que este nuevo método requiere cuatro argumentos: la columna y fila donde empieza nuestro rango y la columna y fila donde termina, recuerda que los números de fila y columna empiezan en 0, algunos piensan que los dos últimos argumentos son el ancho y alto del rango a usar, no es así, estos argumentos también son números de índices de columna y fila respectivamente y tienes que tener la precaución de establecer los segundos iguales o mas grandes que los primeros, sino, te dará un error en tiempo de ejecución y por supuesto sin sobrepasar el máximo de filas y columnas de la hoja de calculo. Observa también, como en la ultima línea seleccionamos el rango referenciado.&lt;br /&gt;
&lt;br /&gt;
Otra posibilidad, es usar nombres definidos de rangos, es decir, aquellos que establecemos desde el &amp;#039;&amp;#039;&amp;#039;Cuadro de nombre&amp;#039;&amp;#039;&amp;#039; en la hoja de calculo, ya sabes, ese cuadro de lista desplegable (combobox) que esta al lado de la barra de formulas, que también puedes establecer desde el menú &amp;#039;&amp;#039;&amp;#039;&amp;#039;Insertar | Nombres | Definir...&amp;#039;&amp;#039;&amp;#039;&amp;#039; cuya teclas de acceso rápido son {{Key|Ctrl|F3}}. En el siguiente ejemplo, seleccionamos el rango de celdas llamado Datos. Toma nota de que si el rango no existe en la hoja desde donde se intenta referenciar, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;Datos&amp;#039;)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Este método no es sensible a mayúsculas o minúsculas. Observa como primero obtenemos una referencia a la interfaz &amp;lt;idl&amp;gt;com.sun.star.sheet.XNamedRanges&amp;lt;/idl&amp;gt; y dado que esta hereda la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XNameAccess&amp;lt;/idl&amp;gt; podemos usar el método &amp;#039;&amp;#039;&amp;#039;getElementNames&amp;#039;&amp;#039;&amp;#039; para obtener todos los nombres con rango en el documento. Si el usuario es el que proporciona el nombre del rango, como siempre, es mejor validar que el rango exista.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nr = doc.NamedRanges&lt;br /&gt;
    nombre = &amp;#039;Datos&amp;#039;&lt;br /&gt;
    nombres_rangos = nr.getElementNames()&lt;br /&gt;
    &lt;br /&gt;
    if nombre in nombres_rangos:&lt;br /&gt;
        rango = nr.getByName(nombre).getReferredCells()&lt;br /&gt;
        doc.getCurrentController().select(rango)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe el rango: %S&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No confundas estos nombres de rangos, con los que puedes establecer en el menú &amp;#039;&amp;#039;&amp;#039;Datos | Definir rango...&amp;#039;&amp;#039;&amp;#039;, ya que estos últimos se refieren a rangos considerados como una tabla de datos, de hecho, puedes tener un mismo nombre para un rango de celdas y para un rango de datos, pero son dos cosas diferentes, los segundos, los veremos más adelante.&lt;br /&gt;
&lt;br /&gt;
De los rangos de celdas, también es posible obtener información, para ello se hace uso de la estructura &amp;lt;idl&amp;gt;com.sun.star.table.CellRangeAddress&amp;lt;/idl&amp;gt; a través del método &amp;#039;&amp;#039;&amp;#039;getRangeAddress&amp;#039;&amp;#039;&amp;#039; que te devuelve información de: la hoja donde esta el rango, la columna y fila donde comienza y la columna y fila donde acaba.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;Datos&amp;#039;)&lt;br /&gt;
    ra = rango.getRangeAddress()&lt;br /&gt;
    &lt;br /&gt;
    message = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    El rango esta en la hoja: %s&lt;br /&gt;
    Columna inicio: %s&lt;br /&gt;
    Fila Inicio: %s&lt;br /&gt;
    Columna final: %s&lt;br /&gt;
    Fila final: %s&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; % (ra.Sheet, ra.StartColumn, ra.StartRow, ra.EndColumn, ra.EndRow)&lt;br /&gt;
    &lt;br /&gt;
    msgbox(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta estructura (&amp;#039;&amp;#039;&amp;#039;getRangeAddress&amp;#039;&amp;#039;&amp;#039;) también es usada por varios métodos para manipular rangos que veremos más adelante, por lo que es importante que la tengas presente.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a varios rangos de celdas ==&lt;br /&gt;
&lt;br /&gt;
Cuando en la interfaz del usuario, hacemos la selección de un rango y mantenemos presionada la tecla {{Key|Ctrl}} y hacemos un segunda selección de un rango y así sucesivamente, estamos hablando de un conjunto de rangos que tiene sus características particulares para su control y manejo. Para seleccionar varios rangos desde código, primero debemos crear el &amp;#039;&amp;#039;&amp;#039;contenedor&amp;#039;&amp;#039;&amp;#039; de estos rangos, veamos como.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    #~ Creamos el contender para los rangos&lt;br /&gt;
    rangos = doc.createInstance(&amp;#039;com.sun.star.sheet.SheetCellRanges&amp;#039;)&lt;br /&gt;
    #~ Creamos la estructura CellRangeAddress necesaria&lt;br /&gt;
    dir_rango = activa.getCellRangeByName(&amp;#039;A1:B2&amp;#039;).getRangeAddress()&lt;br /&gt;
    #~ Y lo agregamos al contenedor de rangos&lt;br /&gt;
    rangos.addRangeAddress(dir_rango, False)&lt;br /&gt;
    #~ Aquí solo hacemos referencia al rango&lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;E1:G2&amp;#039;)&lt;br /&gt;
    #~ Y lo agregamos al contenedor de rangos, nota como tenemos que usar&lt;br /&gt;
    #~ el método getRangeAddress para pasarle el argumento correcto&lt;br /&gt;
    rangos.addRangeAddress(rango.getRangeAddress(), False)&lt;br /&gt;
    #~ Aquí agregamos un rango directamente al contenedor&lt;br /&gt;
    #~ toma en cuenta que se van acumulando &lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;D4:E5&amp;#039;).getRangeAddress() , False)&lt;br /&gt;
&lt;br /&gt;
    #~ Comprobamos que están correctos seleccionándolos&lt;br /&gt;
    doc.getCurrentController().select(rangos)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No te confundas, las tres líneas donde se agrega el rango con el método &amp;#039;&amp;#039;&amp;#039;addRangeAddress()&amp;#039;&amp;#039;&amp;#039; son iguales, lo que cambia es la forma en que hacemos referencia a la dirección del rango, si vas empezando a programar, te recomiendo ir desglosando cada línea, con el tiempo y la experiencia, podrás concentrar código de forma más natural, por ahora, usa todas las líneas que consideres pertinentes para que tu código lo entiendas con solo verlo.&lt;br /&gt;
&lt;br /&gt;
Por supuesto, también de estos rangos podemos obtener información, por ejemplo, los nombres de los rangos que contiene,&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    #~ Creamos el contender para los rangos&lt;br /&gt;
    rangos = doc.createInstance(&amp;#039;com.sun.star.sheet.SheetCellRanges&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    #~ Agregamos los rangos que queramos&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;A1:A2&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;B4:B5&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;C7:C8&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;D10:D11&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;E13:E14&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
&lt;br /&gt;
    #~ Mostramos las direcciones de los rangos&lt;br /&gt;
    msgbox(rangos.getRangeAddressesAsString())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota como los rangos es una cadena larga de las direcciones de los rangos separados por un &amp;#039;&amp;#039;&amp;#039;;&amp;#039;&amp;#039;&amp;#039;, si lo quieres mejor presentable, reemplaza los puntos y comas por un salto de línea con el siguiente código.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    #~ Mostramos las direcciones de los rangos&lt;br /&gt;
    message = rangos.getRangeAddressesAsString().replace(&amp;#039;;&amp;#039;, &amp;#039;\n&amp;#039;)&lt;br /&gt;
    msgbox(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]]&lt;br /&gt;
[[Category:Manuales]]&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos&amp;diff=221908</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos&amp;diff=221908"/>
		<updated>2013-05-22T03:56:16Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE: Referencia a rangos}}&lt;br /&gt;
&lt;br /&gt;
Seguro que sabes, si eres usuario habitual de una hoja de calculo, que el trabajo con rangos es esencial en estos documentos, por lo mismo, el trabajo con rangos desde código es igualmente importante, ya vimos como aseguramos que estamos trabajando en una hoja de calculo, así que dejo a tu criterio esta validación. En la siguientes secciones nos centraremos en aprender como hacer referencia a distintos tipos de rangos para después poder manipularlos, darles formato o hacer con ellos lo que queramos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a celdas individuales ==&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a las celdas de una hoja de calculo de varias maneras, principalmente por su nombre o por su posición, pero muy importante, primero tienes que acceder a la hoja donde están las celdas que te interesa manipular, como acceder a hojas es un tema que ya hemos tratado, pero en cada ejemplo podrás notar que repasamos estos conocimientos, la forma más simple de hacer referencia a una celda es por su nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    # Referencia a la celda E5&lt;br /&gt;
    celda = activa.getCellRangeByName(&amp;#039;E5&amp;#039;)&lt;br /&gt;
    # Mostramos el contenido de la celda&lt;br /&gt;
    msgbox (celda.getString())&lt;br /&gt;
    # Mostramos direccion de esta celda&lt;br /&gt;
    ca = celda.getCellAddress()&lt;br /&gt;
    message = u&amp;#039;Columna: %s\nFila: %s\nHoja: %s&amp;#039; % (ca.Column, ca.Row, ca.Sheet)&lt;br /&gt;
    msgbox (message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como comprobamos en la ultima linea, que efectivamente hemos hecho referencia a la celda que nos interesa, es decir a la celda E5, que en columna y fila es la 4, por que recordamos que los números de columna y fila empiezan en 0, observa la estructura &amp;lt;idl&amp;gt;com.sun.star.table.CellAddress&amp;lt;/idl&amp;gt;, esta, es muy importante pues a muchos métodos para manipular celdas, se les tienen que pasar estructuras como esta, solo tiene tres propiedades, la hoja (valor tipo &amp;#039;&amp;#039;&amp;#039;integer&amp;#039;&amp;#039;&amp;#039; que también empieza en 0) donde esta la celda referenciada, la columna (&amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;) y la fila (&amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;) de esta celda.&lt;br /&gt;
&lt;br /&gt;
Ahora accedemos a una celda por su posición, recuerda que los índices de inicio desde código empiezan en 0, por lo que para hacer referencia a la celda E5, tenemos que poner la columna 4 y fila 4, el primer valor es para la columna y el segundo para la fila, no esta de más comentarte que tengas cuidado de no establecer una posición fuera de la hoja, pues te dará un error, si el valor de la fila y columna se la solicitas al usuario, “deberías” de validar que los valores proporcionados son correctos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    &lt;br /&gt;
    col = 9&lt;br /&gt;
    fil = 14&lt;br /&gt;
    if col &amp;lt; activa.getColumns().getCount() and fil &amp;lt; activa.getRows().getCount():&lt;br /&gt;
        celda = activa.getCellByPosition(col, fil)&lt;br /&gt;
        msgbox (celda.getString())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Valores incorrectos&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es frecuente que el acceso por nombre a una celda se use para establecer valores preestablecidos, como títulos de campos por ejemplo, y el acceso por posición es muy útil para realizar ciclos, como el ejemplo siguiente que inserta el año como titulo en la celda A1 y los meses del año de la celda A2 a la A13.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import datetime&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
        &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa.getCellRangeByName(&amp;#039;A1&amp;#039;).setString(datetime.date.today().year)&lt;br /&gt;
    for i in range(1,13):&lt;br /&gt;
        activa.getCellByPosition(0, i).setString(datetime.date(2013, i, 1).strftime(&amp;#039;%B&amp;#039;))&lt;br /&gt;
&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que hemos estado usando el método &amp;#039;&amp;#039;&amp;#039;getString()&amp;#039;&amp;#039;&amp;#039; para obtener el contenido de una celda y &amp;#039;&amp;#039;&amp;#039;setString(cadena)&amp;#039;&amp;#039;&amp;#039; para establecerlo, más adelante veremos todas las posibilidades que tenemos para introducir u obtener datos de las celdas de nuestra hoja de calculo, así como sus diferencias.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a un rango de celdas ==&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a un rango de celdas por su nombre, usando el mismo método usado para acceder a una celda.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;A1:E5&amp;#039;)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para acceder a un rango de celdas por su posición, hay que usar un método diferente: &amp;#039;&amp;#039;&amp;#039;getCellRangeByPosition&amp;#039;&amp;#039;&amp;#039;, que requiere de cuatro argumentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    # Seleccionamos el rango B1:C10&lt;br /&gt;
    rango = activa.getCellRangeByPosition(1, 0, 2, 9)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que este nuevo método requiere cuatro argumentos: la columna y fila donde empieza nuestro rango y la columna y fila donde termina, recuerda que los números de fila y columna empiezan en 0, algunos piensan que los dos últimos argumentos son el ancho y alto del rango a usar, no es así, estos argumentos también son números de índices de columna y fila respectivamente y tienes que tener la precaución de establecer los segundos iguales o mas grandes que los primeros, sino, te dará un error en tiempo de ejecución y por supuesto sin sobrepasar el máximo de filas y columnas de la hoja de calculo. Observa también, como en la ultima línea seleccionamos el rango referenciado.&lt;br /&gt;
&lt;br /&gt;
Otra posibilidad, es usar nombres definidos de rangos, es decir, aquellos que establecemos desde el &amp;#039;&amp;#039;&amp;#039;Cuadro de nombre&amp;#039;&amp;#039;&amp;#039; en la hoja de calculo, ya sabes, ese cuadro de lista desplegable (combobox) que esta al lado de la barra de formulas, que también puedes establecer desde el menú &amp;#039;&amp;#039;&amp;#039;&amp;#039;Insertar | Nombres | Definir...&amp;#039;&amp;#039;&amp;#039;&amp;#039; cuya teclas de acceso rápido son {{Key|Ctrl|F3}}. En el siguiente ejemplo, seleccionamos el rango de celdas llamado Datos. Toma nota de que si el rango no existe en la hoja desde donde se intenta referenciar, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;Datos&amp;#039;)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Este método no es sensible a mayúsculas o minúsculas. Observa como primero obtenemos una referencia a la interfaz &amp;lt;idl&amp;gt;com.sun.star.sheet.XNamedRanges&amp;lt;/idl&amp;gt; y dado que esta hereda la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XNameAccess&amp;lt;/idl&amp;gt; podemos usar el método &amp;#039;&amp;#039;&amp;#039;getElementNames&amp;#039;&amp;#039;&amp;#039; para obtener todos los nombres con rango en el documento. Si el usuario es el que proporciona el nombre del rango, como siempre, es mejor validar que el rango exista.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nr = doc.NamedRanges&lt;br /&gt;
    nombre = &amp;#039;Datos&amp;#039;&lt;br /&gt;
    nombres_rangos = nr.getElementNames()&lt;br /&gt;
    &lt;br /&gt;
    if nombre in nombres_rangos:&lt;br /&gt;
        rango = nr.getByName(nombre).getReferredCells()&lt;br /&gt;
        doc.getCurrentController().select(rango)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe el rango: %S&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No confundas estos nombres de rangos, con los que puedes establecer en el menú &amp;#039;&amp;#039;&amp;#039;Datos | Definir rango...&amp;#039;&amp;#039;&amp;#039;, ya que estos últimos se refieren a rangos considerados como una tabla de datos, de hecho, puedes tener un mismo nombre para un rango de celdas y para un rango de datos, pero son dos cosas diferentes, los segundos, los veremos más adelante.&lt;br /&gt;
&lt;br /&gt;
De los rangos de celdas, también es posible obtener información, para ello se hace uso de la estructura &amp;lt;idl&amp;gt;com.sun.star.table.CellRangeAddress&amp;lt;/idl&amp;gt; a través del método &amp;#039;&amp;#039;&amp;#039;getRangeAddress&amp;#039;&amp;#039;&amp;#039; que te devuelve información de: la hoja donde esta el rango, la columna y fila donde comienza y la columna y fila donde acaba.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;Datos&amp;#039;)&lt;br /&gt;
    ra = rango.getRangeAddress()&lt;br /&gt;
    &lt;br /&gt;
    message = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    El rango esta en la hoja: %s&lt;br /&gt;
    Columna inicio: %s&lt;br /&gt;
    Fila Inicio: %s&lt;br /&gt;
    Columna final: %s&lt;br /&gt;
    Fila final: %s&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; % (ra.Sheet, ra.StartColumn, ra.StartRow, ra.EndColumn, ra.EndRow)&lt;br /&gt;
    &lt;br /&gt;
    msgbox(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta estructura (&amp;#039;&amp;#039;&amp;#039;getRangeAddress&amp;#039;&amp;#039;&amp;#039;) también es usada por varios métodos para manipular rangos que veremos más adelante, por lo que es importante que la tengas presente.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a varios rangos de celdas ==&lt;br /&gt;
&lt;br /&gt;
Cuando en la interfaz del usuario, hacemos la selección de un rango y mantenemos presionada la tecla {{Key|Ctrl}} y hacemos un segunda selección de un rango y así sucesivamente, estamos hablando de un conjunto de rangos que tiene sus características particulares para su control y manejo. Para seleccionar varios rangos desde código, primero debemos crear el &amp;#039;&amp;#039;&amp;#039;contenedor&amp;#039;&amp;#039;&amp;#039; de estos rangos, veamos como.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    #~ Creamos el contender para los rangos&lt;br /&gt;
    rangos = doc.createInstance(&amp;#039;com.sun.star.sheet.SheetCellRanges&amp;#039;)&lt;br /&gt;
    #~ Creamos la estructura CellRangeAddress necesaria&lt;br /&gt;
    dir_rango = activa.getCellRangeByName(&amp;#039;A1:B2&amp;#039;).getRangeAddress()&lt;br /&gt;
    #~ Y lo agregamos al contenedor de rangos&lt;br /&gt;
    rangos.addRangeAddress(dir_rango, False)&lt;br /&gt;
    #~ Aquí solo hacemos referencia al rango&lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;E1:G2&amp;#039;)&lt;br /&gt;
    #~ Y lo agregamos al contenedor de rangos, nota como tenemos que usar&lt;br /&gt;
    #~ el método getRangeAddress para pasarle el argumento correcto&lt;br /&gt;
    rangos.addRangeAddress(rango.getRangeAddress(), False)&lt;br /&gt;
    #~ Aquí agregamos un rango directamente al contenedor&lt;br /&gt;
    #~ toma en cuenta que se van acumulando &lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;D4:E5&amp;#039;).getRangeAddress() , False)&lt;br /&gt;
&lt;br /&gt;
    #~ Comprobamos que están correctos seleccionándolos&lt;br /&gt;
    doc.getCurrentController().select(rangos)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No te confundas, las tres líneas donde se agrega el rango con el método &amp;#039;&amp;#039;&amp;#039;addRangeAddress()&amp;#039;&amp;#039;&amp;#039; son iguales, lo que cambia es la forma en que hacemos referencia a la dirección del rango, si vas empezando a programar, te recomiendo ir desglosando cada línea, con el tiempo y la experiencia, podrás concentrar código de forma más natural, por ahora, usa todas las líneas que consideres pertinentes para que tu código lo entiendas con solo verlo.&lt;br /&gt;
&lt;br /&gt;
Por supuesto, también de estos rangos podemos obtener información, por ejemplo, los nombres de los rangos que contiene,&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    #~ Creamos el contender para los rangos&lt;br /&gt;
    rangos = doc.createInstance(&amp;#039;com.sun.star.sheet.SheetCellRanges&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    #~ Agregamos los rangos que queramos&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;A1:A2&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;B4:B5&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;C7:C8&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;D10:D11&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
    rangos.addRangeAddress(activa.getCellRangeByName(&amp;#039;E13:E14&amp;#039;).getRangeAddress(), False)&lt;br /&gt;
&lt;br /&gt;
    #~ Mostramos las direcciones de los rangos&lt;br /&gt;
    msgbox(rangos.getRangeAddressesAsString())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nota como los rangos es una cadena larga de las direcciones de los rangos separados por un &amp;#039;&amp;#039;&amp;#039;;&amp;#039;&amp;#039;&amp;#039;, si lo quieres mejor presentable, reemplaza los puntos y comas por un salto de línea con el siguiente código.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    #~ Mostramos las direcciones de los rangos&lt;br /&gt;
    message = rangos.getRangeAddressesAsString().replace(&amp;#039;;&amp;#039;, &amp;#039;\n&amp;#039;)&lt;br /&gt;
    msgbox(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]]&lt;br /&gt;
[[Category:Manuales]]&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos&amp;diff=221049</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos&amp;diff=221049"/>
		<updated>2013-05-15T04:23:18Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE: Referencia a rangos}}&lt;br /&gt;
&lt;br /&gt;
Seguro que sabes, si eres usuario habitual de una hoja de calculo, que el trabajo con rangos es esencial en estos documentos, por lo mismo, el trabajo con rangos desde código es igualmente importante, ya vimos como aseguramos que estamos trabajando en una hoja de calculo, así que dejo a tu criterio esta validación. En la siguientes secciones nos centraremos en aprender como hacer referencia a distintos tipos de rangos para después poder manipularlos, darles formato o hacer con ellos lo que queramos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a celdas individuales ==&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a las celdas de una hoja de calculo de varias maneras, principalmente por su nombre o por su posición, pero muy importante, primero tienes que acceder a la hoja donde están las celdas que te interesa manipular, como acceder a hojas es un tema que ya hemos tratado, pero en cada ejemplo podrás notar que repasamos estos conocimientos, la forma más simple de hacer referencia a una celda es por su nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    # Referencia a la celda E5&lt;br /&gt;
    celda = activa.getCellRangeByName(&amp;#039;E5&amp;#039;)&lt;br /&gt;
    # Mostramos el contenido de la celda&lt;br /&gt;
    msgbox (celda.getString())&lt;br /&gt;
    # Mostramos direccion de esta celda&lt;br /&gt;
    ca = celda.getCellAddress()&lt;br /&gt;
    message = u&amp;#039;Columna: %s\nFila: %s\nHoja: %s&amp;#039; % (ca.Column, ca.Row, ca.Sheet)&lt;br /&gt;
    msgbox (message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como comprobamos en la ultima linea, que efectivamente hemos hecho referencia a la celda que nos interesa, es decir a la celda E5, que en columna y fila es la 4, por que recordamos que los números de columna y fila empiezan en 0, observa la estructura &amp;lt;idl&amp;gt;com.sun.star.table.CellAddress&amp;lt;/idl&amp;gt;, esta, es muy importante pues a muchos métodos para manipular celdas, se les tienen que pasar estructuras como esta, solo tiene tres propiedades, la hoja (valor tipo &amp;#039;&amp;#039;&amp;#039;integer&amp;#039;&amp;#039;&amp;#039; que también empieza en 0) donde esta la celda referenciada, la columna (&amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;) y la fila (&amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;) de esta celda.&lt;br /&gt;
&lt;br /&gt;
Ahora accedemos a una celda por su posición, recuerda que los índices de inicio desde código empiezan en 0, por lo que para hacer referencia a la celda E5, tenemos que poner la columna 4 y fila 4, el primer valor es para la columna y el segundo para la fila, no esta de más comentarte que tengas cuidado de no establecer una posición fuera de la hoja, pues te dará un error, si el valor de la fila y columna se la solicitas al usuario, “deberías” de validar que los valores proporcionados son correctos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    &lt;br /&gt;
    col = 9&lt;br /&gt;
    fil = 14&lt;br /&gt;
    if col &amp;lt; activa.getColumns().getCount() and fil &amp;lt; activa.getRows().getCount():&lt;br /&gt;
        celda = activa.getCellByPosition(col, fil)&lt;br /&gt;
        msgbox (celda.getString())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Valores incorrectos&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es frecuente que el acceso por nombre a una celda se use para establecer valores preestablecidos, como títulos de campos por ejemplo, y el acceso por posición es muy útil para realizar ciclos, como el ejemplo siguiente que inserta el año como titulo en la celda A1 y los meses del año de la celda A2 a la A13.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import datetime&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
        &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa.getCellRangeByName(&amp;#039;A1&amp;#039;).setString(datetime.date.today().year)&lt;br /&gt;
    for i in range(1,13):&lt;br /&gt;
        activa.getCellByPosition(0, i).setString(datetime.date(2013, i, 1).strftime(&amp;#039;%B&amp;#039;))&lt;br /&gt;
&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que hemos estado usando el método &amp;#039;&amp;#039;&amp;#039;getString()&amp;#039;&amp;#039;&amp;#039; para obtener el contenido de una celda y &amp;#039;&amp;#039;&amp;#039;setString(cadena)&amp;#039;&amp;#039;&amp;#039; para establecerlo, más adelante veremos todas las posibilidades que tenemos para introducir u obtener datos de las celdas de nuestra hoja de calculo, así como sus diferencias.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a un rango de celdas ==&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a un rango de celdas por su nombre, usando el mismo método usado para acceder a una celda.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;A1:E5&amp;#039;)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para acceder a un rango de celdas por su posición, hay que usar un método diferente: &amp;#039;&amp;#039;&amp;#039;getCellRangeByPosition&amp;#039;&amp;#039;&amp;#039;, que requiere de cuatro argumentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    # Seleccionamos el rango B1:C10&lt;br /&gt;
    rango = activa.getCellRangeByPosition(1, 0, 2, 9)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que este nuevo método requiere cuatro argumentos: la columna y fila donde empieza nuestro rango y la columna y fila donde termina, recuerda que los números de fila y columna empiezan en 0, algunos piensan que los dos últimos argumentos son el ancho y alto del rango a usar, no es así, estos argumentos también son números de índices de columna y fila respectivamente y tienes que tener la precaución de establecer los segundos iguales o mas grandes que los primeros, sino, te dará un error en tiempo de ejecución y por supuesto sin sobrepasar el máximo de filas y columnas de la hoja de calculo. Observa también, como en la ultima línea seleccionamos el rango referenciado.&lt;br /&gt;
&lt;br /&gt;
Otra posibilidad, es usar nombres definidos de rangos, es decir, aquellos que establecemos desde el &amp;#039;&amp;#039;&amp;#039;Cuadro de nombre&amp;#039;&amp;#039;&amp;#039; en la hoja de calculo, ya sabes, ese cuadro de lista desplegable (combobox) que esta al lado de la barra de formulas, que también puedes establecer desde el menú &amp;#039;&amp;#039;&amp;#039;&amp;#039;Insertar | Nombres | Definir...&amp;#039;&amp;#039;&amp;#039;&amp;#039; cuya teclas de acceso rápido son {{Key|Ctrl|F3}}. En el siguiente ejemplo, seleccionamos el rango de celdas llamado Datos. Toma nota de que si el rango no existe en la hoja desde donde se intenta referenciar, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;Datos&amp;#039;)&lt;br /&gt;
    doc.getCurrentController().select(rango)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Este método no es sensible a mayúsculas o minúsculas. Observa como primero obtenemos una referencia a la interfaz &amp;lt;idl&amp;gt;com.sun.star.sheet.XNamedRanges&amp;lt;/idl&amp;gt; y dado que esta hereda la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XNameAccess&amp;lt;/idl&amp;gt; podemos usar el método &amp;#039;&amp;#039;&amp;#039;getElementNames&amp;#039;&amp;#039;&amp;#039; para obtener todos los nombres con rango en el documento. Si el usuario es el que proporciona el nombre del rango, como siempre, es mejor validar que el rango exista.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nr = doc.NamedRanges&lt;br /&gt;
    nombre = &amp;#039;Datos&amp;#039;&lt;br /&gt;
    nombres_rangos = nr.getElementNames()&lt;br /&gt;
    &lt;br /&gt;
    if nombre in nombres_rangos:&lt;br /&gt;
        rango = nr.getByName(nombre).getReferredCells()&lt;br /&gt;
        doc.getCurrentController().select(rango)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe el rango: %S&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No confundas estos nombres de rangos, con los que puedes establecer en el menú &amp;#039;&amp;#039;&amp;#039;Datos | Definir rango...&amp;#039;&amp;#039;&amp;#039;, ya que estos últimos se refieren a rangos considerados como una tabla de datos, de hecho, puedes tener un mismo nombre para un rango de celdas y para un rango de datos, pero son dos cosas diferentes, los segundos, los veremos más adelante.&lt;br /&gt;
&lt;br /&gt;
De los rangos de celdas, también es posible obtener información, para ello se hace uso de la estructura &amp;lt;idl&amp;gt;com.sun.star.table.CellRangeAddress&amp;lt;/idl&amp;gt; a través del método &amp;#039;&amp;#039;&amp;#039;getRangeAddress&amp;#039;&amp;#039;&amp;#039; que te devuelve información de: la hoja donde esta el rango, la columna y fila donde comienza y la columna y fila donde acaba.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()    &lt;br /&gt;
    rango = activa.getCellRangeByName(&amp;#039;Datos&amp;#039;)&lt;br /&gt;
    ra = rango.getRangeAddress()&lt;br /&gt;
    &lt;br /&gt;
    message = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    El rango esta en la hoja: %s&lt;br /&gt;
    Columna inicio: %s&lt;br /&gt;
    Fila Inicio: %s&lt;br /&gt;
    Columna final: %s&lt;br /&gt;
    Fila final: %s&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; % (ra.Sheet, ra.StartColumn, ra.StartRow, ra.EndColumn, ra.EndRow)&lt;br /&gt;
    &lt;br /&gt;
    msgbox(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta estructura (&amp;#039;&amp;#039;&amp;#039;getRangeAddress&amp;#039;&amp;#039;&amp;#039;) también es usada por varios métodos para manipular rangos que veremos más adelante, por lo que es importante que la tengas presente.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]]&lt;br /&gt;
[[Category:Manuales]]&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos&amp;diff=220793</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos&amp;diff=220793"/>
		<updated>2013-05-14T04:18:39Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: Created page with &amp;quot;{{DISPLAYTITLE: Referencia a rangos}}  Seguro que sabes, si eres usuario habitual de una hoja de calculo, que el trabajo con rangos es esencial en estos documentos, por lo mis...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE: Referencia a rangos}}&lt;br /&gt;
&lt;br /&gt;
Seguro que sabes, si eres usuario habitual de una hoja de calculo, que el trabajo con rangos es esencial en estos documentos, por lo mismo, el trabajo con rangos desde código es igualmente importante, ya vimos como aseguramos que estamos trabajando en una hoja de calculo, así que dejo a tu criterio esta validación. En la siguientes secciones nos centraremos en aprender como hacer referencia a distintos tipos de rangos para después poder manipularlos, darles formato o hacer con ellos lo que queramos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Referencia a celdas individuales ==&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a las celdas de una hoja de calculo de varias maneras, principalmente por su nombre o por su posición, pero muy importante, primero tienes que acceder a la hoja donde están las celdas que te interesa manipular, como acceder a hojas es un tema que ya hemos tratado, pero en cada ejemplo podrás notar que repasamos estos conocimientos, la forma más simple de hacer referencia a una celda es por su nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    # Referencia a la celda E5&lt;br /&gt;
    celda = activa.getCellRangeByName(&amp;#039;E5&amp;#039;)&lt;br /&gt;
    # Mostramos el contenido de la celda&lt;br /&gt;
    msgbox (celda.getString())&lt;br /&gt;
    # Mostramos direccion de esta celda&lt;br /&gt;
    ca = celda.getCellAddress()&lt;br /&gt;
    message = u&amp;#039;Columna: %s\nFila: %s\nHoja: %s&amp;#039; % (ca.Column, ca.Row, ca.Sheet)&lt;br /&gt;
    msgbox (message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como comprobamos en la ultima linea, que efectivamente hemos hecho referencia a la celda que nos interesa, es decir a la celda E5, que en columna y fila es la 4, por que recordamos que los números de columna y fila empiezan en 0, observa la estructura &amp;lt;idl&amp;gt;com.sun.star.table.CellAddress&amp;lt;/idl&amp;gt;, esta, es muy importante pues a muchos métodos para manipular celdas, se les tienen que pasar estructuras como esta, solo tiene tres propiedades, la hoja (valor tipo &amp;#039;&amp;#039;&amp;#039;integer&amp;#039;&amp;#039;&amp;#039; que también empieza en 0) donde esta la celda referenciada, la columna (&amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;) y la fila (&amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;) de esta celda.&lt;br /&gt;
&lt;br /&gt;
Ahora accedemos a una celda por su posición, recuerda que los índices de inicio desde código empiezan en 0, por lo que para hacer referencia a la celda E5, tenemos que poner la columna 4 y fila 4, el primer valor es para la columna y el segundo para la fila, no esta de más comentarte que tengas cuidado de no establecer una posición fuera de la hoja, pues te dará un error, si el valor de la fila y columna se la solicitas al usuario, “deberías” de validar que los valores proporcionados son correctos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    &lt;br /&gt;
    col = 9&lt;br /&gt;
    fil = 14&lt;br /&gt;
    if col &amp;lt; activa.getColumns().getCount() and fil &amp;lt; activa.getRows().getCount():&lt;br /&gt;
        celda = activa.getCellByPosition(col, fil)&lt;br /&gt;
        msgbox (celda.getString())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Valores incorrectos&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es frecuente que el acceso por nombre a una celda se use para establecer valores preestablecidos, como títulos de campos por ejemplo, y el acceso por posición es muy útil para realizar ciclos, como el ejemplo siguiente que inserta el año como titulo en la celda A1 y los meses del año de la celda A2 a la A13.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import datetime&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
        &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa.getCellRangeByName(&amp;#039;A1&amp;#039;).setString(datetime.date.today().year)&lt;br /&gt;
    for i in range(1,13):&lt;br /&gt;
        activa.getCellByPosition(0, i).setString(datetime.date(2013, i, 1).strftime(&amp;#039;%B&amp;#039;))&lt;br /&gt;
&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que hemos estado usando el método &amp;#039;&amp;#039;&amp;#039;getString()&amp;#039;&amp;#039;&amp;#039; para obtener el contenido de una celda y &amp;#039;&amp;#039;&amp;#039;setString(cadena)&amp;#039;&amp;#039;&amp;#039; para establecerlo, más adelante veremos todas las posibilidades que tenemos para introducir u obtener datos de las celdas de nuestra hoja de calculo, así como sus diferencias.&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219958</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219958"/>
		<updated>2013-05-10T05:03:36Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Protección y desprotección de hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Otra hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, hojas.getCount())&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por &amp;#039;&amp;#039;&amp;#039;getCount()&amp;#039;&amp;#039;&amp;#039; pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    indice = activa.getRangeAddress().Sheet &lt;br /&gt;
    msgbox(u&amp;#039;El índice de la hoja activa es: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir en una submacro. Nota como estamos estableciendo un &amp;#039;&amp;#039;&amp;#039;valor por default&amp;#039;&amp;#039;&amp;#039; para el ultimo argumento que será la posición deseada para la nueva hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nueva_hoja(doc, nombre, pos=0):&lt;br /&gt;
    hojas = doc.getSheets() &lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
        indice = activa.getRangeAddress().Sheet&lt;br /&gt;
        if pos == 1:&lt;br /&gt;
            pos = indice&lt;br /&gt;
        elif pos == 2:&lt;br /&gt;
            pos = indice + 1&lt;br /&gt;
        elif pos &amp;gt; 2:&lt;br /&gt;
            pos = hojas.getCount()&lt;br /&gt;
        hojas.insertNewByName(nombre, pos)&lt;br /&gt;
        return hojas.getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora ya podemos insertar una nueva hoja en la posición que sea.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al inicio&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Antes de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 1)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Despues de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 2)&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al final&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 3)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
Para borrar hojas, usamos el método &amp;#039;&amp;#039;&amp;#039;removeByName(Nombre)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Nombre&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; es el nombre de la hoja que queremos borrar, no esta de más recomendarte usar con cuidado el borrado de hojas, aunque algo que me gusta mucho de AOO, es que muchas de las acciones que hacemos por código, son susceptibles de deshacerse de forma normal con la barra de herramientas o con CTRL+Z, el borrado de hojas es una de ellas, compruébalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(&amp;#039;Hoja3&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto no puedes borrar una hoja que no exista, así que verifícalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes borrar la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(activa.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior hasta que no quede ni una, claro, no te dejara por que un documento de hoja de calculo por lo menos debe de tener una hoja, para evitar el error que te da al tratar de borrar la ultima hoja, valida que siempre quede más de una.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;borrame&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and hojas.getCount() &amp;gt; 1:&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;La hoja no existe o solo queda una&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
Para mover hojas usamos el método &amp;#039;&amp;#039;&amp;#039;moveByName(NombreHoja, PosicionNueva)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;NombreHoja&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; tiene que ser el nombre de una hoja existente. En el siguiente ejemplo movemos la hoja al inicio.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, la movemos al final.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, hojas.getCount())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos  a hacer algo muy divertido, como ya sabemos obtener los nombres e índices de cada hoja, y ahora hemos aprendido a mover hojas, hagamos una macro que nos ordene alfabéticamente nuestras hojas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = sorted(hojas.getElementNames())&lt;br /&gt;
    for i,v in enumerate(nombres):&lt;br /&gt;
        hojas.moveByName(v, i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
Para copiar hojas usamos el método &amp;#039;&amp;#039;&amp;#039;copyByName(NombreHoja, NombreNuevo, Posicion)&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.copyByName(&amp;#039;Hoja2&amp;#039;, &amp;#039;Nueva hoja2&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto el nombre de la hoja a copiar debe de existir y el nombre nuevo de la hoja no debe existir, lo mejor, es evaluarlo antes.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Datos&amp;#039;&lt;br /&gt;
    nombre_nuevo = &amp;#039;Datos nuevos&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and not hojas.hasByName(nombre_nuevo):&lt;br /&gt;
        hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se copio la hoja&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos intentar copiar una hoja y asegurarnos de que el nombre no exista, tomando como base el nombre actual de la hoja, por ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = doc.getCurrentController().getActiveSheet().getName()&lt;br /&gt;
    co1 = 1&lt;br /&gt;
    nombre_nuevo = &amp;#039;%s_%s&amp;#039; % (nombre, co1)&lt;br /&gt;
    while hojas.hasByName(nombre_nuevo):&lt;br /&gt;
        co1 += 1&lt;br /&gt;
        nombre_nuevo = &amp;#039;%s_%s&amp;#039; % (nombre, co1)&lt;br /&gt;
    hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())&lt;br /&gt;
    hoja = hojas.getByName(nombre_nuevo)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(hoja)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
Para renombrar hojas usamos el método &amp;#039;&amp;#039;&amp;#039;setName(NuevoNombre)&amp;#039;&amp;#039;&amp;#039;, de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.getByName(&amp;#039;Hola&amp;#039;).setName(&amp;#039;Prueba&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También puedes usar el índice para referirte a la hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.getByIndex(0).setName(&amp;#039;Prueba&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es recomendable validar que la hoja a renombrar exista y que el nuevo nombre no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    actual = &amp;#039;Resumen&amp;#039;&lt;br /&gt;
    nuevo = &amp;#039;Terminado&amp;#039;&lt;br /&gt;
    # Validamos que la hoja exista y el nuevo nombre no&lt;br /&gt;
    if hojas.hasByName(actual) and not hojas.hasByName(nuevo):&lt;br /&gt;
        hojas.getByName(actual).setName(nuevo)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No es posible renombrar la hoja&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo para divertirnos, cambiamos los nombres de las hojas por números.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(i+1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora por letras, el código siguiente podría fallar en algunas circunstancias, tu tarea es decirnos ¿porqué? y corregirlo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(chr(i+65))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O los meses del año:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import datetime&lt;br /&gt;
import locale&lt;br /&gt;
locale.setlocale(locale.LC_ALL, &amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(datetime.date(2013, i+1, 1).strftime(&amp;#039;%B&amp;#039;))&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que hacemos uso de dos nuevas librerias de Python, &amp;#039;&amp;#039;&amp;#039;datetime&amp;#039;&amp;#039;&amp;#039; que tiene muchas utiles funciones para trabajar con fechas y tiempo, y &amp;#039;&amp;#039;&amp;#039;locale&amp;#039;&amp;#039;&amp;#039; para que los meses nos salgan en español.&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
Mostrar y ocultar hojas es muy sencillo, solo hay que establecer su propiedad &amp;#039;&amp;#039;&amp;#039;IsVisible&amp;#039;&amp;#039;&amp;#039; en verdadero (True) o falso (False) según se requiera de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa.IsVisible = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La macro anterior te ocultara la hoja activa, si la ejecutas varias veces te ira ocultando tus hojas hasta que solo quede una, si solo hay una no te dará error, pero la dejará visible por que, como sabes, tiene que haber al menos una hoja visible en un documento de Calc. Si ocultas una hoja, esta no cambia de índice por lo que puedes usar el mismo para acceder a ella, aunque este oculta, la siguiente macro alterna entre mostrar y ocultar la segunda hoja del documento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hoja = doc.getSheets().getByIndex(1)&lt;br /&gt;
    hoja.IsVisible = not hoja.IsVisible&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(hoja)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como ya habrás intuido, para mostrar una hoja oculta simplemente hay que establecer esta propiedad en verdadero (True). El siguiente código te oculta todas las hojas, excepto la hoja activa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet().getRangeAddress().Sheet&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        if i != activa:&lt;br /&gt;
            hojas.getByIndex(i).IsVisible = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tu tarea es hacer la función inversa, muestra todas las hojas ocultas.&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
Para terminar este capítulo, veamos como proteger una hoja, es decir, establecer una contraseña para evitar modificaciones a la misma, además, recuerda que para que la protección de celdas individuales sea efectiva, la hoja debe estar protegida. Para proteger una hoja, usamos el método &amp;#039;&amp;#039;&amp;#039;protect(contraseña)&amp;#039;&amp;#039;&amp;#039;, pasándole como argumento, la contraseña que queremos establecer, por supuesto, puedes pasarle una contraseña vacía, con lo que la hoja no estará muy protegida que digamos, pero créeme, muchos usuarios no saben desproteger una hoja, aun sin contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa.protect(&amp;#039;letmein&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y para desproteger, usamos el método &amp;#039;&amp;#039;&amp;#039;unprotect(contraseña)&amp;#039;&amp;#039;&amp;#039;, si la hoja tiene contraseña hay que pasársela como argumento, si no es correcta, el método no te devolverá ningún error como en la interfaz del usuario que te avisa que la contraseña es incorrecta, para saber si tuvo éxito o no la desprotección, hay que verificar la propiedad &amp;#039;&amp;#039;&amp;#039;isProtected&amp;#039;&amp;#039;&amp;#039;, si es verdadera (True) la hoja sigue protegida, si es falsa (False), la hoja esta desprotegida.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    if activa.isProtected():&lt;br /&gt;
        msgbox(&amp;#039;Hoja protegida, se va a desproteger&amp;#039;)&lt;br /&gt;
        activa.unprotect(&amp;#039;letmein&amp;#039;)&lt;br /&gt;
        if activa.isProtected():&lt;br /&gt;
            msgbox(&amp;#039;Contraseña incorrecta&amp;#039;)&lt;br /&gt;
        else:&lt;br /&gt;
            msgbox(&amp;#039;Hoja desprotegida correctamente&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;La hoja no esta protegida&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como comentarios finales, si intentas proteger una hoja que ya tiene contraseña, no obtendrás ningún error, pero la hoja permanecerá con la contraseña original, para cambiarla, primero tienes que desprotegerla y después cambiarla. Cuando proteges una hoja e intentas hacer modificaciones a esta, por ejemplo, escribir en una celda, tampoco retornará ningún error, pero no será efectiva la modificación.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{ES/Foro|macros}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219957</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219957"/>
		<updated>2013-05-10T05:02:49Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Protección y desprotección de hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Otra hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, hojas.getCount())&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por &amp;#039;&amp;#039;&amp;#039;getCount()&amp;#039;&amp;#039;&amp;#039; pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    indice = activa.getRangeAddress().Sheet &lt;br /&gt;
    msgbox(u&amp;#039;El índice de la hoja activa es: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir en una submacro. Nota como estamos estableciendo un &amp;#039;&amp;#039;&amp;#039;valor por default&amp;#039;&amp;#039;&amp;#039; para el ultimo argumento que será la posición deseada para la nueva hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nueva_hoja(doc, nombre, pos=0):&lt;br /&gt;
    hojas = doc.getSheets() &lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
        indice = activa.getRangeAddress().Sheet&lt;br /&gt;
        if pos == 1:&lt;br /&gt;
            pos = indice&lt;br /&gt;
        elif pos == 2:&lt;br /&gt;
            pos = indice + 1&lt;br /&gt;
        elif pos &amp;gt; 2:&lt;br /&gt;
            pos = hojas.getCount()&lt;br /&gt;
        hojas.insertNewByName(nombre, pos)&lt;br /&gt;
        return hojas.getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora ya podemos insertar una nueva hoja en la posición que sea.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al inicio&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Antes de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 1)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Despues de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 2)&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al final&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 3)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
Para borrar hojas, usamos el método &amp;#039;&amp;#039;&amp;#039;removeByName(Nombre)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Nombre&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; es el nombre de la hoja que queremos borrar, no esta de más recomendarte usar con cuidado el borrado de hojas, aunque algo que me gusta mucho de AOO, es que muchas de las acciones que hacemos por código, son susceptibles de deshacerse de forma normal con la barra de herramientas o con CTRL+Z, el borrado de hojas es una de ellas, compruébalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(&amp;#039;Hoja3&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto no puedes borrar una hoja que no exista, así que verifícalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes borrar la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(activa.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior hasta que no quede ni una, claro, no te dejara por que un documento de hoja de calculo por lo menos debe de tener una hoja, para evitar el error que te da al tratar de borrar la ultima hoja, valida que siempre quede más de una.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;borrame&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and hojas.getCount() &amp;gt; 1:&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;La hoja no existe o solo queda una&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
Para mover hojas usamos el método &amp;#039;&amp;#039;&amp;#039;moveByName(NombreHoja, PosicionNueva)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;NombreHoja&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; tiene que ser el nombre de una hoja existente. En el siguiente ejemplo movemos la hoja al inicio.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, la movemos al final.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, hojas.getCount())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos  a hacer algo muy divertido, como ya sabemos obtener los nombres e índices de cada hoja, y ahora hemos aprendido a mover hojas, hagamos una macro que nos ordene alfabéticamente nuestras hojas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = sorted(hojas.getElementNames())&lt;br /&gt;
    for i,v in enumerate(nombres):&lt;br /&gt;
        hojas.moveByName(v, i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
Para copiar hojas usamos el método &amp;#039;&amp;#039;&amp;#039;copyByName(NombreHoja, NombreNuevo, Posicion)&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.copyByName(&amp;#039;Hoja2&amp;#039;, &amp;#039;Nueva hoja2&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto el nombre de la hoja a copiar debe de existir y el nombre nuevo de la hoja no debe existir, lo mejor, es evaluarlo antes.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Datos&amp;#039;&lt;br /&gt;
    nombre_nuevo = &amp;#039;Datos nuevos&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and not hojas.hasByName(nombre_nuevo):&lt;br /&gt;
        hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se copio la hoja&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos intentar copiar una hoja y asegurarnos de que el nombre no exista, tomando como base el nombre actual de la hoja, por ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = doc.getCurrentController().getActiveSheet().getName()&lt;br /&gt;
    co1 = 1&lt;br /&gt;
    nombre_nuevo = &amp;#039;%s_%s&amp;#039; % (nombre, co1)&lt;br /&gt;
    while hojas.hasByName(nombre_nuevo):&lt;br /&gt;
        co1 += 1&lt;br /&gt;
        nombre_nuevo = &amp;#039;%s_%s&amp;#039; % (nombre, co1)&lt;br /&gt;
    hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())&lt;br /&gt;
    hoja = hojas.getByName(nombre_nuevo)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(hoja)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
Para renombrar hojas usamos el método &amp;#039;&amp;#039;&amp;#039;setName(NuevoNombre)&amp;#039;&amp;#039;&amp;#039;, de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.getByName(&amp;#039;Hola&amp;#039;).setName(&amp;#039;Prueba&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También puedes usar el índice para referirte a la hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.getByIndex(0).setName(&amp;#039;Prueba&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es recomendable validar que la hoja a renombrar exista y que el nuevo nombre no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    actual = &amp;#039;Resumen&amp;#039;&lt;br /&gt;
    nuevo = &amp;#039;Terminado&amp;#039;&lt;br /&gt;
    # Validamos que la hoja exista y el nuevo nombre no&lt;br /&gt;
    if hojas.hasByName(actual) and not hojas.hasByName(nuevo):&lt;br /&gt;
        hojas.getByName(actual).setName(nuevo)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No es posible renombrar la hoja&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo para divertirnos, cambiamos los nombres de las hojas por números.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(i+1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora por letras, el código siguiente podría fallar en algunas circunstancias, tu tarea es decirnos ¿porqué? y corregirlo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(chr(i+65))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O los meses del año:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import datetime&lt;br /&gt;
import locale&lt;br /&gt;
locale.setlocale(locale.LC_ALL, &amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(datetime.date(2013, i+1, 1).strftime(&amp;#039;%B&amp;#039;))&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que hacemos uso de dos nuevas librerias de Python, &amp;#039;&amp;#039;&amp;#039;datetime&amp;#039;&amp;#039;&amp;#039; que tiene muchas utiles funciones para trabajar con fechas y tiempo, y &amp;#039;&amp;#039;&amp;#039;locale&amp;#039;&amp;#039;&amp;#039; para que los meses nos salgan en español.&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
Mostrar y ocultar hojas es muy sencillo, solo hay que establecer su propiedad &amp;#039;&amp;#039;&amp;#039;IsVisible&amp;#039;&amp;#039;&amp;#039; en verdadero (True) o falso (False) según se requiera de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa.IsVisible = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La macro anterior te ocultara la hoja activa, si la ejecutas varias veces te ira ocultando tus hojas hasta que solo quede una, si solo hay una no te dará error, pero la dejará visible por que, como sabes, tiene que haber al menos una hoja visible en un documento de Calc. Si ocultas una hoja, esta no cambia de índice por lo que puedes usar el mismo para acceder a ella, aunque este oculta, la siguiente macro alterna entre mostrar y ocultar la segunda hoja del documento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hoja = doc.getSheets().getByIndex(1)&lt;br /&gt;
    hoja.IsVisible = not hoja.IsVisible&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(hoja)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como ya habrás intuido, para mostrar una hoja oculta simplemente hay que establecer esta propiedad en verdadero (True). El siguiente código te oculta todas las hojas, excepto la hoja activa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet().getRangeAddress().Sheet&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        if i != activa:&lt;br /&gt;
            hojas.getByIndex(i).IsVisible = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tu tarea es hacer la función inversa, muestra todas las hojas ocultas.&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
Para terminar este capítulo, veamos como proteger una hoja, es decir, establecer una contraseña para evitar modificaciones a la misma, además, recuerda que para que la protección de celdas individuales sea efectiva, la hoja debe estar protegida. Para proteger una hoja, usamos el método &amp;#039;&amp;#039;&amp;#039;protect(contraseña)&amp;#039;&amp;#039;&amp;#039;, pasándole como argumento, la contraseña que queremos establecer, por supuesto, puedes pasarle una contraseña vacía, con lo que la hoja no estará muy protegida que digamos, pero créeme, muchos usuarios no saben desproteger una hoja, aun sin contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa.protect(&amp;#039;letmein&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y para desproteger, usamos el método &amp;#039;&amp;#039;&amp;#039;unprotect(contraseña)&amp;#039;&amp;#039;&amp;#039;, si la hoja tiene contraseña hay que pasársela como argumento, si no es correcta, el método no te devolverá ningún error como en la interfaz del usuario que te avisa que la contraseña es incorrecta, para saber si tuvo éxito o no la desprotección, hay que verificar la propiedad &amp;#039;&amp;#039;&amp;#039;isProtected&amp;#039;&amp;#039;&amp;#039;, si es verdadera (True) la hoja sigue protegida, si es falsa (False), la hoja esta desprotegida.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    if activa.isProtected():&lt;br /&gt;
        msgbox(&amp;#039;Hoja protegida, se va a desproteger&amp;#039;)&lt;br /&gt;
        activa.unprotect(&amp;#039;letmein&amp;#039;)&lt;br /&gt;
        if activa.isProtected():&lt;br /&gt;
            msgbox(&amp;#039;Contraseña incorrecta&amp;#039;)&lt;br /&gt;
        else:&lt;br /&gt;
            msgbox(&amp;#039;Hoja desprotegida correctamente&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;La hoja no esta protegida&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como comentarios finales, si intentas proteger una hoja que ya tiene contraseña, no obtendrás ningún error, pero la hoja permanecerá con la contraseña original, para cambiarla, primero tienes que desprotegerla y después cambiarla. Cuando proteges una hoja e intentas hacer modificaciones a esta, por ejemplo, escribir en una celda, tampoco retornará ningún error, pero no será efectiva la modificación.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{ES/Foro|macros}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219956</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219956"/>
		<updated>2013-05-10T04:46:53Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Ocultando y mostrando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Otra hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, hojas.getCount())&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por &amp;#039;&amp;#039;&amp;#039;getCount()&amp;#039;&amp;#039;&amp;#039; pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    indice = activa.getRangeAddress().Sheet &lt;br /&gt;
    msgbox(u&amp;#039;El índice de la hoja activa es: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir en una submacro. Nota como estamos estableciendo un &amp;#039;&amp;#039;&amp;#039;valor por default&amp;#039;&amp;#039;&amp;#039; para el ultimo argumento que será la posición deseada para la nueva hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nueva_hoja(doc, nombre, pos=0):&lt;br /&gt;
    hojas = doc.getSheets() &lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
        indice = activa.getRangeAddress().Sheet&lt;br /&gt;
        if pos == 1:&lt;br /&gt;
            pos = indice&lt;br /&gt;
        elif pos == 2:&lt;br /&gt;
            pos = indice + 1&lt;br /&gt;
        elif pos &amp;gt; 2:&lt;br /&gt;
            pos = hojas.getCount()&lt;br /&gt;
        hojas.insertNewByName(nombre, pos)&lt;br /&gt;
        return hojas.getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora ya podemos insertar una nueva hoja en la posición que sea.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al inicio&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Antes de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 1)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Despues de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 2)&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al final&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 3)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
Para borrar hojas, usamos el método &amp;#039;&amp;#039;&amp;#039;removeByName(Nombre)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Nombre&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; es el nombre de la hoja que queremos borrar, no esta de más recomendarte usar con cuidado el borrado de hojas, aunque algo que me gusta mucho de AOO, es que muchas de las acciones que hacemos por código, son susceptibles de deshacerse de forma normal con la barra de herramientas o con CTRL+Z, el borrado de hojas es una de ellas, compruébalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(&amp;#039;Hoja3&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto no puedes borrar una hoja que no exista, así que verifícalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes borrar la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(activa.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior hasta que no quede ni una, claro, no te dejara por que un documento de hoja de calculo por lo menos debe de tener una hoja, para evitar el error que te da al tratar de borrar la ultima hoja, valida que siempre quede más de una.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;borrame&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and hojas.getCount() &amp;gt; 1:&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;La hoja no existe o solo queda una&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
Para mover hojas usamos el método &amp;#039;&amp;#039;&amp;#039;moveByName(NombreHoja, PosicionNueva)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;NombreHoja&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; tiene que ser el nombre de una hoja existente. En el siguiente ejemplo movemos la hoja al inicio.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, la movemos al final.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, hojas.getCount())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos  a hacer algo muy divertido, como ya sabemos obtener los nombres e índices de cada hoja, y ahora hemos aprendido a mover hojas, hagamos una macro que nos ordene alfabéticamente nuestras hojas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = sorted(hojas.getElementNames())&lt;br /&gt;
    for i,v in enumerate(nombres):&lt;br /&gt;
        hojas.moveByName(v, i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
Para copiar hojas usamos el método &amp;#039;&amp;#039;&amp;#039;copyByName(NombreHoja, NombreNuevo, Posicion)&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.copyByName(&amp;#039;Hoja2&amp;#039;, &amp;#039;Nueva hoja2&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto el nombre de la hoja a copiar debe de existir y el nombre nuevo de la hoja no debe existir, lo mejor, es evaluarlo antes.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Datos&amp;#039;&lt;br /&gt;
    nombre_nuevo = &amp;#039;Datos nuevos&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and not hojas.hasByName(nombre_nuevo):&lt;br /&gt;
        hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se copio la hoja&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos intentar copiar una hoja y asegurarnos de que el nombre no exista, tomando como base el nombre actual de la hoja, por ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = doc.getCurrentController().getActiveSheet().getName()&lt;br /&gt;
    co1 = 1&lt;br /&gt;
    nombre_nuevo = &amp;#039;%s_%s&amp;#039; % (nombre, co1)&lt;br /&gt;
    while hojas.hasByName(nombre_nuevo):&lt;br /&gt;
        co1 += 1&lt;br /&gt;
        nombre_nuevo = &amp;#039;%s_%s&amp;#039; % (nombre, co1)&lt;br /&gt;
    hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())&lt;br /&gt;
    hoja = hojas.getByName(nombre_nuevo)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(hoja)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
Para renombrar hojas usamos el método &amp;#039;&amp;#039;&amp;#039;setName(NuevoNombre)&amp;#039;&amp;#039;&amp;#039;, de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.getByName(&amp;#039;Hola&amp;#039;).setName(&amp;#039;Prueba&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También puedes usar el índice para referirte a la hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.getByIndex(0).setName(&amp;#039;Prueba&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es recomendable validar que la hoja a renombrar exista y que el nuevo nombre no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    actual = &amp;#039;Resumen&amp;#039;&lt;br /&gt;
    nuevo = &amp;#039;Terminado&amp;#039;&lt;br /&gt;
    # Validamos que la hoja exista y el nuevo nombre no&lt;br /&gt;
    if hojas.hasByName(actual) and not hojas.hasByName(nuevo):&lt;br /&gt;
        hojas.getByName(actual).setName(nuevo)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No es posible renombrar la hoja&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo para divertirnos, cambiamos los nombres de las hojas por números.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(i+1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora por letras, el código siguiente podría fallar en algunas circunstancias, tu tarea es decirnos ¿porqué? y corregirlo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(chr(i+65))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O los meses del año:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import datetime&lt;br /&gt;
import locale&lt;br /&gt;
locale.setlocale(locale.LC_ALL, &amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(datetime.date(2013, i+1, 1).strftime(&amp;#039;%B&amp;#039;))&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que hacemos uso de dos nuevas librerias de Python, &amp;#039;&amp;#039;&amp;#039;datetime&amp;#039;&amp;#039;&amp;#039; que tiene muchas utiles funciones para trabajar con fechas y tiempo, y &amp;#039;&amp;#039;&amp;#039;locale&amp;#039;&amp;#039;&amp;#039; para que los meses nos salgan en español.&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
Mostrar y ocultar hojas es muy sencillo, solo hay que establecer su propiedad &amp;#039;&amp;#039;&amp;#039;IsVisible&amp;#039;&amp;#039;&amp;#039; en verdadero (True) o falso (False) según se requiera de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    activa.IsVisible = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La macro anterior te ocultara la hoja activa, si la ejecutas varias veces te ira ocultando tus hojas hasta que solo quede una, si solo hay una no te dará error, pero la dejará visible por que, como sabes, tiene que haber al menos una hoja visible en un documento de Calc. Si ocultas una hoja, esta no cambia de índice por lo que puedes usar el mismo para acceder a ella, aunque este oculta, la siguiente macro alterna entre mostrar y ocultar la segunda hoja del documento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hoja = doc.getSheets().getByIndex(1)&lt;br /&gt;
    hoja.IsVisible = not hoja.IsVisible&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(hoja)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como ya habrás intuido, para mostrar una hoja oculta simplemente hay que establecer esta propiedad en verdadero (True). El siguiente código te oculta todas las hojas, excepto la hoja activa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    &lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet().getRangeAddress().Sheet&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        if i != activa:&lt;br /&gt;
            hojas.getByIndex(i).IsVisible = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tu tarea es hacer la función inversa, muestra todas las hojas ocultas.&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219955</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219955"/>
		<updated>2013-05-10T04:30:58Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Renombrando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Otra hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, hojas.getCount())&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por &amp;#039;&amp;#039;&amp;#039;getCount()&amp;#039;&amp;#039;&amp;#039; pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    indice = activa.getRangeAddress().Sheet &lt;br /&gt;
    msgbox(u&amp;#039;El índice de la hoja activa es: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir en una submacro. Nota como estamos estableciendo un &amp;#039;&amp;#039;&amp;#039;valor por default&amp;#039;&amp;#039;&amp;#039; para el ultimo argumento que será la posición deseada para la nueva hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nueva_hoja(doc, nombre, pos=0):&lt;br /&gt;
    hojas = doc.getSheets() &lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
        indice = activa.getRangeAddress().Sheet&lt;br /&gt;
        if pos == 1:&lt;br /&gt;
            pos = indice&lt;br /&gt;
        elif pos == 2:&lt;br /&gt;
            pos = indice + 1&lt;br /&gt;
        elif pos &amp;gt; 2:&lt;br /&gt;
            pos = hojas.getCount()&lt;br /&gt;
        hojas.insertNewByName(nombre, pos)&lt;br /&gt;
        return hojas.getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora ya podemos insertar una nueva hoja en la posición que sea.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al inicio&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Antes de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 1)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Despues de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 2)&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al final&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 3)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
Para borrar hojas, usamos el método &amp;#039;&amp;#039;&amp;#039;removeByName(Nombre)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Nombre&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; es el nombre de la hoja que queremos borrar, no esta de más recomendarte usar con cuidado el borrado de hojas, aunque algo que me gusta mucho de AOO, es que muchas de las acciones que hacemos por código, son susceptibles de deshacerse de forma normal con la barra de herramientas o con CTRL+Z, el borrado de hojas es una de ellas, compruébalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(&amp;#039;Hoja3&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto no puedes borrar una hoja que no exista, así que verifícalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes borrar la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(activa.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior hasta que no quede ni una, claro, no te dejara por que un documento de hoja de calculo por lo menos debe de tener una hoja, para evitar el error que te da al tratar de borrar la ultima hoja, valida que siempre quede más de una.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;borrame&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and hojas.getCount() &amp;gt; 1:&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;La hoja no existe o solo queda una&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
Para mover hojas usamos el método &amp;#039;&amp;#039;&amp;#039;moveByName(NombreHoja, PosicionNueva)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;NombreHoja&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; tiene que ser el nombre de una hoja existente. En el siguiente ejemplo movemos la hoja al inicio.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, la movemos al final.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, hojas.getCount())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos  a hacer algo muy divertido, como ya sabemos obtener los nombres e índices de cada hoja, y ahora hemos aprendido a mover hojas, hagamos una macro que nos ordene alfabéticamente nuestras hojas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = sorted(hojas.getElementNames())&lt;br /&gt;
    for i,v in enumerate(nombres):&lt;br /&gt;
        hojas.moveByName(v, i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
Para copiar hojas usamos el método &amp;#039;&amp;#039;&amp;#039;copyByName(NombreHoja, NombreNuevo, Posicion)&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.copyByName(&amp;#039;Hoja2&amp;#039;, &amp;#039;Nueva hoja2&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto el nombre de la hoja a copiar debe de existir y el nombre nuevo de la hoja no debe existir, lo mejor, es evaluarlo antes.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Datos&amp;#039;&lt;br /&gt;
    nombre_nuevo = &amp;#039;Datos nuevos&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and not hojas.hasByName(nombre_nuevo):&lt;br /&gt;
        hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se copio la hoja&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos intentar copiar una hoja y asegurarnos de que el nombre no exista, tomando como base el nombre actual de la hoja, por ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = doc.getCurrentController().getActiveSheet().getName()&lt;br /&gt;
    co1 = 1&lt;br /&gt;
    nombre_nuevo = &amp;#039;%s_%s&amp;#039; % (nombre, co1)&lt;br /&gt;
    while hojas.hasByName(nombre_nuevo):&lt;br /&gt;
        co1 += 1&lt;br /&gt;
        nombre_nuevo = &amp;#039;%s_%s&amp;#039; % (nombre, co1)&lt;br /&gt;
    hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())&lt;br /&gt;
    hoja = hojas.getByName(nombre_nuevo)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(hoja)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
Para renombrar hojas usamos el método &amp;#039;&amp;#039;&amp;#039;setName(NuevoNombre)&amp;#039;&amp;#039;&amp;#039;, de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.getByName(&amp;#039;Hola&amp;#039;).setName(&amp;#039;Prueba&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También puedes usar el índice para referirte a la hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.getByIndex(0).setName(&amp;#039;Prueba&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es recomendable validar que la hoja a renombrar exista y que el nuevo nombre no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    actual = &amp;#039;Resumen&amp;#039;&lt;br /&gt;
    nuevo = &amp;#039;Terminado&amp;#039;&lt;br /&gt;
    # Validamos que la hoja exista y el nuevo nombre no&lt;br /&gt;
    if hojas.hasByName(actual) and not hojas.hasByName(nuevo):&lt;br /&gt;
        hojas.getByName(actual).setName(nuevo)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No es posible renombrar la hoja&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo para divertirnos, cambiamos los nombres de las hojas por números.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(i+1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora por letras, el código siguiente podría fallar en algunas circunstancias, tu tarea es decirnos ¿porqué? y corregirlo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(chr(i+65))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O los meses del año:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import datetime&lt;br /&gt;
import locale&lt;br /&gt;
locale.setlocale(locale.LC_ALL, &amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        hojas.getByIndex(i).setName(datetime.date(2013, i+1, 1).strftime(&amp;#039;%B&amp;#039;))&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que hacemos uso de dos nuevas librerias de Python, &amp;#039;&amp;#039;&amp;#039;datetime&amp;#039;&amp;#039;&amp;#039; que tiene muchas utiles funciones para trabajar con fechas y tiempo, y &amp;#039;&amp;#039;&amp;#039;locale&amp;#039;&amp;#039;&amp;#039; para que los meses nos salgan en español.&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices&amp;diff=219951</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices&amp;diff=219951"/>
		<updated>2013-05-09T15:43:03Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE: Apéndices}}&lt;br /&gt;
== Obtener lista de filtros soportados por AOO ==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def obtener_filtros():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ff = sm.createInstance(&amp;#039;com.sun.star.document.FilterFactory&amp;#039;)&lt;br /&gt;
    filtros = ff.getElementNames()&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    doc.getText().setString(&amp;#039;\n&amp;#039;.join(filtros))&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{ES/Foro|macros}}&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc&amp;diff=219950</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc&amp;diff=219950"/>
		<updated>2013-05-09T15:42:22Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE: Trabajando con Calc}}&lt;br /&gt;
En todos los temas de esta sección, asumimos que el lector ha leído y comprendido, todos los temas introductorios a este.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas|Trabajando con hojas]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos|Referencia a rangos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ManipulandoRangos|Manipulando rangos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ManipulandoDatos|Manipulando datos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/DandoFormato|Dando formato]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/Imprimiendo|Imprimiendo]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/RangosDeDatos|Rangos de datos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/BasesDeDatos|Bases de datos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/GraficandoDatos|Graficando datos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConElementosGraficos|Trabajando con elementos gráficos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ConfiguracionGlobalCalc|Configuración global de Calc]]&lt;br /&gt;
&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ES/Foro|macros}}&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=219949</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=219949"/>
		<updated>2013-05-09T15:40:58Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con Apache OpenOffice}}&lt;br /&gt;
&lt;br /&gt;
== Conceptos iniciales==&lt;br /&gt;
&lt;br /&gt;
Este es el tema más importante para crear macros, de forma sencilla, pero se ven las bases para trabajar con todo AOO, por eso es importante no avanzar en estas notas, sin antes haber comprendido a cabalidad los temas presentes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;UNO&amp;#039;&amp;#039;&amp;#039; (Universal Network Objects), es la especificación que da acceso a todos los objetos de Apache OpenOffice. Todo lo que quieras saber de esta especificación, lo puedes encontrar en la [[http://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide Guía del desarrollador]] (en ingles).&lt;br /&gt;
&lt;br /&gt;
El &amp;#039;&amp;#039;&amp;#039;API&amp;#039;&amp;#039;&amp;#039; (Application Programer Interface) de Apache OpenOffice proporciona el acceso a toda la funcionalidad de AOO, independientemente del lenguaje. Todo el API de AOO esta en &amp;lt;idl&amp;gt;com.sun.star.module-ix&amp;lt;/idl&amp;gt; (solo ingles).&lt;br /&gt;
&lt;br /&gt;
La comunicación entre objetos UNO se basa en &amp;#039;&amp;#039;&amp;#039;interfaces&amp;#039;&amp;#039;&amp;#039; de objeto.  Las interfaces pueden ser vistos desde el exterior o el interior de un objeto y proporcionan formas de ver o manipular el objeto.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;servicios&amp;#039;&amp;#039;&amp;#039; son agrupaciones lógicas de interfaces, son la forma en que un mismo objeto pueda ofrecer la funcionalidad de varias interfaces.&lt;br /&gt;
&lt;br /&gt;
Los servicios se pueden implementar en librerías compartidas llamadas &amp;#039;&amp;#039;&amp;#039;componentes UNO&amp;#039;&amp;#039;&amp;#039;, con Python podemos crear componentes nuevos y generalmente el usuario final las recibe como una extensión OXT.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;modulos&amp;#039;&amp;#039;&amp;#039; pueden agrupar submodulos, servicios, excepciones, constantes, enumeraciones, etc, se utilizan para especificar bloques coherentes en la API, esto permite tener un API bien estructurada.&lt;br /&gt;
&lt;br /&gt;
== Creando servicios ==&lt;br /&gt;
Para crear un servicio, usamos la &amp;#039;&amp;#039;&amp;#039;fabrica de servicios&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;), una interfaz especial para crear nuevos servicios, pero para llegar a ella, tenemos que hacerlo a traves de la interfaz &amp;#039;&amp;#039;&amp;#039;ComponentContext&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;), como puedes verlo en la siguiente imagen. &lt;br /&gt;
[[Image:UseServices1.png|none|thumb|400px|ComponentContext y ServiceManager]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En pyUNO tenemos dos formas de acceder a esta interfaz, las dos son equivalentes por lo que puedes usar la que prefieras. En la introducción a Python se mencionó que la mayoría de sus herramientas están disponibles en librerias, estás librerias tienen que importarse &amp;#039;&amp;#039;&amp;#039;antes&amp;#039;&amp;#039;&amp;#039; de poder usarse, en nuestro caso importaremos la librería &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; que nos da acceso (entre otras cosas) al contexto de ejecución de AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx1 = XSCRIPTCONTEXT.getComponentContext()&lt;br /&gt;
    ctx2 = uno.getComponentContext()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si te gusta investigar, busca el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; en la carpeta de instalación de AOO, ahí puedes ver de donde sale XSCRIPTCONTEXT}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, podemos acceder a la fábrica de servicios con el &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿como sabemos que este &amp;#039;&amp;#039;&amp;#039;objeto (ComponentContext)&amp;#039;&amp;#039;&amp;#039; tiene este &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;? porque lo estamos demostrando, si, también por eso, pero también porque puedes ver su documentación (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;) en el API de AOO, pero más importante aún, porque podemos hacer que el mismo objeto te diga todo lo que sabe hacer. Para ello haremos uso de una magnifica extensión que te tiene que acompañar el resto de tus días como programador de macros Python, nos referimos a [http://extensions.services.openoffice.org/project/MRI MRI]. Instala (tal vez tengas que reiniciar AOO para poder usarla) y la probamos de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    # llamamos a la extensión MRI y le pasamos el objeto a inspeccionar&lt;br /&gt;
    mri(ctx)&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def mri(target):&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()    &lt;br /&gt;
    mri = sm.createInstanceWithContext(&amp;#039;mytools.Mri&amp;#039;, ctx)&lt;br /&gt;
    mri.inspect(target)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa en la imágen siguiente, como hemos seleccionado los métodos del objeto y nos lista todos los que tenga, hemos remarcado el que por ahora nos interesa &amp;#039;&amp;#039;&amp;#039;getServiceManager()&amp;#039;&amp;#039;&amp;#039;, observa al final de la línea que efectivamente este método nos devuelve una &amp;#039;&amp;#039;&amp;#039;instancia&amp;#039;&amp;#039;&amp;#039; de la interfaz &amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;. &lt;br /&gt;
[[Image:Py_img_0006.png|none|thumb|500px|Usando la extensión MRI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gran ventaja de usar esta extensión (que por cierto esta hecha en Python), es que siempre te devolverá la información directamente del objeto, a esto se le llama &amp;#039;&amp;#039;&amp;#039;instrospección&amp;#039;&amp;#039;&amp;#039;. Acostumbrate a usarla.&lt;br /&gt;
&lt;br /&gt;
Ahora si, ya podemos crear una instancia de cualquier servicio o interfaz disponible en AOO, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existe una forma alternativa de crear este servicio, usando &amp;#039;&amp;#039;&amp;#039;XSCRIPTCONTEXT&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    XSCRIPTCONTEXT.getDesktop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si vuelves a mirar el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; notaras que usa el mismo método para instanciar este servicio}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y para que sirve este servicio? Entre otras cosas para crear nuevos documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
nuevo = desktop.loadComponentFromURL(&amp;#039;private:factory/scalc&amp;#039;, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos a detalle este método y otros relacionados con los documentos de AOO. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; es la instancia de la administración central para todas las aplicaciones AOO.  Todas las ventanas de la aplicación AOO se organizan en una jerarquía de marcos que contienen componentes visibles.  &lt;br /&gt;
&lt;br /&gt;
[[Image:DesktopOverview.png|none|thumb|400px|Desktop administra los componentes y marcos.]]&lt;br /&gt;
&lt;br /&gt;
Para los fines de crear macros es suficiente que recuerdes que, Desktop es el marco raíz de toda la jerarquía de documentos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para crear la instancia del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; usamos un contexto y usamos el método &amp;#039;&amp;#039;&amp;#039;createInstanceWithContext&amp;#039;&amp;#039;&amp;#039;. Otros servicios no requieren de contexto para ser instanciados y usados, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.util.PathSettings&amp;lt;/idl&amp;gt; que nos sirve para obtener las rutas de trabajo actuales en AOO, para estos casos usamos el método &amp;#039;&amp;#039;&amp;#039;createInstance&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    rutas = sm.createInstance(&amp;#039;com.sun.star.util.PathSettings&amp;#039;)&lt;br /&gt;
    # mostramos la ruta de trabajo del usuario&lt;br /&gt;
    print (rutas.Work)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora que ya sabemos instanciar servicios, veamos de nuevo nuestra macro para mostrar un mensaje en pantalla y analicemosla línea a línea para que veas que sencillo es, además, nos servirá para ver otros detalles al programar con Python en AOO. La macro tiene ahora unos ligeros cambios para que trabaje mejor y para explicar algunas cosas, veamos cuales.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la primer línea &amp;#039;&amp;#039;&amp;#039;declaramos&amp;#039;&amp;#039;&amp;#039; nuestra macro, su nombre y los argumentos que necesita, en este caso solo uno &amp;#039;&amp;#039;&amp;#039;message&amp;#039;&amp;#039;&amp;#039; que será el mensaje a mostrar.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la segunda línea, estamos importando (&amp;#039;&amp;#039;&amp;#039;import&amp;#039;&amp;#039;&amp;#039;) la estructura &amp;#039;&amp;#039;&amp;#039;Rectangle&amp;#039;&amp;#039;&amp;#039; desde (&amp;#039;&amp;#039;&amp;#039;from&amp;#039;&amp;#039;&amp;#039;) el modulo &amp;lt;idl&amp;gt;com.sun.star.awt.module-ix&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Las estructuras son un conjunto de valores relacionados, valores que pueden ser de tipos diferentes, pero que son mostrados como una unidad lógica, por ejemplo, la estructura &amp;lt;idl&amp;gt;com.sun.star.awt.Rectangle&amp;lt;/idl&amp;gt; hace referencia a un área rectangular estableciendo su posición y tamaño, en este caso, solo sirve para cumplir los argumentos del método para mostrar nuestro mensaje.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la tercer línea, hacemos otra importación, pero esta vez la hacemos de una constante, específicamente la constante para mostrar el botón &amp;#039;&amp;#039;&amp;#039;Aceptar&amp;#039;&amp;#039;&amp;#039; (OK), estas constantes las puedes ver aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.MessageBoxButtons&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La cuarta línea esta vacía solo para separar la parte de importacion con el resto del código. En la siguiente línea hacemos una validación del argumento pasado a nuestra macro, si el argumento &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; es una instancia de la clase &amp;#039;&amp;#039;&amp;#039;unicode&amp;#039;&amp;#039;&amp;#039; o de la clase &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, entonces la convertimos a &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, esto nos permite pasar a nuestra macro, listas, tuplas, diccionarios y practicamente cualquier objeto, del cual, podremos ver su representación en texto, muchas veces, con información bastante útil.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea ya la hemos estudiado, creamos una instancia del contexto donde se ejecuta AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea también ya la hemos estudiado, creamos una instancia de la fabrica de servicios, una de las instancias más importantes y que usaras constantemente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la siguiente línea creamos una instancia con contexto de un nuevo servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt;, este servicio sirve, entre otras muchas cosas para crear ventanas y mensaje de texto, como el de nuestra macro.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la penultima línea, usamos el método &amp;#039;&amp;#039;&amp;#039;createMessageBox&amp;#039;&amp;#039;&amp;#039; del servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt; para crear nuestro cuadro de mensaje, todos los argumentos de este método puedes verlo aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.XMessageBoxFactory&amp;lt;/idl&amp;gt;, pero aquí los explicamos uno a uno.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Aunque veas muchas líneas, el interpete la considera una sola, esto se logra al estar todos los argumentos entre paréntesis.&lt;br /&gt;
* El primer argumento es la ventana padre (&amp;#039;&amp;#039;&amp;#039;parent&amp;#039;&amp;#039;&amp;#039;) donde será mostrado el cuadro de mensaje, observa como usamos de nuevo el servicio &amp;#039;&amp;#039;&amp;#039;toolkit&amp;#039;&amp;#039;&amp;#039; para recuperar (&amp;#039;&amp;#039;&amp;#039;getDesktopWindow&amp;#039;&amp;#039;&amp;#039;) la ventana padre de AOO.&lt;br /&gt;
* El segundo argumento es el área rectangular del cuadro de mensaje, observa los dos paréntesis al final del nombre de la estructura, son necesarios para inicializarla.&lt;br /&gt;
* El tercer argumento es el tipo de mensaje, dependiendo de este argumento se muestra el icono correspondiente, los valores permitidos son: &amp;#039;&amp;#039;&amp;#039;infobox, warningbox, errorbox, querybox y messbox&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;infobox&amp;#039;&amp;#039;&amp;#039;, el siguiente argumento es ignorado.&lt;br /&gt;
* El cuarto argumento sirve para mostrar botones de comando diferentes, como: &amp;#039;&amp;#039;&amp;#039;Si, No, Cancelar&amp;#039;&amp;#039;&amp;#039;, etc, que están establecidos en las constantes vistas más arriba.&lt;br /&gt;
* El quinto argumento es el título del cuadro de mensaje.&lt;br /&gt;
* Y por ultimo, el mensaje a mostrar, el cual ya validamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la ultima línea al mismo tiempo que mostramos (&amp;#039;&amp;#039;&amp;#039;ejecute&amp;#039;&amp;#039;&amp;#039;) estamos retornando el cuadro de mensaje, esto nos da la posibilidad de capturar el botón al que le haya dado click el usuario, lo cual, veremos más adelante. Todas las macros retornan un valor, aun y cuando este sea un valor vacío (None).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, los servicio los instanciamos y las estructuras y constantes las importamos, y el punto más importante; &amp;#039;&amp;#039;&amp;#039;acostúmbrate a usar, manejar y dominar, la extensión MRI&amp;#039;&amp;#039;&amp;#039;, ella te dice todo lo necesario para trabajar con los objetos UNO de AOO, los demás, es sencillo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== El documento activo ==&lt;br /&gt;
&lt;br /&gt;
Tenemos dos formas de acceder al documento activo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc1 = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
    doc2 = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc1.getIdentifier())&lt;br /&gt;
    print (doc2.getIdentifier())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note| Mira en el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; la forma en que trabaja el método &amp;#039;&amp;#039;&amp;#039;getDocument&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si seguiste nuestra recomendación de asignar la macro de pruebas a una combinación de teclas disponible en todo AOO, prueba a abrir cada uno de los tipos de documentos que puedes ver en el menú &amp;#039;&amp;#039;&amp;#039;Archivo-&amp;gt;Nuevo-&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
[[Image:Py_img_0007.png|none|thumb|500px|Tipos de documentos en AOO]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y a ejecutar la siguiente macro, teniendo como documento activo cada uno de ellos, es decir, activas uno y ejecutas la macro, activas otro y vuelves a llamar a la macro y así sucesivamente con todos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getIdentifier())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los mensajes devueltos en cada documento, son bastante ilustrativos de que &amp;#039;&amp;#039;&amp;#039;tipo de documento&amp;#039;&amp;#039;&amp;#039; se trata. Pero si probaste con todos, habrás notado que con la base de datos nos devuelve un error, si no lo has probado hazlo ahora. Para resolver este caso tenemos varias posibilidades, la primera es controlar la excepción como ya aprendimos en la introducción a Python.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿estamos realmente seguros que ese es el error?, es mejor especificarlo y asegurarnos de que este es el error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tenemos otra alternativa donde no usamos controlador de excepciónes, si no una función que nos dice si un cierto atributo lo posee o no un objeto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    if hasattr(doc, &amp;#039;getIdentifier&amp;#039;):&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Sin atributo getIdentifier&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es mucho mejor esta segunda opción. Aun así, no podemos estar 100% seguros de que cuando no la tenga, el documento sea una base de datos, simplemente estamos excluyendo la posibilidad pero no lo estamos asegurando, probemos con otra propiedad.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getImplementationName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mucho mejor, ahora ya no tenemos errores, pero si probaste de nuevo con todos los tipos de documentos, habrás notado que con &amp;#039;&amp;#039;&amp;#039;Impres&amp;#039;&amp;#039;&amp;#039; y con &amp;#039;&amp;#039;&amp;#039;Draw&amp;#039;&amp;#039;&amp;#039; obtenemos el mismo resultado, por lo que no tenemos la certeza de que tipo de documento es, por lo que descartamos esta propiedad para nuestra finalidad que es identificar fehacientemente cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
Ya vimos que cada objeto UNO soporta diferentes servicios e interfaces, asì que cada documento de AOO (&amp;#039;&amp;#039;&amp;#039;que son objetos&amp;#039;&amp;#039;&amp;#039;) soportan diferentes servicios, algunos son iguales, es decir, comúnes a todos, pero algunos pueden ser únicos para cada documento. Ya vimos como saber si un documento soporta una propiedad, pero para saber si soporta un servicio completo, cambiamos de método, ahora usamos &amp;#039;&amp;#039;&amp;#039;supportsService&amp;#039;&amp;#039;&amp;#039; que nos devuelve falso o verdadero según soporte o no el nombre del servicio pasado como argumento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    res = doc.supportsService(&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;)&lt;br /&gt;
    mensaje = u&amp;#039;No soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    if res:&lt;br /&gt;
        mensaje = u&amp;#039;Soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    print(mensaje)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y mejor aun, podemos saber todos los servicios que soporta un objeto con el método &amp;#039;&amp;#039;&amp;#039;getSupportedServiceNames&amp;#039;&amp;#039;&amp;#039; que nos devuelve una tupla con todos sus nombres.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    servicios = doc.getSupportedServiceNames()&lt;br /&gt;
    &lt;br /&gt;
    print(servicios)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Te queda de tarea probar esta macro en cada uno de los documentos abiertos, incluso puedes probar también el IDE para AOOBasic que incorpora AOO y determinar que servicio usar para diferenciar sin duda cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
== Los documentos abiertos ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todos los documentos abiertos en la sesión de AOO, usamos el método &amp;#039;&amp;#039;&amp;#039;getComponents&amp;#039;&amp;#039;&amp;#039; del objeto &amp;#039;&amp;#039;&amp;#039;Desktop&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;MRI&amp;#039;&amp;#039;&amp;#039;, notarás que este método nos devuelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta interfaz (&amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;) tiene un solo método llamado &amp;#039;&amp;#039;&amp;#039;createEnumeration&amp;#039;&amp;#039;&amp;#039; que nos duelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumeration&amp;lt;/idl&amp;gt; la cual a su vez tiene solo dos métodos, el primero para saber si tenemos más elementos en la enumeración: &amp;#039;&amp;#039;&amp;#039;hasMoreElements&amp;#039;&amp;#039;&amp;#039; y el segundo para acceder al siguiente elemento &amp;#039;&amp;#039;&amp;#039;nextElement&amp;#039;&amp;#039;&amp;#039;, veamoslo con un ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    # mientras tengamos elementos&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        # obtenemos el siguiente elemento&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # mostrámos el tipo de documento&lt;br /&gt;
        mensaje = obtener_tipo(doc)&lt;br /&gt;
        print(mensaje)&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;Calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;Writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;Impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;Draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;Base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;Math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;Basic&amp;#039;}&lt;br /&gt;
    # iteramos entre los tipos de documentos&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        # validamos si soporta el servicio&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            # devolvemos el tipo de documento&lt;br /&gt;
            return &amp;#039;Soy %s&amp;#039; % tipo[t]&lt;br /&gt;
    # si termina sin encontrar un tipo&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como usamos una macro de apoyo para saber que tipo de documento es. Una enumeración no es más que una lista de objetos y es una forma muy común y a veces la única de acceder a ciertos objetos en AOO, es importante que la recuerdes.&lt;br /&gt;
&lt;br /&gt;
== Rutas de archivos y directorios ==&lt;br /&gt;
&lt;br /&gt;
Apache OpenOffice, al ser multiplataforma, hace uso de las rutas de archivos y directorios, en el formato URL, por ejemplo.&lt;br /&gt;
&lt;br /&gt;
file:///home/usuario/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
file:///d:/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta que este formato hace uso de los caracteres 0-9, a-z y A-Z, y cualquier otro carácter será convertido y mostrado con su respectivo código, por ejemplo, los espacios los reemplazara con &amp;#039;&amp;#039;&amp;#039;%20&amp;#039;&amp;#039;&amp;#039;. Siempre que le pases una ruta de archivo a cualquier servicio de AOO, hazlo, casi como una regla, pasarle la ruta en formato Url, para ello, la libreria &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; cuenta con dos funciones muy útiles que hacen el trabajo &amp;#039;&amp;#039;&amp;#039;systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; y &amp;#039;&amp;#039;&amp;#039;fileUrlToSystemPath&amp;#039;&amp;#039;&amp;#039;, veamos como se usan.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def rutas():&lt;br /&gt;
    &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi archivo de Calc.ods&amp;quot;&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # La convertimos al formato URL&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # Regresamos al formato local&lt;br /&gt;
    ruta = uno.fileUrlToSystemPath(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Abre varios documentos existentes y ejecuta la siguiente macro desde cada uno:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def info_ruta():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
    &lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    # obtenemos la ruta en disco&lt;br /&gt;
    ruta =  doc.getURL()&lt;br /&gt;
    # obtenemos las diferentes partes de la ruta&lt;br /&gt;
    ruta, archivo = os.path.split(ruta)&lt;br /&gt;
    nombre, extension = os.path.splitext(archivo)&lt;br /&gt;
    &lt;br /&gt;
    print (ruta)&lt;br /&gt;
    print (uno.fileUrlToSystemPath(ruta))&lt;br /&gt;
    print (archivo)&lt;br /&gt;
    print (nombre)&lt;br /&gt;
    print (extension)&lt;br /&gt;
    &lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hemos importado una nueva librería de Python, &amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; que entre otras muchas cosas, nos permite obtener información de las rutas de archivos como en la macro anterior.&lt;br /&gt;
&lt;br /&gt;
En nuestros siguientes temas, veremos la importancia de usar las rutas de archivos y directorios en formato Url y recuerda que en S.O. Linux, se tiene en cuenta la diferencia entre mayúsculas y minúsculas.&lt;br /&gt;
&lt;br /&gt;
== Creando nuevos documentos ==&lt;br /&gt;
&lt;br /&gt;
El método que nos permite crear nuevos documentos se llama &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039; y es un método del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, por ejemplo, para crear una nueva hoja de calculo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo hay que hacer un pequeño cambio para crear un nuevo documento de texto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y los demás tipos de documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/simpress&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/sdraw&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/smath&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y una base de datos?, probemos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/sbase&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos da un error ¿verdad?&lt;br /&gt;
[[Image:Py_img_0008.png|none|thumb|500px|Error al crear base de datos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No esta soportado. Para saber por que nos da un error, intenta abrir una base de datos nueva, observa como primero, si queremos trabajar con ella, el asistente nos “obliga” primero a guardarla con un nombre y después ya podemos manipularla, esto, solo pasa con las bases de datos, de los demás documentos podemos crear tantos nuevos documentos como queramos sin tener que guardar nada, entonces ¿como creamos una nueva base de datos?, la respuesta es sencilla, del mismo modo que lo hacemos desde la interfaz de usuario, es decir, tenemos que guardar primero la base de datos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
 &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi_Base_Datos.odb&amp;quot;&lt;br /&gt;
    # Creamos el servicio que nos permite manipular bases de datos&lt;br /&gt;
    dbcon = sm.createInstance(&amp;#039;com.sun.star.sdb.DatabaseContext&amp;#039;)&lt;br /&gt;
    # creamos una instancia de una nueva base de datos&lt;br /&gt;
    base = dbcon.createInstance()&lt;br /&gt;
    # establecemos el tipo de base&lt;br /&gt;
    base.URL = &amp;quot;sdbc:embedded:hsqldb&amp;quot;&lt;br /&gt;
    # y la guardamos&lt;br /&gt;
    base.DatabaseDocument.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta dos cosas muy importantes en la macro anterior, el nombre que uses, si ya existe, simplemente lo reemplazara, no te preguntara nada, así que ten cuidado de no usar una ruta o nombre de una base importante que tengas y segundo, la base de datos así creada, no quedara “registrada” en AOO, con lo que no tendrás acceso desde otros programas de la aplicación, más adelante veremos como registrar una base de datos por código.&lt;br /&gt;
&lt;br /&gt;
== Abriendo, guardando y cerrando documentos ==&lt;br /&gt;
Abrir archivos existentes es sumamente sencillo, usamos el mismo método usado&lt;br /&gt;
para crear nuevos documentos &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, pero en el parámetro ruta, le especificamos la ubicación del archivo a abrir de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def documento1():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si tus archivos existen (esto se puede validar), el código anterior los abrirá, &amp;#039;&amp;#039;&amp;#039;siempre&amp;#039;&amp;#039;&amp;#039; utiliza&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;uno.systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; cuando uses rutas de archivos o directorios en&lt;br /&gt;
funciones de AOO que las requieran como argumentos. Ya vimos que el primer&lt;br /&gt;
agumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, es la ruta del archivo a&lt;br /&gt;
abrir, el segundo argumento es una cadena con el nombre del macro (frame)&lt;br /&gt;
donde será mostrado el documento abierto, generalmente si existe este frame se&lt;br /&gt;
usa si no se crea uno nuevo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_cal&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_writer&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existen nombre especiales para este agumento, los más usuales son dos, primero&lt;br /&gt;
que ya hemos estado usando &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; que usa el frame actual y&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039; que siempre crea un nuevo frame.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La recomendación es que uses siempre &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; o &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, un&lt;br /&gt;
escenario puede ser que habrás con &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; una instancia, y después de&lt;br /&gt;
forma oculta uno nuevo con &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, más abajo vemos como abrir un&lt;br /&gt;
documento de forma oculta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si abres una plantilla, esta se comportará de forma normal, es decir, te abrirá una copia de dicha plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_plantilla.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero también podrías querer abrir la plantilla para editarla, en este caso,&lt;br /&gt;
le indicamos en las opciones de apertura esta opción, y aquí vemos como usar&lt;br /&gt;
el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como hemos importado una nueva estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como la instanciamos y asignamos sus valores.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Muy importante, el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
espera una tupla, por eso es que usamos la coma al final del nombre del&lt;br /&gt;
argumento &amp;#039;&amp;#039;&amp;#039;(opciones,)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt; esta conformada por&lt;br /&gt;
un par de valores, un nombre y un valor y es muy frecuentemente usada cuando se&lt;br /&gt;
programa en AOO, para este ejemplo solo hemos usado un par de agumentos,&lt;br /&gt;
siempre van en pares, pero muy bien puede tener más opciones como veremos más&lt;br /&gt;
adelante. En la macro anterior le estamos indicando la propiedad&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (que seria algo así como Es Plantilla), si el valor es&lt;br /&gt;
falso (False), le estamos indicando que queremos abrir la plantilla para&lt;br /&gt;
editarla, en caso contrario (True) abrirá una copia de la plantilla. Lo&lt;br /&gt;
interesante de esta propiedad es que perfectamente la puedes aplicar a archivos&lt;br /&gt;
existentes, es decir, archivos que &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; necesariamente sean plantillas, con&lt;br /&gt;
esta propiedad podemos forzarlos a comportarse como plantillas, por ejemplo, prueba el siguiente código con algún archivo existente que no sea plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como el archivo es un documento de texto normal (ODT), pero con la&lt;br /&gt;
propiedad &amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;, forzamos su apertura como una plantilla.&lt;br /&gt;
&lt;br /&gt;
Otras propiedades interesantes son &amp;#039;&amp;#039;&amp;#039;ReadOnly&amp;#039;&amp;#039;&amp;#039; (Solo Lectura) para abrir un&lt;br /&gt;
archivo como solo lectura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y &amp;#039;&amp;#039;&amp;#039;Password&amp;#039;&amp;#039;&amp;#039; (Contraseña) para abrir archivos con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto puedes combinar cualquier cantidad de opciones siempre y cuando no&lt;br /&gt;
entren en conflicto, es importante que al final, sea una tupla lo que le pasas&lt;br /&gt;
al método, si no, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # creamos una lista vacía&lt;br /&gt;
    opciones = []&lt;br /&gt;
    # creamos la primer propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opcion.Value = True&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
    # creamos la segunda propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opcion.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    # nota que la lista la convertimos en tupla&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, tuple(opciones))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si la contraseña es incorrecta, no obtendrás ningún mensaje, simplemente no&lt;br /&gt;
lo abrira y la variable &amp;#039;&amp;#039;&amp;#039;doc&amp;#039;&amp;#039;&amp;#039; será vacía, puedes validar esto:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if doc is None:&lt;br /&gt;
        print (&amp;#039;No se abrio el documento&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos otras formas de validar y depurar nuestras macros para&lt;br /&gt;
los dificiles casos en donde no obtengamos ningún mensaje de error, pero&lt;br /&gt;
simplemente nuestra macro se niega a hacer su trabajo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mientras un formato de archivo sea soportado por AOO, lo podrás abrir con el&lt;br /&gt;
método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, en el siguiente ejemplo, abrimos un archivo tipo Doc, un Html y un Xls.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_web.html&amp;#039;)&lt;br /&gt;
    doc_h = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_excel.xls&amp;#039;)&lt;br /&gt;
    doc_x = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Qué otras opciones tengo para abrir archivos?. La mayoría están descritas&lt;br /&gt;
en el servicio &amp;lt;idl&amp;gt;com.sun.star.document.MediaDescriptor&amp;lt;/idl&amp;gt;, aquí veremos&lt;br /&gt;
las más usadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cuando abres un archivo por código y este contiene macros, tu puedes&lt;br /&gt;
establecer si se abre con las macros activadas, de forma predeterminada lo abre&lt;br /&gt;
con las macros desactivadas, así que solo nos resta saber como abrirlo con las&lt;br /&gt;
macros activadas, las constanes que puedes usar puedes verlas aquí&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.document.MacroExecMode&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.document.MacroExecMode import ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;MacroExecutionMode&amp;#039;&lt;br /&gt;
    opciones.Value = ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Otra opción interesante, es la que nos permite abrir una presentación e iniciarla inmediatamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;StartPresentation&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_impress.odp&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes abrir un archivo como vista previa, útil para evitar que el usuario haga cambios en el, en este estado, los cambios que intente hacer el usuario no se guardaran.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Preview&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, la idea general de abrir un archivo es para obtener datos de el o para manipularlo, ya sea un documento nuevo o uno existente, veamos como guardar los cambios realizados y cerrar el archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    # aquí va todo el código que quieras para manipular el archivo&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto correctamente, presiona Aceptar para gaurdarlo y cerrarlo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # guardamos los cambios&lt;br /&gt;
    doc.store()&lt;br /&gt;
    # cerramos el archivo&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El código anterior funcionara con un archivo existente, pero con uno nuevo no,&lt;br /&gt;
te dará un error, por supuesto no me creas, compruébalo. Los documentos&lt;br /&gt;
tienen un método (&amp;#039;&amp;#039;&amp;#039;hasLocation&amp;#039;&amp;#039;&amp;#039;) que nos informa si un documento ya esta guardado o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
    &lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El primer mensaje debe mostrarte falso (False) porque es un documento nuevo y&lt;br /&gt;
el segundo verdadero (True) por ser un archivo abierto del disco.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También tenemos una propiedad que nos ayuda a saber si un documento ha sido modificado o no, ejecuta la siguiente macro, llamándola desde diferentes documentos, unos ábrelos y modifícalos antes de ejecutarla, otros, solo ábrelos y ejecútala para que notes la diferencia.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def esta_modificado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
 &lt;br /&gt;
    msgbox(doc.isModified())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y otra más que nos informa si el documento es de solo lectura (&amp;#039;&amp;#039;&amp;#039;isReadonly&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que valides antes de intentar guardar un archivo, si este ha sido&lt;br /&gt;
modificado o es de solo lectura. Ahora veamos como guardar un archivo nuevo con el método &amp;#039;&amp;#039;&amp;#039;storeAsUrl&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como requiere dos parámetros, la ruta del archivo y una matriz de&lt;br /&gt;
propiedades, algunas de las cuales veremos a continuación. Toma nota de que si&lt;br /&gt;
el archivo ya existe lo reemplazara sin avisarte por lo que es buena practica&lt;br /&gt;
de programación validar esto, observa como volvemos a usar la librería&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; para saber si un archivo existe ya.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    documentos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def documentos():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;&lt;br /&gt;
    if os.path.exists(ruta):&lt;br /&gt;
        msgbox(u&amp;#039;El archivo existe, no se guardará el nuevo&amp;#039;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
De la macro anterior, &amp;#039;&amp;#039;&amp;#039;es muy importante&amp;#039;&amp;#039;&amp;#039; que tomes nota que para todos&lt;br /&gt;
los métodos de Python que usen rutas de archivos o directorios, se les tienen&lt;br /&gt;
que pasar en las rutas nativas del sistema operativo donde estes trabajando,&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;solo&amp;#039;&amp;#039;&amp;#039; a los métodos de AOO, es a los que se les pasa en notación URL.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Veamos algunas propiedades interesantes para guardar archivos, por ejemplo, guardar con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo pero con contraseña&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_protegido.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como sabes, AOO, soporta la importación/exportación de múltiples formatos de archivos, veamos como guardar, por ejemplo, en formato DOC.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo en formato DOC&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;MS Word 97&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que cuando exportes, uses un formato compatible, es decir, no&lt;br /&gt;
puedes guardar una hoja de calculo como documento de texto. En el [[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices|Apéndice]]&lt;br /&gt;
mostramos una macro para obtener todos los filtros que soporta AOO.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El método storeAsURL también lo puedes usar para abrir un archivo existente y guardarlo con otro nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos con otro nombre&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc_nuevo.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para terminar esta sección, vamos a hacer un poco más interactiva la apertura&lt;br /&gt;
y guardado de archivos, permitamos que el usuario escoja la ruta y el archivo&lt;br /&gt;
desde un cuadro de dialogo, para ello, usaremos el servicio&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt;, que nos permite hacer esto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    # podemos establecer el título&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        # el primer elemento es la ruta seleccionada&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si estableces la propiedad &amp;#039;&amp;#039;&amp;#039;MultiSelectionMode&amp;#039;&amp;#039;&amp;#039; en verdadero, le&lt;br /&gt;
permitiras al usuario seleccionar más de un archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    dlg.setMultiSelectionMode(True)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        archivos = dlg.getFiles()&lt;br /&gt;
        if len(archivos) == 1:&lt;br /&gt;
            # si selecciona uno, devuelve la ruta completa&lt;br /&gt;
            desktop.loadComponentFromURL(archivos[0], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
        else:&lt;br /&gt;
            # si selecciona varios, el primer elemento es la carpeta&lt;br /&gt;
            folder = archivos[0]&lt;br /&gt;
            # los demás elementos son los archivos seleccionados&lt;br /&gt;
            for f in range(1, len(archivos)):&lt;br /&gt;
                desktop.loadComponentFromURL(folder + archivos[f], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si lo notaste, con la macro anterior el usuario puede seleccionar cualquier&lt;br /&gt;
archivo, para limitar las opciones, agrega un filtro con el método&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;appendFilter&amp;#039;&amp;#039;&amp;#039; con solo los tipos de&lt;br /&gt;
archivos que necesites, usa una línea por cada filtro, este método requiere&lt;br /&gt;
dos argumentos, el primero es el título, lo que verá el usuario y el segundo&lt;br /&gt;
es el filtro en si.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, mostramos el cuadro de dialogo Guardar Como, para permitir al usuario&lt;br /&gt;
seleccionar carpeta y nombre de archivo donde guardar su archivo, se usa el&lt;br /&gt;
mismo servicio &amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt; solo cambiando&lt;br /&gt;
algunas de sus propiedades.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_AUTOEXTENSION_PASSWORD&lt;br /&gt;
    &lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Guardar archivo&amp;#039;)&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
    # con esta opción le indicamos que use guardar como con otras opciones&lt;br /&gt;
    dlg.initialize((FILESAVE_AUTOEXTENSION_PASSWORD,))&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        msgbox(ruta)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota que el argumento del método &amp;#039;&amp;#039;&amp;#039;initialize&amp;#039;&amp;#039;&amp;#039; es una tupla.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, para terminar, te mostramos como abrir un archivo de forma oculta.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo cerraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.store()&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es &amp;#039;&amp;#039;&amp;#039;muy importante&amp;#039;&amp;#039;&amp;#039;, que cuando abras un archivo oculto siempre uses el argumento &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, a menos claro esta, que sepas lo que haces, y que, mantengas una referencia a el, para poder cerrarlo en cuanto no lo necesites.&lt;br /&gt;
&lt;br /&gt;
== Algunas tareas comunes en documentos ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exportando a PDF ===&lt;br /&gt;
&lt;br /&gt;
Para exportar a PDF solo hay que establecer el filtro correcto, nota como construimos el nombre del filtro de acuerdo al tipo de documento y como construimos la ruta de acuerdo a la ruta actual donde este guardado el documento solo reemplazando la extensión para que quede en PDF. Estamos haciendo uso de la macro &amp;#039;&amp;#039;&amp;#039;obtener_tipo&amp;#039;&amp;#039;&amp;#039; con unos ligeros cambios para este propósito.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    export_pdf()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def export_pdf():&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    tipo = obtener_tipo(doc)&lt;br /&gt;
    soportados = &amp;#039;calc,writer,draw,impress,math&amp;#039;&lt;br /&gt;
    if tipo in soportados:&lt;br /&gt;
        # establecemos el filtro como PDF&lt;br /&gt;
        opciones = PropertyValue()&lt;br /&gt;
        opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
        opciones.Value = &amp;#039;%s_pdf_Export&amp;#039; % tipo&lt;br /&gt;
        # obtenemos la ruta y reemplazados la extensión por PDF&lt;br /&gt;
        ruta, archivo = os.path.split(doc.getURL())&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
        ruta = os.path.join(ruta, nombre + &amp;#039;.pdf&amp;#039;)&lt;br /&gt;
        # guardamos&lt;br /&gt;
        doc.storeToURL(ruta, (opciones,))&lt;br /&gt;
        msgbox(u&amp;#039;Documento exportado correctamente a PDF&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;Aplicación no soportada&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;basic&amp;#039;}&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            return tipo[t]&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La forma de descomponer la ruta en sus diferentes partes, ya la vimos anteriormente, en este caso, observa como la extensión actual del documento ya no la usaremos por lo que la omitimos con un guión bajo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ocultando y mostrando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para ocultar una ventana, hay que acceder a la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # y la ocultamos&lt;br /&gt;
        ventana.setVisible(False)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Se han ocultado todas las ventanas, presiona Aceptar para mostrarlas&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # tienes que crear de nuevo la enumeración&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # ahora las mostramos&lt;br /&gt;
        ventana.setVisible(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta técnica la puedes usar también para mostrar un archivo que abriste de forma oculta previamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo mostraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    ventana.setVisible(True)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo visible, ahora lo cerramos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Activando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para usamos el método &amp;#039;&amp;#039;&amp;#039;setFocus&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # esperamos 3 segundos y mostramos la ventana&lt;br /&gt;
        time.sleep(3)&lt;br /&gt;
        ventana.setFocus()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando la barra de estado ===&lt;br /&gt;
&lt;br /&gt;
La barra de estado, generalmente en la parte inferior de las aplicaciones, es útil para dar información al usuario, generalmente de un proceso en progreso.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def barra_estado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    barra = doc.getCurrentController().getStatusIndicator()&lt;br /&gt;
    barra.start(u&amp;#039;Se procesaran líneas en tres segundos&amp;#039;, 10)&lt;br /&gt;
    # esta pausa es solo para que veas el mensaje anterior en la barra de estado&lt;br /&gt;
    time.sleep(3)&lt;br /&gt;
    for i in range(1, 11):&lt;br /&gt;
        barra.setValue(i)&lt;br /&gt;
        barra.setText(u&amp;#039;Procesando línea: %s&amp;#039; % i)&lt;br /&gt;
        # pausa de un segundo&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
    # importante para regresar el control a la aplicación&lt;br /&gt;
    barra.end()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando el zoom de la vista ===&lt;br /&gt;
La porcentaje del zoom de la vista del documento se puede modificar con la propiedad &amp;#039;&amp;#039;&amp;#039;ZoomValue&amp;#039;&amp;#039;&amp;#039; del controlador del documento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    ctl = doc.getCurrentController()&lt;br /&gt;
    # cambiamos el zoom a 120%&lt;br /&gt;
    ctl.ZoomValue = 120&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Cambiando posición y tamaño de ventana ===&lt;br /&gt;
&lt;br /&gt;
Para eso usamos el método &amp;#039;&amp;#039;&amp;#039;setPosSize&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora, es importante decirle que valores queremos aplicar con las constantes &amp;lt;idl&amp;gt;com.sun.star.awt.PosSize&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.PosSize import POSSIZE&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    # movemos la ventana a la posicion X = 0, Y = 0&lt;br /&gt;
    # establecemos el ancho (width) = 800 y el alto (height) = 600&lt;br /&gt;
    ventana.setPosSize(0, 0, 800, 600, POSSIZE)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{ES/Foro|macros}}&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/IntroduccionPython&amp;diff=219948</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/IntroduccionPython</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/IntroduccionPython&amp;diff=219948"/>
		<updated>2013-05-09T15:39:05Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Introducción a Python}}&lt;br /&gt;
&lt;br /&gt;
== Agradecimientos ==&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Nota&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;: Estas notas están basadas en el excelente libro de Raúl González Duque [http://mundogeek.net/tutorial-python Python para todos]}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la red hay muchos y muy buenos manuales de Python, en la introducción ya recomendamos algunos y estas notas le deben mucho a ellos. En esta sección solo veremos los elementos mínimos de Python para poder continuar con nuestro aprendizaje de macros en AOO. Empecemos.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Python&amp;#039;&amp;#039;&amp;#039; tiene una sintaxis muy sencilla pero el &amp;#039;&amp;#039;&amp;#039;interprete&amp;#039;&amp;#039;&amp;#039;, es decir, el programa que se encarga de validar y ejecutar nuestro código es muy &amp;#039;&amp;#039;&amp;#039;estricto&amp;#039;&amp;#039;&amp;#039;, recuerda bien esto, &amp;#039;&amp;#039;&amp;#039;es muy estricto&amp;#039;&amp;#039;&amp;#039;. Los espacios, los tabuladores y hasta los nombres que asignamos, pueden tener repercusión en la ejecución de nuestro código, también pueden ser fuente de múltiples frustraciones que deseamos se reduzcan con estas notas.&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Sintaxis&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;: conjunto de reglas}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reiteramos, &amp;#039;&amp;#039;&amp;#039;Python es muy estricto en su sintaxis&amp;#039;&amp;#039;&amp;#039;, por ello y por otras buenas razones, Python cuenta con una guía de estilo de programación, que, en mayor medida, intentamos seguir la mayoría de los pythonistas, esta guía se le llama PEP8 y fue escrita, entre otros, por el mismo autor de Python, Guido van Rossum, tenemos una excelente traducción de nuestro amigo; Raúl González Duque, el autor del libro ya mencionado &amp;#039;&amp;#039;&amp;#039;Python para todos&amp;#039;&amp;#039;&amp;#039;, que puedes ver aquí: http://mundogeek.net/traducciones/guia-estilo-python.htm&lt;br /&gt;
&lt;br /&gt;
== Declarando y llamando macros ==&lt;br /&gt;
&lt;br /&gt;
La estructura básica para una macro es.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nombre_de_la_macro():&lt;br /&gt;
    # Instrucciones de nuestra macro&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En el tema anterior ya vimos como &amp;#039;&amp;#039;&amp;#039;llamar a otras macros&amp;#039;&amp;#039;&amp;#039;, repasemoslo aquí.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def inicio():&lt;br /&gt;
    solicitar_datos()&lt;br /&gt;
    procesar_datos()&lt;br /&gt;
    mostrar_info()&lt;br /&gt;
    print (&amp;#039;Fin&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def solicitar_datos():&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def procesar_datos():&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def mostrar_info():&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es &amp;#039;&amp;#039;&amp;#039;muy importante&amp;#039;&amp;#039;&amp;#039; que respetes la indentación de las líneas, más adelante veremos que importantes son. ¿Recuerdas que comentamos que Python es &amp;#039;&amp;#039;&amp;#039;muy estricto&amp;#039;&amp;#039;&amp;#039;?, comprobemoslo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    macro03&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def macro03():&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Ya lo notaste? nos falto poner los paréntesis al &amp;#039;&amp;#039;&amp;#039;llamar&amp;#039;&amp;#039;&amp;#039; la macro. Veamos otra.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    macro03()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def macro03()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, AOO nos muestra un mensaje de error. Observa como nos indica el archivo y la línea donde esta el error. En este caso, nos faltaron los dos puntos al final de la declaración de la macro. Lo repetiremos muchas veces: &amp;#039;&amp;#039;&amp;#039;Python es muy estricto&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[File:Py_img_0005.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Variables - Tipos básicos ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No es necesario declarar el tipo de dato que contendrá una variable en Python, a esta característica se le llama: &amp;#039;&amp;#039;&amp;#039;tipado dinámico&amp;#039;&amp;#039;&amp;#039;. Ejemplos:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    variables()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def variables():&lt;br /&gt;
    texto = &amp;#039;Soy un texto&amp;#039;&lt;br /&gt;
    numero_entero = 10&lt;br /&gt;
    numero_flotante = 3.1416&lt;br /&gt;
    booleanos = True  # o False&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Nota&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;: de aquí en adelante, solo mostraremos los nuevos ejemplos, en el entendido de que tienen que ser ejecutados desde nuestra macro inicial &amp;#039;&amp;#039;&amp;#039;pruebas&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para saber el tipo de valor que contiene una variable, usamos la función &amp;#039;&amp;#039;&amp;#039;type&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def variables():&lt;br /&gt;
    texto = &amp;#039;Soy un texto&amp;#039;&lt;br /&gt;
    numero_entero = 10&lt;br /&gt;
    numero_flotante = 3.1416&lt;br /&gt;
    booleanos = True  # o False&lt;br /&gt;
&lt;br /&gt;
    print (type(texto))&lt;br /&gt;
    print (type(numero_entero))&lt;br /&gt;
    print (type(numero_flotante))&lt;br /&gt;
    print (type(booleanos))&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Cuidado&amp;#039;&amp;#039;&amp;#039;, el que no necesites declarar el tipo de variable, no significa que puedas usarlas cuando quieras, recuerda, &amp;#039;&amp;#039;&amp;#039;solo puedes usar variables asignadas previamente&amp;#039;&amp;#039;&amp;#039;, la siguiente macro te tiene que dar un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def variables():&lt;br /&gt;
    t = &amp;#039;Hola mundo&amp;#039;&lt;br /&gt;
    print (t)&lt;br /&gt;
    print (s)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Variables - Colecciones ==&lt;br /&gt;
&lt;br /&gt;
Estos tipos de variables permiten almacenar más de un valor.&lt;br /&gt;
&lt;br /&gt;
=== Listas ===&lt;br /&gt;
&lt;br /&gt;
La lista es un tipo de colección ordenada. Sería equivalente a lo que en otros lenguajes se conoce por arrays, o vectores. Las listas pueden contener cualquier tipo de dato: números, cadenas, booleanos, ... y también listas, para crear una lista, se usan los corchetes y sus elementos separados por comas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def variables():&lt;br /&gt;
    # lista de número enteros&lt;br /&gt;
    mi_lista1 = [1, 2, 3, 4]&lt;br /&gt;
    # lista de cadenas&lt;br /&gt;
    mi_lista2 = [&amp;#039;Noemi&amp;#039;, &amp;#039;Paola&amp;#039;, &amp;#039;Claudia&amp;#039;]&lt;br /&gt;
    # lista mixta&lt;br /&gt;
    mi_lista3 = [10, &amp;#039;Alejandra&amp;#039;, 3.14, True, [9, 8, 7]]&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que en la ultima lista, su ultimo elemento es otra lista. Más abajo mira algunas de las operaciones que podemos hacer con las listas. Para hacer referencia a un elementos de la lista, usamos su indice o posición, este, siempre empieza en cero.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (mi_lista3[1])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes modificar cualquier elemento de la lista.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    mi_lista3[2] = 3.1416&lt;br /&gt;
    print (mi_lista3)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes realizar las siguiente operaciones con las listas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # agregar un elemento al final&lt;br /&gt;
    mi_lista.append(10)&lt;br /&gt;
    print (mi_lista)&lt;br /&gt;
    &lt;br /&gt;
    # extender la lista con otra secuencia&lt;br /&gt;
    mi_lista.extend([100,200,300])&lt;br /&gt;
    print (mi_lista)&lt;br /&gt;
&lt;br /&gt;
    # borra un elemento&lt;br /&gt;
    mi_lista.remove(200)&lt;br /&gt;
    print (mi_lista)&lt;br /&gt;
&lt;br /&gt;
    # insertar un elemento en la posición determinada&lt;br /&gt;
    mi_lista.insert(4, 500)&lt;br /&gt;
    print (mi_lista)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Tuplas ===&lt;br /&gt;
Son muy parecidas a las listas, se diferencian en su forma de crearse y en que son inmutables, es decir, no puede modificar sus elementos como en las listas. Para crear una tupla, usamos los paréntesis, si creas una tupla de un solo elemento, es importante uses la coma para crearla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    mi_tupla1 = (&amp;#039;Un solo elemento&amp;#039;,)&lt;br /&gt;
    mi_tupla2 = (12, 13, 14)&lt;br /&gt;
    mi_tupla3 = (10, &amp;#039;Estela&amp;#039;, False, (1,3,5)) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que de nuevo en la ultima tupla, en su ultimo elemento, tenemos una tupla.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Diccionarios ===&lt;br /&gt;
Los diccionarios, también llamados matrices asociativas, son colecciones que relacionan una clave y un valor, para crearlos se usan las llaves de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    peliculas = {&amp;#039;Vivir&amp;#039;: &amp;#039;Akira Kurosawa&amp;#039;,&lt;br /&gt;
                &amp;#039;El Gran Pez&amp;#039;: &amp;#039;Tim Burton&amp;#039;,&lt;br /&gt;
                &amp;#039;Amores Perros&amp;#039;: &amp;#039;Alejandro González Iñárritu&amp;#039;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El primer valor se trata de la clave y el segundo del valor asociado a la clave. Como clave podemos utilizar cualquier valor inmutable: podríamos usar números, cadenas, booleanos, tuplas, ... pero no listas o diccionarios, dado que son mutables. La diferencia principal entre los diccionarios y las listas o las tuplas es que a los valores almacenados en un diccionario se les accede no por su índice, porque de hecho no tienen orden, sino por su clave.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (peliculas[&amp;#039;Vivir&amp;#039;])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes usar esta misma clave para cambiar su valor.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    peliculas[&amp;#039;Vivir&amp;#039;] = &amp;#039;Zhang Yimou&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Variables - Secuencias ==&lt;br /&gt;
Las listas, las tuplas y las cadenas de texto, son secuencias por que se puede acceder a sus elementos a través de un índice, no son los únicos en Python. Entre sus características están.&lt;br /&gt;
* No es necesario conocer cuantos elementos contendrá la secuencia.&lt;br /&gt;
* Pueden guardar cualquier tipo de objeto.&lt;br /&gt;
* No hay limite para la cantidad de elementos que guardará.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para acceder a cualquier elemento de la secuencia, usamos un índice.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def secuencias():&lt;br /&gt;
    mi_lista = [5, 9, 12, 1, 56]&lt;br /&gt;
    mi_tupla = (23, 89, 12, 56, 23)&lt;br /&gt;
    mi_cadena = &amp;#039;Python es facil y divertido&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    print (mi_lista[0])&lt;br /&gt;
    print (mi_tupla[1])&lt;br /&gt;
    print (mi_cadena[2])&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si intentas usar un índice inexistente, el interprete te mostrará un error. También puedes usar índices negativos, con lo cual la cuenta empezará desde el ultimo elemento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def secuencias():&lt;br /&gt;
    print (mi_lista[-1])&lt;br /&gt;
    print (mi_tupla[-2])&lt;br /&gt;
    print (mi_cadena[-3])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes usar funciones comunes a las secuencias, como contar su número de elementos, obtener el máximo o el mínimo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (len(mi_lista))&lt;br /&gt;
    print (len(mi_tupla))&lt;br /&gt;
    print (len(mi_cadena))&lt;br /&gt;
&lt;br /&gt;
    print (max(mi_lista))&lt;br /&gt;
    print (max(mi_tupla))&lt;br /&gt;
    print (max(mi_cadena))&lt;br /&gt;
&lt;br /&gt;
    print (min(mi_lista))&lt;br /&gt;
    print (min(mi_tupla))&lt;br /&gt;
    print (min(mi_cadena))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes conocer el índice del primer elemento encontrado.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (mi_lista.index(12))&lt;br /&gt;
    print (mi_tupla.index(56))&lt;br /&gt;
    print (mi_cadena.index(&amp;#039;d&amp;#039;))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes conocer el número de veces que aparece un elemento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (mi_lista.count(9))&lt;br /&gt;
    print (mi_tupla.count(89))&lt;br /&gt;
    print (mi_cadena.count(&amp;#039;o&amp;#039;))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes ordenar los elementos, para ello, usamos la función &amp;#039;&amp;#039;&amp;#039;sorted&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (sorted(mi_lista))&lt;br /&gt;
    print (sorted(mi_tupla))&lt;br /&gt;
    print (sorted(mi_cadena))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes devolver solo una parte de la secuencia, a esta operación se le llama &amp;#039;&amp;#039;&amp;#039;slices&amp;#039;&amp;#039;&amp;#039; y se usan índices enteros (pueden ser positivos o negativos) de la forma [x:y:z], donde:&lt;br /&gt;
* x = elemento inicial.&lt;br /&gt;
* y = elemento final, cuidado, la posición &amp;#039;&amp;#039;&amp;#039;y&amp;#039;&amp;#039;&amp;#039; no es devuelta, por lo que el fin real es &amp;#039;&amp;#039;&amp;#039;y-1&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* z = salto entre elementos, de forma predeterminada &amp;#039;&amp;#039;&amp;#039;z = 1&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (mi_cadena[7:15:1])&lt;br /&gt;
    print (mi_cadena[0:20:2])&lt;br /&gt;
    print (mi_cadena[-1:-10:-1])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Se pueden omitir los argumentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # devolvemos los primeros diez&lt;br /&gt;
    print (mi_cadena[:10])&lt;br /&gt;
    # devolvemos los últimos diez&lt;br /&gt;
    print (mi_cadena[-10:])&lt;br /&gt;
    # mira que divertido&lt;br /&gt;
    print (mi_cadena[::-1])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos saber si un elemento pertenece a una secuencia con el operador &amp;#039;&amp;#039;&amp;#039;in&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (12 in mi_lista)&lt;br /&gt;
    print (100 in mi_tupla)&lt;br /&gt;
    print (&amp;#039;es&amp;#039; in mi_cadena)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes &amp;#039;&amp;#039;&amp;#039;sumar&amp;#039;&amp;#039;&amp;#039; dos secuencias, con la única condición de que sean del mismo tipo, en el siguiente ejemplo, la ultima línea te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (mi_lista + [&amp;#039;a&amp;#039;, &amp;#039;b&amp;#039;, &amp;#039;c&amp;#039;])&lt;br /&gt;
    print (mi_tupla + (&amp;#039;x&amp;#039;, &amp;#039;y&amp;#039;, False))&lt;br /&gt;
    print (mi_cadena + (5, 10, 20))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes &amp;#039;&amp;#039;&amp;#039;multiplicar&amp;#039;&amp;#039;&amp;#039; una secuencia por un entero, recuerda que la multiplicación es una suma abreviada.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print ([&amp;#039;a&amp;#039;, &amp;#039;b&amp;#039;, &amp;#039;c&amp;#039;] * 3)&lt;br /&gt;
    print ((&amp;#039;x&amp;#039;, &amp;#039;y&amp;#039;) * 4)&lt;br /&gt;
    print (&amp;#039;adios&amp;#039; * 5)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Conversión del tipo de la variable ==&lt;br /&gt;
&lt;br /&gt;
No se permite tratar a una variable como si fuera de un tipo distinto al que tiene, es necesario convertir de forma explícita dicha variable al nuevo tipo previamente, a esta característica se le llama &amp;#039;&amp;#039;&amp;#039;fuertemente tipado&amp;#039;&amp;#039;&amp;#039;. Para convertir variables de un tipo a otro usamos las siguientes funciones.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # convertimos un entero en cadena&lt;br /&gt;
    mi_entero = 100&lt;br /&gt;
    print (type(mi_entero))&lt;br /&gt;
    mi_entero = str(mi_entero)&lt;br /&gt;
    print (type(mi_entero))&lt;br /&gt;
&lt;br /&gt;
    # convertimos un flotante en cadena&lt;br /&gt;
    mi_numero = 3.14&lt;br /&gt;
    print (type(mi_numero))&lt;br /&gt;
    mi_numero = str(mi_numero)&lt;br /&gt;
    print (type(mi_numero))&lt;br /&gt;
&lt;br /&gt;
    # convertimos una cadena, en entero y luego el entero en flotante&lt;br /&gt;
    mi_cadena = &amp;#039;1000&amp;#039;&lt;br /&gt;
    print (type(mi_cadena))&lt;br /&gt;
    mi_cadena = int(mi_cadena)&lt;br /&gt;
    print (type(mi_cadena))&lt;br /&gt;
    mi_cadena = float(mi_cadena)&lt;br /&gt;
    print (type(mi_cadena))&lt;br /&gt;
&lt;br /&gt;
    # convertimos una cadena (secuencia) en una lista, luego la lista en tupla&lt;br /&gt;
    # y al final de nuevo en cadena, CUIDADO con la ultima conversión.&lt;br /&gt;
    mi_cadena = &amp;#039;Hola Mundo&amp;#039;&lt;br /&gt;
    print (type(mi_cadena))&lt;br /&gt;
    mi_cadena = list(mi_cadena)&lt;br /&gt;
    print (type(mi_cadena))&lt;br /&gt;
    mi_cadena = tuple(mi_cadena)&lt;br /&gt;
    print (type(mi_cadena))&lt;br /&gt;
    mi_cadena = str(mi_cadena)&lt;br /&gt;
    print (type(mi_cadena))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Operadores ==&lt;br /&gt;
Los operadores aritméticos son los siguientes:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt; &lt;br /&gt;
    # suma&lt;br /&gt;
    t = 10 + 20&lt;br /&gt;
&lt;br /&gt;
    # resta&lt;br /&gt;
    r = 100 - 45&lt;br /&gt;
&lt;br /&gt;
    # multiplicación&lt;br /&gt;
    m = 34 * 45&lt;br /&gt;
&lt;br /&gt;
    # exponenciación&lt;br /&gt;
    e = 2 ** 6&lt;br /&gt;
&lt;br /&gt;
    # división&lt;br /&gt;
    d = 50.5 / 2&lt;br /&gt;
&lt;br /&gt;
    # división entera&lt;br /&gt;
    de = 3.5 / 2&lt;br /&gt;
&lt;br /&gt;
    # modulo, resto de una división&lt;br /&gt;
    mo = 7 % 2&lt;br /&gt;
&lt;br /&gt;
    print (t, r, m, e, d, de, mo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los operadores de relación y booleanos son los siguientes.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # igualdad&lt;br /&gt;
    r = 10 == 10&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = 10 == 20&lt;br /&gt;
    print (r)&lt;br /&gt;
&lt;br /&gt;
    # diferencia&lt;br /&gt;
    r = &amp;#039;A&amp;#039; != &amp;#039;A&amp;#039;&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = &amp;#039;A&amp;#039; != &amp;#039;B&amp;#039;&lt;br /&gt;
    print (r)&lt;br /&gt;
&lt;br /&gt;
    # menor que&lt;br /&gt;
    r = 10 &amp;lt; 20&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = 10 &amp;lt; 5&lt;br /&gt;
    print (r)&lt;br /&gt;
&lt;br /&gt;
    # mayor que&lt;br /&gt;
    r = 20 &amp;gt; 5&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = 10 &amp;gt; 100&lt;br /&gt;
    print (r)&lt;br /&gt;
&lt;br /&gt;
    print &amp;#039;\n&amp;#039;&lt;br /&gt;
    # and&lt;br /&gt;
    r = True and True&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = True and False&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = False and True&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = False and False&lt;br /&gt;
    print (r)&lt;br /&gt;
&lt;br /&gt;
    # or&lt;br /&gt;
    r = True or True&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = True or False&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = False or True&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = False or False&lt;br /&gt;
    print (r)&lt;br /&gt;
&lt;br /&gt;
    # negación&lt;br /&gt;
    r = not False&lt;br /&gt;
    print (r)&lt;br /&gt;
    r = not True&lt;br /&gt;
    print (r)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Condicionales ==&lt;br /&gt;
Estas estructuras nos permiten evaluar una instrucción y tomar un camino, dependiendo si esa es Falsa(False) o Verdadera (True), por ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    edad = 15&lt;br /&gt;
    if edad &amp;lt; 18:&lt;br /&gt;
        print (&amp;#039;Eres menor de edad&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Importante&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;: Observa los dos puntos al final de la evaluación de la condición y la sangría al inicio de la siguiente línea, la sangría le dice al interprete, que esta línea esta &amp;#039;&amp;#039;&amp;#039;dentro&amp;#039;&amp;#039;&amp;#039; de la estructura &amp;#039;&amp;#039;&amp;#039;if&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
Si solo tienes dos alternativas, puedes complementar la estructura con la instrucción &amp;#039;&amp;#039;else&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    edad = 25&lt;br /&gt;
    if edad &amp;lt; 18:&lt;br /&gt;
        print (&amp;#039;Eres menor de edad&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Eres mayor de edad&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si tienes varias alternativas, entonces complementa con la instrucción &amp;#039;&amp;#039;&amp;#039;elif&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # observa la asignacion que usa un solo signo igual&lt;br /&gt;
    calificacion = 7&lt;br /&gt;
    if calificacion &amp;lt; 6:&lt;br /&gt;
        print (&amp;#039;Reprobado&amp;#039;)&lt;br /&gt;
    # observa la comparación que usa dos signos igual&lt;br /&gt;
    elif calificacion == 6:&lt;br /&gt;
        print (&amp;#039;De panzaso pasaste&amp;#039;)&lt;br /&gt;
    elif calificacion &amp;gt; 6 and calificacion &amp;lt;= 7:&lt;br /&gt;
        print (&amp;#039;Hay que esforzarse más&amp;#039;)&lt;br /&gt;
    elif calificacion &amp;gt; 7 and calificacion &amp;lt;= 9:&lt;br /&gt;
        print (&amp;#039;Bien Hecho&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Excelente&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota que independiente de la cantidad de comparaciones, cada línea termina en dos puntos y las líneas &amp;#039;&amp;#039;&amp;#039;dentro&amp;#039;&amp;#039;&amp;#039; de dicha condición tienen una sangría para indicarle que son parte de dicha condición. Toman en cuenta que como condición; &amp;#039;&amp;#039;se puede usar cualquier expresión susceptible de ser evaluada como verdadera(True) o falsa(False)&amp;#039;&amp;#039;. Cualquier variable vacía o cero, serán evaluados como falsas, cualquier otra como verdaderas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # números&lt;br /&gt;
    numero = 10&lt;br /&gt;
    if numero:&lt;br /&gt;
        print (numero)&lt;br /&gt;
    numero = 0&lt;br /&gt;
    if not numero:&lt;br /&gt;
        print (&amp;#039;Cero&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # cadenas&lt;br /&gt;
    cadena = &amp;#039;PyUNO&amp;#039;&lt;br /&gt;
    if cadena:&lt;br /&gt;
        print (cadena)&lt;br /&gt;
    cadena = &amp;#039;&amp;#039;&lt;br /&gt;
    if not cadena:&lt;br /&gt;
        print (&amp;#039;Cadena vacia&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # listas&lt;br /&gt;
    lista = []&lt;br /&gt;
    if not lista:&lt;br /&gt;
        print (&amp;#039;Lista vacia&amp;#039;)&lt;br /&gt;
    lista = [1, 2, 3]&lt;br /&gt;
    if lista:&lt;br /&gt;
        print (lista)&lt;br /&gt;
&lt;br /&gt;
    # tuplas&lt;br /&gt;
    tupla = ()&lt;br /&gt;
    if not tupla:&lt;br /&gt;
        print (&amp;#039;Tupla vacia&amp;#039;)&lt;br /&gt;
    tupla = (1, 2, 3)&lt;br /&gt;
    if tupla:&lt;br /&gt;
        print (tupla)&lt;br /&gt;
&lt;br /&gt;
    # diccionario&lt;br /&gt;
    dic = {}&lt;br /&gt;
    if not dic:&lt;br /&gt;
        print (&amp;#039;Diccionario vacio&amp;#039;)&lt;br /&gt;
    dic = {&amp;#039;Nombre&amp;#039;: &amp;#039;Noemi Hernandez&amp;#039;}&lt;br /&gt;
    if dic:&lt;br /&gt;
        print (dic)&lt;br /&gt;
&lt;br /&gt;
    # valor Nulo&lt;br /&gt;
    otro = None&lt;br /&gt;
    if not otro:&lt;br /&gt;
        print (&amp;#039;Sin valor&amp;#039;)&lt;br /&gt;
    otro = 100&lt;br /&gt;
    if otro:&lt;br /&gt;
        print (otro)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por ultimo, en Python no hay una estructura &amp;#039;&amp;#039;&amp;#039;Select...Case&amp;#039;&amp;#039;&amp;#039; de otros lenguajes, sencillamente &amp;#039;&amp;#039;porque no es necesaria&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
== Bucles ==&lt;br /&gt;
&lt;br /&gt;
Para ejecutar una fragmento de código varias veces, usamos los bucles. La estructura &amp;#039;&amp;#039;&amp;#039;for...in&amp;#039;&amp;#039;&amp;#039; y la estructura &amp;#039;&amp;#039;&amp;#039;while&amp;#039;&amp;#039;&amp;#039;. Lo decimos una vez más; &amp;#039;&amp;#039;&amp;#039;Python es muy estricto&amp;#039;&amp;#039;&amp;#039;, y en el caso de los bucles lo podrás notar, pues el bloque de estas estructuras quedan delimitados por la indentación del código, no se usan paréntesis o llaves como en otros lenguajes, simplemente la sangría de las líneas es lo que determina la pertenencia y la validez de una estructura.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Estructura for..in ===&lt;br /&gt;
Esta estructura nos permite iterar en una secuencia, por ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    for i in [1,2,3,4,5]:&lt;br /&gt;
        print (i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Importante&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;: Observa los dos puntos al final de la primer línea y la sangría al inicio de la segunda, la sangría le dice al interprete, que esta línea esta &amp;#039;&amp;#039;&amp;#039;dentro&amp;#039;&amp;#039;&amp;#039; de la estructura for...in}}&lt;br /&gt;
&lt;br /&gt;
Puedes apoyarte en la función &amp;#039;&amp;#039;&amp;#039;range&amp;#039;&amp;#039;&amp;#039; si quieres iterar un número determinado de veces.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    for i in range(5):&lt;br /&gt;
        print (i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Observa&amp;#039;&amp;#039;&amp;#039; que, los dos ejemplos previos, iteran el mismo número de veces (cinco), pero no en el mismo rango, esto es por que mientras no le indiques lo contrario, la función rango empieza en 0. Puedes generar un rango determinado, pasandole los argumentos correctos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    for i in range(10, 21):&lt;br /&gt;
        print (i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como ya habrás notado, la función &amp;#039;&amp;#039;&amp;#039;range&amp;#039;&amp;#039;&amp;#039; recibo los mismos argumentos usados en las secuencias.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    for i in range(100, 1001, 100):&lt;br /&gt;
        print (i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Incluyendo los enteros negativos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    for i in range(0, -500, -50):&lt;br /&gt;
        print (i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como ya mencionamos, esta estructura puede iterar en los elementos de una secuencia.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    mi_lista = [5, 9, 12, 1, 56]&lt;br /&gt;
    mi_tupla = (23, 89, 12, 56, 23)&lt;br /&gt;
    mi_cadena = &amp;#039;pyUNO&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    for i in mi_lista:&lt;br /&gt;
        print (i)&lt;br /&gt;
    print (&amp;#039;\n&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    for i in mi_tupla:&lt;br /&gt;
        print (i)&lt;br /&gt;
    print (&amp;#039;\n&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    for i in mi_cadena:&lt;br /&gt;
        print (i)&lt;br /&gt;
    print (&amp;#039;\n&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Observa&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;: la forma de mostrar un salto de línea en pantalla, usando la secuencia de escape &amp;#039;\n&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
Puedes iterar en una secuencia y numerar sus elementos, usando la función &amp;#039;&amp;#039;&amp;#039;enumerate&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    mi_tupla = (&amp;#039;Noemi&amp;#039;, &amp;#039;Claudia&amp;#039;, &amp;#039;Paola&amp;#039;, &amp;#039;Estela&amp;#039;)&lt;br /&gt;
    for i,v in enumerate(mi_tupla):&lt;br /&gt;
        print (i, v)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
De un modo similar puedes iterar un diccionario y devolver su clave y el valor de dicha clave.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    dic = {1: &amp;#039;Uno&amp;#039;, 2: &amp;#039;Dos&amp;#039;, 3: &amp;#039;Tres&amp;#039;, 4: &amp;#039;Cuatro&amp;#039;, 5: &amp;#039;Cinco&amp;#039;}&lt;br /&gt;
    for k,v in dic.items():&lt;br /&gt;
        print (k,v)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por ultimo, puedes tener estructuras anidadas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    datos = (&lt;br /&gt;
        (&amp;#039;A1&amp;#039;, &amp;#039;B1&amp;#039;, &amp;#039;C2&amp;#039;, &amp;#039;D1&amp;#039;, &amp;#039;E1&amp;#039;),&lt;br /&gt;
        (&amp;#039;A2&amp;#039;, &amp;#039;B2&amp;#039;, &amp;#039;C2&amp;#039;, &amp;#039;D2&amp;#039;, &amp;#039;E2&amp;#039;),&lt;br /&gt;
        (&amp;#039;A3&amp;#039;, &amp;#039;B3&amp;#039;, &amp;#039;C3&amp;#039;, &amp;#039;D3&amp;#039;, &amp;#039;E3&amp;#039;),&lt;br /&gt;
        (&amp;#039;A4&amp;#039;, &amp;#039;B4&amp;#039;, &amp;#039;C4&amp;#039;, &amp;#039;D4&amp;#039;, &amp;#039;E4&amp;#039;),&lt;br /&gt;
        (&amp;#039;A5&amp;#039;, &amp;#039;B5&amp;#039;, &amp;#039;C5&amp;#039;, &amp;#039;D5&amp;#039;, &amp;#039;E5&amp;#039;),&lt;br /&gt;
    )&lt;br /&gt;
    for r in datos:&lt;br /&gt;
        print (r)&lt;br /&gt;
        for c in r:&lt;br /&gt;
            print (c)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Importante&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;: si, ya lo mencionamos, pero toma nota de la &amp;#039;&amp;#039;&amp;#039;correcta sangría&amp;#039;&amp;#039;&amp;#039; en cada línea}}&lt;br /&gt;
&lt;br /&gt;
Otras instrucciones que complementan a esta estructura son: &amp;#039;&amp;#039;&amp;#039;break&amp;#039;&amp;#039;&amp;#039; que nos permite salir de un ciclo de forma anticipada y &amp;#039;&amp;#039;&amp;#039;continue&amp;#039;&amp;#039;&amp;#039; que nos permite saltar directamente al siguiente ciclo, por ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # observa como no imprime las dos ultimas cifras&lt;br /&gt;
    datos = (13, 67, 45, 0, 34, 56)&lt;br /&gt;
    for v in datos:&lt;br /&gt;
        if v == 0:&lt;br /&gt;
            break&lt;br /&gt;
        else:&lt;br /&gt;
            print (v)&lt;br /&gt;
    print (&amp;#039;\n&amp;#039;)&lt;br /&gt;
    # observa como no imprime el cero, pero si las dos ultimas cifras&lt;br /&gt;
    datos = (13, 67, 45, 0, 34, 56)&lt;br /&gt;
    for v in datos:&lt;br /&gt;
        if v == 0:&lt;br /&gt;
            continue&lt;br /&gt;
        else:&lt;br /&gt;
            print (v)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Estructura while ===&lt;br /&gt;
Esta estructura nos permite ejecutar fragmentos de código mientras se cumpla o hasta que se cumpla una condición dada, por ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # valor inicial&lt;br /&gt;
    edad = 5&lt;br /&gt;
    # condición para continuar&lt;br /&gt;
    while edad &amp;lt; 18:&lt;br /&gt;
        # aumentamos la edad en uno&lt;br /&gt;
        edad += 1&lt;br /&gt;
        # mostramos la edad&lt;br /&gt;
        print (&amp;#039;Tienes &amp;#039; + str(edad) + &amp;#039; años&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos formas más &amp;#039;&amp;#039;elegantes&amp;#039;&amp;#039; de formatear cadenas de texto. Hay que tener algo de precaución cuando se defina la condición de una estructura &amp;#039;&amp;#039;&amp;#039;while&amp;#039;&amp;#039;&amp;#039;, cuando se es novel es común caer en condiciones que nunca se cumplen y por lo tanto quedar &amp;#039;&amp;#039;atrapados&amp;#039;&amp;#039; en bucles infinitos.&lt;br /&gt;
&lt;br /&gt;
Al igual que en la estructura &amp;#039;&amp;#039;&amp;#039;for...in&amp;#039;&amp;#039;&amp;#039;, en la estructura &amp;#039;&amp;#039;&amp;#039;while&amp;#039;&amp;#039;&amp;#039; podemos usar las instrucciones &amp;#039;&amp;#039;&amp;#039;break&amp;#039;&amp;#039;&amp;#039; y &amp;#039;&amp;#039;&amp;#039;continue&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Funciones incorporadas ==&lt;br /&gt;
&lt;br /&gt;
La mayor parte de las herramientas de Python, están desarrolladas en módulos independientes que hay que importar de forma explicita cada vez que se requieran, este tema lo veremos más adelante. En esta sección veremos algunas de las funciones incorporadas, algunas de las cuales ya vimos en temas anteriores, por ejemplo.&lt;br /&gt;
&lt;br /&gt;
Para ver el tipo de una variable usamos &amp;#039;&amp;#039;&amp;#039;type&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    n = 1001&lt;br /&gt;
    print (type(n))&lt;br /&gt;
    n = &amp;#039;AOO&amp;#039;&lt;br /&gt;
    print (type(n))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para devolver el valor absoluto de un número usamos &amp;#039;&amp;#039;&amp;#039;abs&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    n = -1001&lt;br /&gt;
    print (abs(n))&lt;br /&gt;
    n = -3.1416&lt;br /&gt;
    print (abs(n))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para convertir una variable en tipo booleana usamos &amp;#039;&amp;#039;&amp;#039;bool&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    v = &amp;#039;&amp;#039;&lt;br /&gt;
    b = bool(v)&lt;br /&gt;
    print (b)&lt;br /&gt;
&lt;br /&gt;
    v = &amp;#039;AOO&amp;#039;&lt;br /&gt;
    b = bool(v)&lt;br /&gt;
    print (b)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para devolver el valor ASCII del entero pasado usamos &amp;#039;&amp;#039;&amp;#039;chr&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    v = chr(97)&lt;br /&gt;
    print (v)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para convertir una cadena o entero en flotante, usamos &amp;#039;&amp;#039;&amp;#039;float&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    texto = &amp;#039;100&amp;#039;&lt;br /&gt;
    n = float(texto)&lt;br /&gt;
    print n&lt;br /&gt;
    texto = &amp;#039;-10.5&amp;#039;&lt;br /&gt;
    n = float(texto)&lt;br /&gt;
    print n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para convertir una cadena en entero, usamos &amp;#039;&amp;#039;&amp;#039;int&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    numero = &amp;#039;100&amp;#039;&lt;br /&gt;
    i = int(numero)&lt;br /&gt;
    print (i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para saber si una variable es de un tipo(clase) determinado, usamos &amp;#039;&amp;#039;&amp;#039;isinstance&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    numero = &amp;#039;100&amp;#039;&lt;br /&gt;
    if isinstance(numero, str):&lt;br /&gt;
        print (&amp;#039;Es una cadena&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    numero = 100&lt;br /&gt;
    if isinstance(numero, int):&lt;br /&gt;
        print (&amp;#039;Es un entero&amp;#039;)i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para devolver la longitud de una secuencia o diccionario usamos &amp;#039;&amp;#039;&amp;#039;len&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    lista = [1, 2, 3]&lt;br /&gt;
    print (len(lista))&lt;br /&gt;
&lt;br /&gt;
    tupla = (&amp;#039;a&amp;#039;, &amp;#039;b&amp;#039;, &amp;#039;c&amp;#039;, &amp;#039;d&amp;#039;, &amp;#039;e&amp;#039;)&lt;br /&gt;
    print (len(tupla))&lt;br /&gt;
&lt;br /&gt;
    cadena = &amp;#039;Apache OpenOffice&amp;#039;&lt;br /&gt;
    print (len(cadena))&lt;br /&gt;
&lt;br /&gt;
    dic = {&amp;#039;Uno&amp;#039;: &amp;#039;Dos&amp;#039;, &amp;#039;Tres&amp;#039;: &amp;#039;Cuatro&amp;#039;}&lt;br /&gt;
    print (len(dic))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para convertir una secuencia en lista usamos &amp;#039;&amp;#039;&amp;#039;list&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    tupla = (&amp;#039;a&amp;#039;, &amp;#039;b&amp;#039;, &amp;#039;c&amp;#039;, &amp;#039;d&amp;#039;, &amp;#039;e&amp;#039;)&lt;br /&gt;
    lista = list(tupla)&lt;br /&gt;
    print (type(lista), lista)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para convertir una cadena o número en entero largo usamos &amp;#039;&amp;#039;&amp;#039;long&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    cadena = &amp;#039;100000&amp;#039;&lt;br /&gt;
    n = long(cadena)&lt;br /&gt;
    print (type(n), n)a)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para devolver el máximo de una secuencia usamos &amp;#039;&amp;#039;&amp;#039;max&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    tupla = (10, 100, 0, 500, 999)&lt;br /&gt;
    print (max(tupla))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para devolver el mínimo de una secuencia usamos &amp;#039;&amp;#039;&amp;#039;min&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    tupla = (10, 100, 0, 500, 999)&lt;br /&gt;
    print (min(tupla))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para abrir un archivo y escribir en el usamos usamos &amp;#039;&amp;#039;&amp;#039;open&amp;#039;&amp;#039;&amp;#039;. Más adelante veremos el trabajo con archivos a detalle.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    f = open(&amp;#039;detalle.txt&amp;#039;, &amp;#039;w&amp;#039;)&lt;br /&gt;
    f.write(&amp;#039;Aprendiendo python&amp;#039;)&lt;br /&gt;
    f.close()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para elevar un número a una potencia usamos &amp;#039;&amp;#039;&amp;#039;pow&amp;#039;&amp;#039;&amp;#039;. El siguiente número te tiene que resultar familiar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (pow(2,10))&lt;br /&gt;
    print (2 ** 10)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para devolver una lista con una progresión aritmética usamos &amp;#039;&amp;#039;&amp;#039;range&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    print (range(11))&lt;br /&gt;
    print (range(1000, 10000, 500))&lt;br /&gt;
    print (range(-100, -500, -50))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para devolver una secuencia en reversa &amp;#039;&amp;#039;&amp;#039;reversed&amp;#039;&amp;#039;&amp;#039;. Toma en cuenta que tienes que convertir de nuevo al tipo de secuencia original. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    tupla = (10, 100, 0, 500, 999)&lt;br /&gt;
    print (tuple(reversed(tupla)))&lt;br /&gt;
&lt;br /&gt;
    lista = [&amp;#039;a&amp;#039;, &amp;#039;d&amp;#039;, &amp;#039;p&amp;#039;, &amp;#039;g&amp;#039;, &amp;#039;z&amp;#039;]&lt;br /&gt;
    print (list(reversed(lista)))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para redondear un número flotante usamos &amp;#039;&amp;#039;&amp;#039;round&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    numero = 3.1499&lt;br /&gt;
    print (round(numero, 2))&lt;br /&gt;
    # si omites el segundo argumento&lt;br /&gt;
    print (round(numero))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para ordenar secuencias usamos &amp;#039;&amp;#039;&amp;#039;sorted&amp;#039;&amp;#039;&amp;#039;. Más adelante veremos otras técnicas de ordenamiento para secuencias y diccionarios.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    tupla = (10, 100, 0, 500, 999)&lt;br /&gt;
    print (sorted(tupla))&lt;br /&gt;
&lt;br /&gt;
    lista = [&amp;#039;a&amp;#039;, &amp;#039;d&amp;#039;, &amp;#039;p&amp;#039;, &amp;#039;g&amp;#039;, &amp;#039;z&amp;#039;]&lt;br /&gt;
    print (sorted(lista))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para devolver la representación impresa de un objeto usamos &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    lista = [1, 2, 3]&lt;br /&gt;
    print (str(lista))&lt;br /&gt;
&lt;br /&gt;
    tupla = (&amp;#039;a&amp;#039;, &amp;#039;b&amp;#039;, &amp;#039;c&amp;#039;, &amp;#039;d&amp;#039;, &amp;#039;e&amp;#039;)&lt;br /&gt;
    print (str(tupla))&lt;br /&gt;
&lt;br /&gt;
    dic = {&amp;#039;Uno&amp;#039;: &amp;#039;Dos&amp;#039;, &amp;#039;Tres&amp;#039;: &amp;#039;Cuatro&amp;#039;}&lt;br /&gt;
    print (str(dic))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para devolver la suma de una secuencia usamos &amp;#039;&amp;#039;&amp;#039;sum&amp;#039;&amp;#039;&amp;#039;, esta, solo debe contener números.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    lista = [1, 2, 3]&lt;br /&gt;
    print (sum(lista))&lt;br /&gt;
&lt;br /&gt;
    tupla = [1, 2, 3, 4, 5]&lt;br /&gt;
    print (sum(tupla))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para convertir una secuencia en tupla usamos &amp;#039;&amp;#039;&amp;#039;tuple&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    lista = [1, 2, 3]&lt;br /&gt;
    print (tuple(lista))&lt;br /&gt;
&lt;br /&gt;
    cadena = &amp;#039;Apache&amp;#039;&lt;br /&gt;
    print (tuple(cadena))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ámbito de variables ==&lt;br /&gt;
&lt;br /&gt;
El ámbito de las variables se refiere al espacio donde son validas, al lugar desde donde se puede &amp;#039;&amp;#039;&amp;#039;verlas&amp;#039;&amp;#039;&amp;#039; y hacer referencia a ellas y donde no, veamos el siguiente ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    macro_uno()&lt;br /&gt;
    macro_dos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def macro_uno():&lt;br /&gt;
    var = &amp;#039;Hola&amp;#039;&lt;br /&gt;
    print (var)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def macro_dos():&lt;br /&gt;
    var = &amp;#039;Mundo&amp;#039;&lt;br /&gt;
    print (var)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota, al ejecutar, que las variables, aun teniendo el mismo nombre, se muestran correctamente, a este ámbito se le llama local. Para usar la misma variable en diferentes macros, asignala a nivel de modulo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
var2 = &amp;#039;pyUNO&amp;#039;&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    print (var2)&lt;br /&gt;
    macro_uno()&lt;br /&gt;
    macro_dos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def macro_uno():&lt;br /&gt;
    var = &amp;#039;Hola&amp;#039;&lt;br /&gt;
    print (var)&lt;br /&gt;
    print (var2)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def macro_dos():&lt;br /&gt;
    var = &amp;#039;Mundo&amp;#039;&lt;br /&gt;
    print (var)&lt;br /&gt;
    print (var2)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos más opciones y alternativas para ver nuestras variables.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Excepciones ==&lt;br /&gt;
&lt;br /&gt;
Los errores, presentes en toda actividad, son susceptibles de capturarse, Python nos provee de la estructura &amp;#039;&amp;#039;&amp;#039;try...except&amp;#039;&amp;#039;&amp;#039; para esto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def errores():&lt;br /&gt;
    # intentamos mostrar una variable no declarada&lt;br /&gt;
    print texto&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, controlemos este error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def errores():&lt;br /&gt;
    try:&lt;br /&gt;
        print texto&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;Variable no declarada&amp;#039;)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, un error diferente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def errores():&lt;br /&gt;
    try:&lt;br /&gt;
        r = 10 / 0&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;División entre cero&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, los dos errores en la misma macro.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def errores():&lt;br /&gt;
    try:&lt;br /&gt;
        r = 10 / 0&lt;br /&gt;
        print texto&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;No se que fallo&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para determinar el tipo de error, puedes complementar con el tipo de error de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def errores():&lt;br /&gt;
    try:&lt;br /&gt;
        r = 10 / 0&lt;br /&gt;
        print texto&lt;br /&gt;
    except (NameError, ZeroDivisionError):&lt;br /&gt;
        print (&amp;#039;Variable no declarada o división entre cero&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aunque lo mejor es tratar cada error de forma separada.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def errores():&lt;br /&gt;
    try:&lt;br /&gt;
        r = 10 / 0&lt;br /&gt;
        print texto&lt;br /&gt;
    except NameError:&lt;br /&gt;
        print (&amp;#039;Variable no declarada&amp;#039;)&lt;br /&gt;
    except ZeroDivisionError:&lt;br /&gt;
        print (&amp;#039;División entre cero&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota, que en el ejemplo anterior, siempre te mostrará el primer error capturado, por ello, es una mala practica intentar meter todo tu código entre líneas &amp;#039;&amp;#039;&amp;#039;try...except&amp;#039;&amp;#039;&amp;#039;, resistete a esto y trata de usar la captura de errores cuando realmente se requiera, esto, solo lo sabrás con la experiencia y consultando código de otros, algo, que podemos hacer con el software libre.&lt;br /&gt;
&lt;br /&gt;
La captura de errores también tiene una clausula &amp;#039;&amp;#039;&amp;#039;else&amp;#039;&amp;#039;&amp;#039; que se ejecuta solo cuando no ocurrió ningún error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def errores():&lt;br /&gt;
    try:&lt;br /&gt;
        texto = &amp;#039;Correct&amp;#039;&lt;br /&gt;
        r = 10 / 5&lt;br /&gt;
        print texto&lt;br /&gt;
    except ZeroDivisionError:&lt;br /&gt;
        print (&amp;#039;División entre cero&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Todo correcto&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y por ultimo, la clausula &amp;#039;&amp;#039;&amp;#039;finally&amp;#039;&amp;#039;&amp;#039; que se ejecuta siempre, haya ocurrido o no un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def errores():&lt;br /&gt;
    try:&lt;br /&gt;
        texto = &amp;#039;Correct&amp;#039;&lt;br /&gt;
        r = 10 / 0&lt;br /&gt;
        print texto&lt;br /&gt;
    except ZeroDivisionError:&lt;br /&gt;
        print (&amp;#039;División entre cero&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Todo correcto&amp;#039;)&lt;br /&gt;
    finally:&lt;br /&gt;
        print (&amp;#039;Siempe se ejecuta&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Python permite incluso declarar tus errores personalizados, tema que se verá más adelante.&lt;br /&gt;
&lt;br /&gt;
{{ES/Foro|macros}}&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/ConceptosIniciales&amp;diff=219947</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/ConceptosIniciales</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/ConceptosIniciales&amp;diff=219947"/>
		<updated>2013-05-09T15:38:26Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE: Conceptos iniciales}}&lt;br /&gt;
=== Organización de macros ===&lt;br /&gt;
Las macros en PyUNO, se organizan en archivos con extensión &amp;#039;&amp;#039;&amp;#039;py&amp;#039;&amp;#039;&amp;#039;, donde cada archivo es una biblioteca y cada función una macro. Más adelante veremos que también podemos organizarlas en clases.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Configurando nuestro entorno de trabajo ===&lt;br /&gt;
Dado que AOO no incorpora ningún editor para macros en Python, tenemos que hacer uso de algún editor externo. Para empezar, recomendamos el uso de [http://geany.org Geany], un IDE multiplataforma y multilenguaje que soporta Python.&lt;br /&gt;
&lt;br /&gt;
[[File:Pymacros001.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La configuración recomendada de trabajo para este editor es la siguiente:&lt;br /&gt;
&lt;br /&gt;
[[File:Pymacros002.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pymacros003.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pymacros004.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pymacros005.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como ya se vio en la introducción, nuestras macros pueden estar en tres diferentes lugares: sección mis macros, solo disponible para el usuario actual, sección macros del sistema, disponibles para todos los usuarios y dentro de un archivo de AOO. De aquí en adelante, asumiremos que estamos trabajando en la sección mis macros, pues en este sitio es el de más fácil acceso para todos.&lt;br /&gt;
&lt;br /&gt;
Dentro de la carpeta &amp;#039;&amp;#039;&amp;#039;python&amp;#039;&amp;#039;&amp;#039; crea un archivo que se llame &amp;#039;&amp;#039;&amp;#039;mismacros.py&amp;#039;&amp;#039;&amp;#039;, dentro de el escribe la siguiente macro y guardala:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
﻿import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas(): &lt;br /&gt;
    print (&amp;#039;Todo correcto&amp;#039;)&lt;br /&gt;
    return None&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, si estas usando Linux, abre una terminal de comandos y ejecuta Apache OpenOffice (AOO de aquí en adelante) con la siguiente instrucción:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ soffice -calc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ve a Herramientas -&amp;gt; Macros -&amp;gt; Ejecutar macros... y selecciona la macro &amp;#039;&amp;#039;&amp;#039;pruebas&amp;#039;&amp;#039;&amp;#039; recién creada.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:py_img_0001.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro y mira el resultado en la ventana del terminal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:py_img_0002.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si eres usuario de otro sistema operativo, puedes usar la siguiente alternativa para mostrar cualquier mensaje en pantalla. No te preocupes por ahora de estas líneas, cada una será usada y explicada en su momento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    msgbox (&amp;#039;Todo correcto&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    1,&lt;br /&gt;
                                    &amp;#039;UNOPython&amp;#039;,&lt;br /&gt;
                                    str(message))&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, verifica que funcione:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Py_img_0004.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo para probar nuestro entorno de trabajo, agrega dos nuevas macros y &amp;#039;&amp;#039;&amp;#039;llámalas&amp;#039;&amp;#039;&amp;#039; desde la primera, guarda y prueba. Recuerda de cambiar los &amp;#039;&amp;#039;&amp;#039;print&amp;#039;&amp;#039;&amp;#039; (puedes dejarlos si quieres) y usar nuestra macro &amp;#039;&amp;#039;&amp;#039;msgbox&amp;#039;&amp;#039;&amp;#039; si prefieres, también puedes ejecutar la macro &amp;#039;&amp;#039;&amp;#039;pruebas&amp;#039;&amp;#039;&amp;#039; con la combinación de teclas definida en el punto siguiente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    macro01()&lt;br /&gt;
    macro02()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def macro01():&lt;br /&gt;
    print (&amp;#039;Otra macro&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def macro02():&lt;br /&gt;
    print (&amp;#039;Una tercera&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por ultimo, para que sea sencillo &amp;#039;&amp;#039;&amp;#039;llamar&amp;#039;&amp;#039;&amp;#039; a esta macro, asignala a la combinación de teclas que más te guste y que, por supuesto, no este usada por AOO, se recomienda asignar esta combinación de teclas a todo AOO, para que puedas llamar la macro desde cualquier aplicación, como puedes ver en la siguiente imagen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Py_img_0003.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, mientras no se indique lo contrario, todas nuestras macros de ejemplo mostradas, serán &amp;#039;&amp;#039;&amp;#039;ejecutadas&amp;#039;&amp;#039;&amp;#039; desde la primer macro llamada &amp;#039;&amp;#039;&amp;#039;pruebas&amp;#039;&amp;#039;&amp;#039;, de preferencia, con una combinación de teclas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Utilidades de apoyo ===&lt;br /&gt;
Las siguientes herramientas, nos ayudarán en el desarrollo y estudio de macros con Python, por ahora, solo asegúrate de dejarlas trabajando como en los ejemplos, más adelante, explicaremos como trabajan y como puedes desarrollar las tuyas.&lt;br /&gt;
&lt;br /&gt;
Instala la siguiente extensión [http://extensions.services.openoffice.org/project/MRI MRI], esta maravillosa extensión nos ayudará a obtener toda la información de un &amp;#039;&amp;#039;&amp;#039;objeto&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{ES/Foro|macros}}&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/ConceptosIniciales&amp;diff=219946</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/ConceptosIniciales</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/ConceptosIniciales&amp;diff=219946"/>
		<updated>2013-05-09T15:37:25Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE: Conceptos iniciales}}&lt;br /&gt;
=== Organización de macros ===&lt;br /&gt;
Las macros en PyUNO, se organizan en archivos con extensión &amp;#039;&amp;#039;&amp;#039;py&amp;#039;&amp;#039;&amp;#039;, donde cada archivo es una biblioteca y cada función una macro. Más adelante veremos que también podemos organizarlas en clases.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Configurando nuestro entorno de trabajo ===&lt;br /&gt;
Dado que AOO no incorpora ningún editor para macros en Python, tenemos que hacer uso de algún editor externo. Para empezar, recomendamos el uso de [http://geany.org Geany], un IDE multiplataforma y multilenguaje que soporta Python.&lt;br /&gt;
&lt;br /&gt;
[[File:Pymacros001.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La configuración recomendada de trabajo para este editor es la siguiente:&lt;br /&gt;
&lt;br /&gt;
[[File:Pymacros002.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pymacros003.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pymacros004.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pymacros005.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como ya se vio en la introducción, nuestras macros pueden estar en tres diferentes lugares: sección mis macros, solo disponible para el usuario actual, sección macros del sistema, disponibles para todos los usuarios y dentro de un archivo de AOO. De aquí en adelante, asumiremos que estamos trabajando en la sección mis macros, pues en este sitio es el de más fácil acceso para todos.&lt;br /&gt;
&lt;br /&gt;
Dentro de la carpeta &amp;#039;&amp;#039;&amp;#039;python&amp;#039;&amp;#039;&amp;#039; crea un archivo que se llame &amp;#039;&amp;#039;&amp;#039;mismacros.py&amp;#039;&amp;#039;&amp;#039;, dentro de el escribe la siguiente macro y guardala:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
﻿import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas(): &lt;br /&gt;
	print (&amp;#039;Todo correcto&amp;#039;)&lt;br /&gt;
	return None&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, si estas usando Linux, abre una terminal de comandos y ejecuta Apache OpenOffice (AOO de aquí en adelante) con la siguiente instrucción:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ soffice -calc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ve a Herramientas -&amp;gt; Macros -&amp;gt; Ejecutar macros... y selecciona la macro &amp;#039;&amp;#039;&amp;#039;pruebas&amp;#039;&amp;#039;&amp;#039; recién creada.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:py_img_0001.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro y mira el resultado en la ventana del terminal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:py_img_0002.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si eres usuario de otro sistema operativo, puedes usar la siguiente alternativa para mostrar cualquier mensaje en pantalla. No te preocupes por ahora de estas líneas, cada una será usada y explicada en su momento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    msgbox (&amp;#039;Todo correcto&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    1,&lt;br /&gt;
                                    &amp;#039;UNOPython&amp;#039;,&lt;br /&gt;
                                    str(message))&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, verifica que funcione:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Py_img_0004.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo para probar nuestro entorno de trabajo, agrega dos nuevas macros y &amp;#039;&amp;#039;&amp;#039;llámalas&amp;#039;&amp;#039;&amp;#039; desde la primera, guarda y prueba. Recuerda de cambiar los &amp;#039;&amp;#039;&amp;#039;print&amp;#039;&amp;#039;&amp;#039; (puedes dejarlos si quieres) y usar nuestra macro &amp;#039;&amp;#039;&amp;#039;msgbox&amp;#039;&amp;#039;&amp;#039; si prefieres, también puedes ejecutar la macro &amp;#039;&amp;#039;&amp;#039;pruebas&amp;#039;&amp;#039;&amp;#039; con la combinación de teclas definida en el punto siguiente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    macro01()&lt;br /&gt;
    macro02()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def macro01():&lt;br /&gt;
    print (&amp;#039;Otra macro&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def macro02():&lt;br /&gt;
    print (&amp;#039;Una tercera&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por ultimo, para que sea sencillo &amp;#039;&amp;#039;&amp;#039;llamar&amp;#039;&amp;#039;&amp;#039; a esta macro, asignala a la combinación de teclas que más te guste y que, por supuesto, no este usada por AOO, se recomienda asignar esta combinación de teclas a todo AOO, para que puedas llamar la macro desde cualquier aplicación, como puedes ver en la siguiente imagen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Py_img_0003.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, mientras no se indique lo contrario, todas nuestras macros de ejemplo mostradas, serán &amp;#039;&amp;#039;&amp;#039;ejecutadas&amp;#039;&amp;#039;&amp;#039; desde la primer macro llamada &amp;#039;&amp;#039;&amp;#039;pruebas&amp;#039;&amp;#039;&amp;#039;, de preferencia, con una combinación de teclas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Utilidades de apoyo ===&lt;br /&gt;
Las siguientes herramientas, nos ayudarán en el desarrollo y estudio de macros con Python, por ahora, solo asegúrate de dejarlas trabajando como en los ejemplos, más adelante, explicaremos como trabajan y como puedes desarrollar las tuyas.&lt;br /&gt;
&lt;br /&gt;
Instala la siguiente extensión [http://extensions.services.openoffice.org/project/MRI MRI], esta maravillosa extensión nos ayudará a obtener toda la información de un &amp;#039;&amp;#039;&amp;#039;objeto&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{ES/Foro|macros}}&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Introduccion&amp;diff=219945</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Introduccion</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Introduccion&amp;diff=219945"/>
		<updated>2013-05-09T15:35:09Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE: Introducción}}&lt;br /&gt;
&lt;br /&gt;
=== ¿Que es PyUNO? ===&lt;br /&gt;
Apache OpenOffice (AOO de aquí en adelante), cuenta con la posibilidad de escribir macros en varios lenguajes interpretados, uno de ellos es [http://www.python.org Python]. El componente que nos da acceso a la Interfaz de programación de aplicaciones (IPA o API de aquí en adelante por sus siglas del inglés Application Programming Interface) de AOO con este lenguaje se le llama [http://www.openoffice.org/udk/python/python-bridge.html PyUNO].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ¿Que necesito saber? ===&lt;br /&gt;
Si bien trataremos de ir de menor a más detalle y complejidad, son necesarios un mínimo de requisitos para aprovechar estas notas y todo el poder de PyUNO, entre más familiarizado estés con la programación en general y con lenguajes como C,C++, Java y otros, te será más fácil adentrarte en PyUNO, si vienes de un lenguajes tipo Basic, requerirás un poco más de esfuerzo por las inercias inherentes a este lenguaje como su permisividad en su sintaxis.&lt;br /&gt;
* Conocimientos básicos de programación.&lt;br /&gt;
* Conocimientos básicos de programación con Python - Recomendamos los siguientes cursos para adentrarte en el lenguaje de programación Python.&lt;br /&gt;
** [http://mundogeek.net/tutorial-python Python para todos] excelente curso de Raúl González Duque.&lt;br /&gt;
** [http://www.maestrosdelweb.com/editorial/guia-python/ Guía de Python] excelente curso para iniciarse en Python por Eugenia Bahit&lt;br /&gt;
** [http://manuales.gfc.edu.co/python/tlc/thinkCSpy.es.pdf Aprenda a Pensar Como un Programador con Python] este libro tiene dos finalidades, enseñarte a pensar como un programador y enseñarte Python, puede ser una buena opción si vas empezando a programar. Puedes encontrar en tu buscador favorito muchos vínculos para descargar este libro en PDF.&lt;br /&gt;
* Conocimientos medios/avanzados de OpenOffice.org - Definitivamente, entre más domines la herramienta que queremos controlar por código, tendrás menos problemas y tu curva de aprendizaje será menos pronunciada, en los [http://forum.openoffice.org/es/forum/viewforum.php?f=50 foros oficiales de Apache OpenOffice], puedes resolver muchas de tus dudas, incluyendo claro esta, las que surgan durante tu aprendizaje con PyUNO. Procura tener siempre la ultima versión estable del programa.&lt;br /&gt;
* Y mucha practica, esfuerzo y dedicación, si alguien te ha dicho que programar es fácil, tal vez involuntariamente, pero te ha engañado, programar requiere, como decía Thomas Alva Edison: 1% inspiración y 99% transpiración.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ¿Donde empiezo? ===&lt;br /&gt;
Si tienes instalado correctamente OpenOffice.org (por ahora no importa el sistema operativo que uses), tienes todo lo necesario para empezar con PyUNO, para comprobarlo, veamos como ejecutar una macro que incluye OpenOffice.org de forma predeterminada. Abre Writer, es importante que sea Writer, esta macro solo funciona en este programa. Ve al menú Herramientas | Macros | Organizar macros | Python... tal como se muestra en la siguiente imagen.&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno001.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La acción anterior te mostrará el cuadro de diálogo &amp;quot;Macros de Python&amp;quot;, en este cuadro de diálogo, selecciona las siguientes opciones:&lt;br /&gt;
# Selecciona y expande la rama Macros de OpenOffice.org&lt;br /&gt;
# Selecciona y expande la subrama HelloWorld&lt;br /&gt;
# Selecciona la macro HelloWorldPython&lt;br /&gt;
# Da un clic en el botón de comando Ejecutar&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno002.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El resultado tiene que ser el siguiente:&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno003.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{ES/Foro|macros}}&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Introduccion&amp;diff=219944</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Introduccion</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Introduccion&amp;diff=219944"/>
		<updated>2013-05-09T15:33:37Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== ¿Que es PyUNO? ===&lt;br /&gt;
Apache OpenOffice (AOO de aquí en adelante), cuenta con la posibilidad de escribir macros en varios lenguajes interpretados, uno de ellos es [http://www.python.org Python]. El componente que nos da acceso a la Interfaz de programación de aplicaciones (IPA o API de aquí en adelante por sus siglas del inglés Application Programming Interface) de AOO con este lenguaje se le llama [http://www.openoffice.org/udk/python/python-bridge.html PyUNO].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ¿Que necesito saber? ===&lt;br /&gt;
Si bien trataremos de ir de menor a más detalle y complejidad, son necesarios un mínimo de requisitos para aprovechar estas notas y todo el poder de PyUNO, entre más familiarizado estés con la programación en general y con lenguajes como C,C++, Java y otros, te será más fácil adentrarte en PyUNO, si vienes de un lenguajes tipo Basic, requerirás un poco más de esfuerzo por las inercias inherentes a este lenguaje como su permisividad en su sintaxis.&lt;br /&gt;
* Conocimientos básicos de programación.&lt;br /&gt;
* Conocimientos básicos de programación con Python - Recomendamos los siguientes cursos para adentrarte en el lenguaje de programación Python.&lt;br /&gt;
** [http://mundogeek.net/tutorial-python Python para todos] excelente curso de Raúl González Duque.&lt;br /&gt;
** [http://www.maestrosdelweb.com/editorial/guia-python/ Guía de Python] excelente curso para iniciarse en Python por Eugenia Bahit&lt;br /&gt;
** [http://manuales.gfc.edu.co/python/tlc/thinkCSpy.es.pdf Aprenda a Pensar Como un Programador con Python] este libro tiene dos finalidades, enseñarte a pensar como un programador y enseñarte Python, puede ser una buena opción si vas empezando a programar. Puedes encontrar en tu buscador favorito muchos vínculos para descargar este libro en PDF.&lt;br /&gt;
* Conocimientos medios/avanzados de OpenOffice.org - Definitivamente, entre más domines la herramienta que queremos controlar por código, tendrás menos problemas y tu curva de aprendizaje será menos pronunciada, en los [http://forum.openoffice.org/es/forum/viewforum.php?f=50 foros oficiales de Apache OpenOffice], puedes resolver muchas de tus dudas, incluyendo claro esta, las que surgan durante tu aprendizaje con PyUNO. Procura tener siempre la ultima versión estable del programa.&lt;br /&gt;
* Y mucha practica, esfuerzo y dedicación, si alguien te ha dicho que programar es fácil, tal vez involuntariamente, pero te ha engañado, programar requiere, como decía Thomas Alva Edison: 1% inspiración y 99% transpiración.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ¿Donde empiezo? ===&lt;br /&gt;
Si tienes instalado correctamente OpenOffice.org (por ahora no importa el sistema operativo que uses), tienes todo lo necesario para empezar con PyUNO, para comprobarlo, veamos como ejecutar una macro que incluye OpenOffice.org de forma predeterminada. Abre Writer, es importante que sea Writer, esta macro solo funciona en este programa. Ve al menú Herramientas | Macros | Organizar macros | Python... tal como se muestra en la siguiente imagen.&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno001.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La acción anterior te mostrará el cuadro de diálogo &amp;quot;Macros de Python&amp;quot;, en este cuadro de diálogo, selecciona las siguientes opciones:&lt;br /&gt;
# Selecciona y expande la rama Macros de OpenOffice.org&lt;br /&gt;
# Selecciona y expande la subrama HelloWorld&lt;br /&gt;
# Selecciona la macro HelloWorldPython&lt;br /&gt;
# Da un clic en el botón de comando Ejecutar&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno002.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El resultado tiene que ser el siguiente:&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno003.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si por alguna razón no has obtenido este resultado o te muestra algún mensaje de error, háznoslo saber [http://forum.openoffice.org/es/forum/viewforum.php?f=50 aquí].&lt;br /&gt;
&lt;br /&gt;
[[Category:Manuales]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/MiPrimeraMacro&amp;diff=219943</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/MiPrimeraMacro</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/MiPrimeraMacro&amp;diff=219943"/>
		<updated>2013-05-09T15:30:51Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Mi primer macro}}&lt;br /&gt;
=== Mi primer macro ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos a crear nuestra primer macro con Python con el clásico &amp;quot;Hola Mundo&amp;quot;, que, acabas de ver en acción, pero lo haremos paso a paso y esta vez usaremos una hoja de calculo que tienes que tener activa cuando ejecutes las pruebas.&lt;br /&gt;
* Abre tu editor de texto plano favorito:&lt;br /&gt;
** En Linux; geany, gedit, kate, vi, nano, etc, etc...&lt;br /&gt;
** En Windows puedes usar el Block de notas, presiona WIN+R y escribes &amp;quot;notepad&amp;quot; (sin las comillas)&lt;br /&gt;
** En Mac OS puedes usar TextMate que ahora es software libre.&lt;br /&gt;
&lt;br /&gt;
Escribe o copia el siguiente código:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
﻿import uno&lt;br /&gt;
&lt;br /&gt;
def HolaMundo():&lt;br /&gt;
	# Accedemos al modelo del documento actual &lt;br /&gt;
	model = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
	# Accedemos a la primer hoja del documento&lt;br /&gt;
	hoja = model.getSheets().getByIndex(0)&lt;br /&gt;
	# Accedemos a la celda A1 de la hoja&lt;br /&gt;
	celda = hoja.getCellRangeByName(&amp;quot;A1&amp;quot;)&lt;br /&gt;
	# Escribimos en la celda&lt;br /&gt;
	celda.setString(&amp;quot;Hola Mundo en Python&amp;quot;)&lt;br /&gt;
	return None&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aquí, es importante mencionar que Python es muy estricto con la indentación, algunos procesadores de texto plano insertan espacios en lugar de tabulaciones, Python puede trabajar sin problemas con unos y otros, el único requisito es que sean consistentes, asegúrate de que estas efectivamente insertando tabulaciones o espacios según prefieras trabajar en cada línea de código. Guarda este código como &amp;#039;&amp;#039;&amp;#039;holamundo.py&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== ¿Dónde se guardan las macros? ===&lt;br /&gt;
Dependiendo del sistema operativo y versión de Apache OpenOffice que uses (recomendamos usar siempre la ultima versión estable), las macros pueden guardarse en:&lt;br /&gt;
* La carpeta del usuario, macros solo disponibles para dicho &amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;:&lt;br /&gt;
** En Linux y OOo 3.4 en: /home/&amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;/config/.openoffice.org/3/user/Scripts/python&lt;br /&gt;
** En Windows 7 y OOo 3.4 en: C:\Users\&amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;\AppData\Roaming\OpenOffice.org\3\user\Scripts\python&lt;br /&gt;
** En Windows XP y OOo 3.4 en: C:\Documents and Settings\&amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;\Datos de programa\OpenOffice.org\3\user\Scripts\python&lt;br /&gt;
&lt;br /&gt;
* La carpeta del programa, macros disponibles para todos los usuarios:&lt;br /&gt;
** En Linux y OOo 3.4 en: /opt/openoffice.org/basis3.2/share/Scripts/python&lt;br /&gt;
** En Windows 7 y OOo 3.4 en: C:\Program Files\OpenOffice.org 3\Basis\share\Scripts\python&lt;br /&gt;
** En Windows XP y OOo 3.4 en: C:\Archivos de programa\OpenOffice.org 3\Basis\share\Scripts\python&lt;br /&gt;
&lt;br /&gt;
Estas rutas son las predeterminadas, pueden cambiar en instalaciones personalizadas o en versiones de Apache OpenOffice alternas a la oficial. Nuestra recomendación es que siempre uses e instales la ultima versión estable oficial que puedes descargar desde [http://es.openoffice.org/ aquí].&lt;br /&gt;
En el caso de las carpetas de usuario, es posible que no encuentres la carpeta &amp;#039;&amp;#039;&amp;#039;python&amp;#039;&amp;#039;&amp;#039;, si es el caso, créala manualmente, escribe el nombre de esta carpeta en minúsculas. En la carpeta del programa, para escribir en ella, en Linux necesitaras permisos de administrador (root), en Windows, dependerá de las políticas de acceso del sistema.&lt;br /&gt;
&lt;br /&gt;
* Dentro del documento:&lt;br /&gt;
Un archivo de Apache OpenOffice es realmente un archivo ZIP con una estructura determinada, por lo que puedes, también, manipularlos con tu programa favorito para este tipo de archivos. Crea y guarda un archivo nuevo de Calc, ciérralo y ábrelo ahora con tu programa ZIP. Crea las carpetas Scripts/python en la raíz del archivo. Dentro de esta carpeta agrega los archivos con las macros, para nuestro ejemplo &amp;#039;&amp;#039;&amp;#039;holamundo.py&amp;#039;&amp;#039;&amp;#039;. Ahora, edita el archivo manifest.xml que esta en la carpeta META-INF, a cuyo contenido agrégale las siguientes líneas, justo antes del cierre &amp;#039;&amp;#039;&amp;#039;&amp;lt;/manifest:manifest&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=xml&amp;gt;&lt;br /&gt;
 &amp;lt;manifest:file-entry manifest:media-type=&amp;quot;&amp;quot; manifest:full-path=&amp;quot;Scripts/python/holamundo.py&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;manifest:file-entry manifest:media-type=&amp;quot;application/binary&amp;quot; manifest:full-path=&amp;quot;Scripts/python/&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;manifest:file-entry manifest:media-type=&amp;quot;application/binary&amp;quot; manifest:full-path=&amp;quot;Scripts/&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/manifest:manifest&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Guarda los cambios y cierra el archivo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ejecutando nuestra macro ===&lt;br /&gt;
El archivo &amp;#039;&amp;#039;&amp;#039;holamundo.py&amp;#039;&amp;#039;&amp;#039; copialo a cualquiera de las ubicaciones vistas en el apartado anterior, como ejemplo, nosotros lo hemos copiado en las tres ubicaciones, por lo que al ir al menú Herramientas | Macros | Organizar macros | Python..., podrás ver la macro en las siguientes secciones:&lt;br /&gt;
&lt;br /&gt;
# El archivo del usuario Mis Macros...&lt;br /&gt;
# Las macros del programa&lt;br /&gt;
# Dentro del documento&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno004.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Selecciona cualquiera de las tres y presiona Ejecutar, el resultado, debe ser igual al de la siguiente imagen:&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno005.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{ES/Foro|macros}}&lt;br /&gt;
&lt;br /&gt;
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/MiPrimeraMacro&amp;diff=219942</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/MiPrimeraMacro</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/MiPrimeraMacro&amp;diff=219942"/>
		<updated>2013-05-09T15:30:09Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Mi primer macro}}&lt;br /&gt;
=== Mi primer macro ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos a crear nuestra primer macro con Python con el clásico &amp;quot;Hola Mundo&amp;quot;, que, acabas de ver en acción, pero lo haremos paso a paso y esta vez usaremos una hoja de calculo que tienes que tener activa cuando ejecutes las pruebas.&lt;br /&gt;
* Abre tu editor de texto plano favorito:&lt;br /&gt;
** En Linux; geany, gedit, kate, vi, nano, etc, etc...&lt;br /&gt;
** En Windows puedes usar el Block de notas, presiona WIN+R y escribes &amp;quot;notepad&amp;quot; (sin las comillas)&lt;br /&gt;
** En Mac OS puedes usar TextMate que ahora es software libre.&lt;br /&gt;
&lt;br /&gt;
Escribe o copia el siguiente código:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
﻿import uno&lt;br /&gt;
&lt;br /&gt;
def HolaMundo():&lt;br /&gt;
	# Accedemos al modelo del documento actual &lt;br /&gt;
	model = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
	# Accedemos a la primer hoja del documento&lt;br /&gt;
	hoja = model.getSheets().getByIndex(0)&lt;br /&gt;
	# Accedemos a la celda A1 de la hoja&lt;br /&gt;
	celda = hoja.getCellRangeByName(&amp;quot;A1&amp;quot;)&lt;br /&gt;
	# Escribimos en la celda&lt;br /&gt;
	celda.setString(&amp;quot;Hola Mundo en Python&amp;quot;)&lt;br /&gt;
	return None&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aquí, es importante mencionar que Python es muy estricto con la indentación, algunos procesadores de texto plano insertan espacios en lugar de tabulaciones, Python puede trabajar sin problemas con unos y otros, el único requisito es que sean consistentes, asegúrate de que estas efectivamente insertando tabulaciones o espacios según prefieras trabajar en cada línea de código. Guarda este código como &amp;#039;&amp;#039;&amp;#039;holamundo.py&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== ¿Dónde se guardan las macros? ===&lt;br /&gt;
Dependiendo del sistema operativo y versión de Apache OpenOffice que uses (recomendamos usar siempre la ultima versión estable), las macros pueden guardarse en:&lt;br /&gt;
* La carpeta del usuario, macros solo disponibles para dicho &amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;:&lt;br /&gt;
** En Linux y OOo 3.4 en: /home/&amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;/config/.openoffice.org/3/user/Scripts/python&lt;br /&gt;
** En Windows 7 y OOo 3.4 en: C:\Users\&amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;\AppData\Roaming\OpenOffice.org\3\user\Scripts\python&lt;br /&gt;
** En Windows XP y OOo 3.4 en: C:\Documents and Settings\&amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;\Datos de programa\OpenOffice.org\3\user\Scripts\python&lt;br /&gt;
&lt;br /&gt;
* La carpeta del programa, macros disponibles para todos los usuarios:&lt;br /&gt;
** En Linux y OOo 3.4 en: /opt/openoffice.org/basis3.2/share/Scripts/python&lt;br /&gt;
** En Windows 7 y OOo 3.4 en: C:\Program Files\OpenOffice.org 3\Basis\share\Scripts\python&lt;br /&gt;
** En Windows XP y OOo 3.4 en: C:\Archivos de programa\OpenOffice.org 3\Basis\share\Scripts\python&lt;br /&gt;
&lt;br /&gt;
Estas rutas son las predeterminadas, pueden cambiar en instalaciones personalizadas o en versiones de Apache OpenOffice alternas a la oficial. Nuestra recomendación es que siempre uses e instales la ultima versión estable oficial que puedes descargar desde [http://es.openoffice.org/ aquí].&lt;br /&gt;
En el caso de las carpetas de usuario, es posible que no encuentres la carpeta &amp;#039;&amp;#039;&amp;#039;python&amp;#039;&amp;#039;&amp;#039;, si es el caso, créala manualmente, escribe el nombre de esta carpeta en minúsculas. En la carpeta del programa, para escribir en ella, en Linux necesitaras permisos de administrador (root), en Windows, dependerá de las políticas de acceso del sistema.&lt;br /&gt;
&lt;br /&gt;
* Dentro del documento:&lt;br /&gt;
Un archivo de Apache OpenOffice es realmente un archivo ZIP con una estructura determinada, por lo que puedes, también, manipularlos con tu programa favorito para este tipo de archivos. Crea y guarda un archivo nuevo de Calc, ciérralo y ábrelo ahora con tu programa ZIP. Crea las carpetas Scripts/python en la raíz del archivo. Dentro de esta carpeta agrega los archivos con las macros, para nuestro ejemplo &amp;#039;&amp;#039;&amp;#039;holamundo.py&amp;#039;&amp;#039;&amp;#039;. Ahora, edita el archivo manifest.xml que esta en la carpeta META-INF, a cuyo contenido agrégale las siguientes líneas, justo antes del cierre &amp;#039;&amp;#039;&amp;#039;&amp;lt;/manifest:manifest&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=xml&amp;gt;&lt;br /&gt;
 &amp;lt;manifest:file-entry manifest:media-type=&amp;quot;&amp;quot; manifest:full-path=&amp;quot;Scripts/python/holamundo.py&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;manifest:file-entry manifest:media-type=&amp;quot;application/binary&amp;quot; manifest:full-path=&amp;quot;Scripts/python/&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;manifest:file-entry manifest:media-type=&amp;quot;application/binary&amp;quot; manifest:full-path=&amp;quot;Scripts/&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/manifest:manifest&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Guarda los cambios y cierra el archivo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ejecutando nuestra macro ===&lt;br /&gt;
El archivo &amp;#039;&amp;#039;&amp;#039;holamundo.py&amp;#039;&amp;#039;&amp;#039; copialo a cualquiera de las ubicaciones vistas en el apartado anterior, como ejemplo, nosotros lo hemos copiado en las tres ubicaciones, por lo que al ir al menú Herramientas | Macros | Organizar macros | Python..., podrás ver la macro en las siguientes secciones:&lt;br /&gt;
&lt;br /&gt;
# El archivo del usuario Mis Macros...&lt;br /&gt;
# Las macros del programa&lt;br /&gt;
# Dentro del documento&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno004.png]]&lt;br /&gt;
&lt;br /&gt;
Selecciona cualquiera de las tres y presiona Ejecutar, el resultado, debe ser igual al de la siguiente imagen:&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno005.png]]&lt;br /&gt;
&lt;br /&gt;
Cualquier duda, comentario o error, háznoslo saber [http://forum.openoffice.org/es/forum/viewforum.php?f=50 aquí].&lt;br /&gt;
&lt;br /&gt;
[[Category:Manuales]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/MiPrimeraMacro&amp;diff=219941</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/MiPrimeraMacro</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/MiPrimeraMacro&amp;diff=219941"/>
		<updated>2013-05-09T15:29:28Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Mi primera macro}}&lt;br /&gt;
=== Mi primer macro ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos a crear nuestra primer macro con Python con el clásico &amp;quot;Hola Mundo&amp;quot;, que, acabas de ver en acción, pero lo haremos paso a paso y esta vez usaremos una hoja de calculo que tienes que tener activa cuando ejecutes las pruebas.&lt;br /&gt;
* Abre tu editor de texto plano favorito:&lt;br /&gt;
** En Linux; geany, gedit, kate, vi, nano, etc, etc...&lt;br /&gt;
** En Windows puedes usar el Block de notas, presiona WIN+R y escribes &amp;quot;notepad&amp;quot; (sin las comillas)&lt;br /&gt;
** En Mac OS puedes usar TextMate que ahora es software libre.&lt;br /&gt;
&lt;br /&gt;
Escribe o copia el siguiente código:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
﻿import uno&lt;br /&gt;
&lt;br /&gt;
def HolaMundo():&lt;br /&gt;
	# Accedemos al modelo del documento actual &lt;br /&gt;
	model = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
	# Accedemos a la primer hoja del documento&lt;br /&gt;
	hoja = model.getSheets().getByIndex(0)&lt;br /&gt;
	# Accedemos a la celda A1 de la hoja&lt;br /&gt;
	celda = hoja.getCellRangeByName(&amp;quot;A1&amp;quot;)&lt;br /&gt;
	# Escribimos en la celda&lt;br /&gt;
	celda.setString(&amp;quot;Hola Mundo en Python&amp;quot;)&lt;br /&gt;
	return None&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aquí, es importante mencionar que Python es muy estricto con la indentación, algunos procesadores de texto plano insertan espacios en lugar de tabulaciones, Python puede trabajar sin problemas con unos y otros, el único requisito es que sean consistentes, asegúrate de que estas efectivamente insertando tabulaciones o espacios según prefieras trabajar en cada línea de código. Guarda este código como &amp;#039;&amp;#039;&amp;#039;holamundo.py&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== ¿Dónde se guardan las macros? ===&lt;br /&gt;
Dependiendo del sistema operativo y versión de Apache OpenOffice que uses (recomendamos usar siempre la ultima versión estable), las macros pueden guardarse en:&lt;br /&gt;
* La carpeta del usuario, macros solo disponibles para dicho &amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;:&lt;br /&gt;
** En Linux y OOo 3.4 en: /home/&amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;/config/.openoffice.org/3/user/Scripts/python&lt;br /&gt;
** En Windows 7 y OOo 3.4 en: C:\Users\&amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;\AppData\Roaming\OpenOffice.org\3\user\Scripts\python&lt;br /&gt;
** En Windows XP y OOo 3.4 en: C:\Documents and Settings\&amp;#039;&amp;#039;&amp;#039;USUARIO&amp;#039;&amp;#039;&amp;#039;\Datos de programa\OpenOffice.org\3\user\Scripts\python&lt;br /&gt;
&lt;br /&gt;
* La carpeta del programa, macros disponibles para todos los usuarios:&lt;br /&gt;
** En Linux y OOo 3.4 en: /opt/openoffice.org/basis3.2/share/Scripts/python&lt;br /&gt;
** En Windows 7 y OOo 3.4 en: C:\Program Files\OpenOffice.org 3\Basis\share\Scripts\python&lt;br /&gt;
** En Windows XP y OOo 3.4 en: C:\Archivos de programa\OpenOffice.org 3\Basis\share\Scripts\python&lt;br /&gt;
&lt;br /&gt;
Estas rutas son las predeterminadas, pueden cambiar en instalaciones personalizadas o en versiones de Apache OpenOffice alternas a la oficial. Nuestra recomendación es que siempre uses e instales la ultima versión estable oficial que puedes descargar desde [http://es.openoffice.org/ aquí].&lt;br /&gt;
En el caso de las carpetas de usuario, es posible que no encuentres la carpeta &amp;#039;&amp;#039;&amp;#039;python&amp;#039;&amp;#039;&amp;#039;, si es el caso, créala manualmente, escribe el nombre de esta carpeta en minúsculas. En la carpeta del programa, para escribir en ella, en Linux necesitaras permisos de administrador (root), en Windows, dependerá de las políticas de acceso del sistema.&lt;br /&gt;
&lt;br /&gt;
* Dentro del documento:&lt;br /&gt;
Un archivo de Apache OpenOffice es realmente un archivo ZIP con una estructura determinada, por lo que puedes, también, manipularlos con tu programa favorito para este tipo de archivos. Crea y guarda un archivo nuevo de Calc, ciérralo y ábrelo ahora con tu programa ZIP. Crea las carpetas Scripts/python en la raíz del archivo. Dentro de esta carpeta agrega los archivos con las macros, para nuestro ejemplo &amp;#039;&amp;#039;&amp;#039;holamundo.py&amp;#039;&amp;#039;&amp;#039;. Ahora, edita el archivo manifest.xml que esta en la carpeta META-INF, a cuyo contenido agrégale las siguientes líneas, justo antes del cierre &amp;#039;&amp;#039;&amp;#039;&amp;lt;/manifest:manifest&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=xml&amp;gt;&lt;br /&gt;
 &amp;lt;manifest:file-entry manifest:media-type=&amp;quot;&amp;quot; manifest:full-path=&amp;quot;Scripts/python/holamundo.py&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;manifest:file-entry manifest:media-type=&amp;quot;application/binary&amp;quot; manifest:full-path=&amp;quot;Scripts/python/&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;manifest:file-entry manifest:media-type=&amp;quot;application/binary&amp;quot; manifest:full-path=&amp;quot;Scripts/&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/manifest:manifest&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Guarda los cambios y cierra el archivo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ejecutando nuestra macro ===&lt;br /&gt;
El archivo &amp;#039;&amp;#039;&amp;#039;holamundo.py&amp;#039;&amp;#039;&amp;#039; copialo a cualquiera de las ubicaciones vistas en el apartado anterior, como ejemplo, nosotros lo hemos copiado en las tres ubicaciones, por lo que al ir al menú Herramientas | Macros | Organizar macros | Python..., podrás ver la macro en las siguientes secciones:&lt;br /&gt;
&lt;br /&gt;
# El archivo del usuario Mis Macros...&lt;br /&gt;
# Las macros del programa&lt;br /&gt;
# Dentro del documento&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno004.png]]&lt;br /&gt;
&lt;br /&gt;
Selecciona cualquiera de las tres y presiona Ejecutar, el resultado, debe ser igual al de la siguiente imagen:&lt;br /&gt;
&lt;br /&gt;
[[File:pyuno005.png]]&lt;br /&gt;
&lt;br /&gt;
Cualquier duda, comentario o error, háznoslo saber [http://forum.openoffice.org/es/forum/viewforum.php?f=50 aquí].&lt;br /&gt;
&lt;br /&gt;
[[Category:Manuales]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219938</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219938"/>
		<updated>2013-05-09T04:38:30Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Copiando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Otra hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, hojas.getCount())&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por &amp;#039;&amp;#039;&amp;#039;getCount()&amp;#039;&amp;#039;&amp;#039; pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    indice = activa.getRangeAddress().Sheet &lt;br /&gt;
    msgbox(u&amp;#039;El índice de la hoja activa es: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir en una submacro. Nota como estamos estableciendo un &amp;#039;&amp;#039;&amp;#039;valor por default&amp;#039;&amp;#039;&amp;#039; para el ultimo argumento que será la posición deseada para la nueva hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nueva_hoja(doc, nombre, pos=0):&lt;br /&gt;
    hojas = doc.getSheets() &lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
        indice = activa.getRangeAddress().Sheet&lt;br /&gt;
        if pos == 1:&lt;br /&gt;
            pos = indice&lt;br /&gt;
        elif pos == 2:&lt;br /&gt;
            pos = indice + 1&lt;br /&gt;
        elif pos &amp;gt; 2:&lt;br /&gt;
            pos = hojas.getCount()&lt;br /&gt;
        hojas.insertNewByName(nombre, pos)&lt;br /&gt;
        return hojas.getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora ya podemos insertar una nueva hoja en la posición que sea.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al inicio&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Antes de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 1)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Despues de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 2)&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al final&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 3)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
Para borrar hojas, usamos el método &amp;#039;&amp;#039;&amp;#039;removeByName(Nombre)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Nombre&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; es el nombre de la hoja que queremos borrar, no esta de más recomendarte usar con cuidado el borrado de hojas, aunque algo que me gusta mucho de AOO, es que muchas de las acciones que hacemos por código, son susceptibles de deshacerse de forma normal con la barra de herramientas o con CTRL+Z, el borrado de hojas es una de ellas, compruébalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(&amp;#039;Hoja3&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto no puedes borrar una hoja que no exista, así que verifícalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes borrar la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(activa.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior hasta que no quede ni una, claro, no te dejara por que un documento de hoja de calculo por lo menos debe de tener una hoja, para evitar el error que te da al tratar de borrar la ultima hoja, valida que siempre quede más de una.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;borrame&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and hojas.getCount() &amp;gt; 1:&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;La hoja no existe o solo queda una&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
Para mover hojas usamos el método &amp;#039;&amp;#039;&amp;#039;moveByName(NombreHoja, PosicionNueva)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;NombreHoja&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; tiene que ser el nombre de una hoja existente. En el siguiente ejemplo movemos la hoja al inicio.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, la movemos al final.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, hojas.getCount())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos  a hacer algo muy divertido, como ya sabemos obtener los nombres e índices de cada hoja, y ahora hemos aprendido a mover hojas, hagamos una macro que nos ordene alfabéticamente nuestras hojas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = sorted(hojas.getElementNames())&lt;br /&gt;
    for i,v in enumerate(nombres):&lt;br /&gt;
        hojas.moveByName(v, i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
Para copiar hojas usamos el método &amp;#039;&amp;#039;&amp;#039;copyByName(NombreHoja, NombreNuevo, Posicion)&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.copyByName(&amp;#039;Hoja2&amp;#039;, &amp;#039;Nueva hoja2&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto el nombre de la hoja a copiar debe de existir y el nombre nuevo de la hoja no debe existir, lo mejor, es evaluarlo antes.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Datos&amp;#039;&lt;br /&gt;
    nombre_nuevo = &amp;#039;Datos nuevos&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and not hojas.hasByName(nombre_nuevo):&lt;br /&gt;
        hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se copio la hoja&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos intentar copiar una hoja y asegurarnos de que el nombre no exista, tomando como base el nombre actual de la hoja, por ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = doc.getCurrentController().getActiveSheet().getName()&lt;br /&gt;
    co1 = 1&lt;br /&gt;
    nombre_nuevo = &amp;#039;%s_%s&amp;#039; % (nombre, co1)&lt;br /&gt;
    while hojas.hasByName(nombre_nuevo):&lt;br /&gt;
        co1 += 1&lt;br /&gt;
        nombre_nuevo = &amp;#039;%s_%s&amp;#039; % (nombre, co1)&lt;br /&gt;
    hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())&lt;br /&gt;
    hoja = hojas.getByName(nombre_nuevo)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(hoja)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219937</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219937"/>
		<updated>2013-05-09T04:13:02Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Moviendo hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Otra hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, hojas.getCount())&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por &amp;#039;&amp;#039;&amp;#039;getCount()&amp;#039;&amp;#039;&amp;#039; pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    indice = activa.getRangeAddress().Sheet &lt;br /&gt;
    msgbox(u&amp;#039;El índice de la hoja activa es: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir en una submacro. Nota como estamos estableciendo un &amp;#039;&amp;#039;&amp;#039;valor por default&amp;#039;&amp;#039;&amp;#039; para el ultimo argumento que será la posición deseada para la nueva hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nueva_hoja(doc, nombre, pos=0):&lt;br /&gt;
    hojas = doc.getSheets() &lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
        indice = activa.getRangeAddress().Sheet&lt;br /&gt;
        if pos == 1:&lt;br /&gt;
            pos = indice&lt;br /&gt;
        elif pos == 2:&lt;br /&gt;
            pos = indice + 1&lt;br /&gt;
        elif pos &amp;gt; 2:&lt;br /&gt;
            pos = hojas.getCount()&lt;br /&gt;
        hojas.insertNewByName(nombre, pos)&lt;br /&gt;
        return hojas.getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora ya podemos insertar una nueva hoja en la posición que sea.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al inicio&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Antes de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 1)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Despues de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 2)&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al final&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 3)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
Para borrar hojas, usamos el método &amp;#039;&amp;#039;&amp;#039;removeByName(Nombre)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Nombre&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; es el nombre de la hoja que queremos borrar, no esta de más recomendarte usar con cuidado el borrado de hojas, aunque algo que me gusta mucho de AOO, es que muchas de las acciones que hacemos por código, son susceptibles de deshacerse de forma normal con la barra de herramientas o con CTRL+Z, el borrado de hojas es una de ellas, compruébalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(&amp;#039;Hoja3&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto no puedes borrar una hoja que no exista, así que verifícalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes borrar la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(activa.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior hasta que no quede ni una, claro, no te dejara por que un documento de hoja de calculo por lo menos debe de tener una hoja, para evitar el error que te da al tratar de borrar la ultima hoja, valida que siempre quede más de una.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;borrame&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and hojas.getCount() &amp;gt; 1:&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;La hoja no existe o solo queda una&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
Para mover hojas usamos el método &amp;#039;&amp;#039;&amp;#039;moveByName(NombreHoja, PosicionNueva)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;NombreHoja&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; tiene que ser el nombre de una hoja existente. En el siguiente ejemplo movemos la hoja al inicio.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, la movemos al final.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, hojas.getCount())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos  a hacer algo muy divertido, como ya sabemos obtener los nombres e índices de cada hoja, y ahora hemos aprendido a mover hojas, hagamos una macro que nos ordene alfabéticamente nuestras hojas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = sorted(hojas.getElementNames())&lt;br /&gt;
    for i,v in enumerate(nombres):&lt;br /&gt;
        hojas.moveByName(v, i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219936</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219936"/>
		<updated>2013-05-09T04:11:42Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Moviendo hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Otra hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, hojas.getCount())&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por &amp;#039;&amp;#039;&amp;#039;getCount()&amp;#039;&amp;#039;&amp;#039; pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    indice = activa.getRangeAddress().Sheet &lt;br /&gt;
    msgbox(u&amp;#039;El índice de la hoja activa es: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir en una submacro. Nota como estamos estableciendo un &amp;#039;&amp;#039;&amp;#039;valor por default&amp;#039;&amp;#039;&amp;#039; para el ultimo argumento que será la posición deseada para la nueva hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nueva_hoja(doc, nombre, pos=0):&lt;br /&gt;
    hojas = doc.getSheets() &lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
        indice = activa.getRangeAddress().Sheet&lt;br /&gt;
        if pos == 1:&lt;br /&gt;
            pos = indice&lt;br /&gt;
        elif pos == 2:&lt;br /&gt;
            pos = indice + 1&lt;br /&gt;
        elif pos &amp;gt; 2:&lt;br /&gt;
            pos = hojas.getCount()&lt;br /&gt;
        hojas.insertNewByName(nombre, pos)&lt;br /&gt;
        return hojas.getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora ya podemos insertar una nueva hoja en la posición que sea.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al inicio&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Antes de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 1)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Despues de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 2)&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al final&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 3)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
Para borrar hojas, usamos el método &amp;#039;&amp;#039;&amp;#039;removeByName(Nombre)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Nombre&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; es el nombre de la hoja que queremos borrar, no esta de más recomendarte usar con cuidado el borrado de hojas, aunque algo que me gusta mucho de AOO, es que muchas de las acciones que hacemos por código, son susceptibles de deshacerse de forma normal con la barra de herramientas o con CTRL+Z, el borrado de hojas es una de ellas, compruébalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(&amp;#039;Hoja3&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto no puedes borrar una hoja que no exista, así que verifícalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes borrar la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(activa.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior hasta que no quede ni una, claro, no te dejara por que un documento de hoja de calculo por lo menos debe de tener una hoja, para evitar el error que te da al tratar de borrar la ultima hoja, valida que siempre quede más de una.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;borrame&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and hojas.getCount() &amp;gt; 1:&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;La hoja no existe o solo queda una&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
Para mover hojas usamos el método &amp;#039;&amp;#039;&amp;#039;moveByName(NombreHoja, PosicionNueva)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;NombreHoja&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; tiene que ser el nombre de una hoja existente. En el siguiente ejemplo movemos la hoja al inicio.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, la movemos al final.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.moveByName(&amp;#039;Hoja3&amp;#039;, hojas.getCount())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos  a hacer algo muy divertido, como ya sabemos obtener los nombres e índices de cada hoja, y ahora hemos aprendido a mover hojas, hagamos una macro que nos ordene alfabéticamente nuestras hojas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = sorted(hojas.getElementNames())&lt;br /&gt;
    for i,v in enumerate(nombre):&lt;br /&gt;
        hojas.moveByName(v, i)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219934</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219934"/>
		<updated>2013-05-09T04:01:28Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Borrando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Otra hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, hojas.getCount())&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por &amp;#039;&amp;#039;&amp;#039;getCount()&amp;#039;&amp;#039;&amp;#039; pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    indice = activa.getRangeAddress().Sheet &lt;br /&gt;
    msgbox(u&amp;#039;El índice de la hoja activa es: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir en una submacro. Nota como estamos estableciendo un &amp;#039;&amp;#039;&amp;#039;valor por default&amp;#039;&amp;#039;&amp;#039; para el ultimo argumento que será la posición deseada para la nueva hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nueva_hoja(doc, nombre, pos=0):&lt;br /&gt;
    hojas = doc.getSheets() &lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
        indice = activa.getRangeAddress().Sheet&lt;br /&gt;
        if pos == 1:&lt;br /&gt;
            pos = indice&lt;br /&gt;
        elif pos == 2:&lt;br /&gt;
            pos = indice + 1&lt;br /&gt;
        elif pos &amp;gt; 2:&lt;br /&gt;
            pos = hojas.getCount()&lt;br /&gt;
        hojas.insertNewByName(nombre, pos)&lt;br /&gt;
        return hojas.getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora ya podemos insertar una nueva hoja en la posición que sea.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al inicio&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Antes de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 1)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Despues de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 2)&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al final&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 3)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
Para borrar hojas, usamos el método &amp;#039;&amp;#039;&amp;#039;removeByName(Nombre)&amp;#039;&amp;#039;&amp;#039;, donde &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Nombre&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; es el nombre de la hoja que queremos borrar, no esta de más recomendarte usar con cuidado el borrado de hojas, aunque algo que me gusta mucho de AOO, es que muchas de las acciones que hacemos por código, son susceptibles de deshacerse de forma normal con la barra de herramientas o con CTRL+Z, el borrado de hojas es una de ellas, compruébalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(&amp;#039;Hoja3&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto no puedes borrar una hoja que no exista, así que verifícalo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes borrar la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.removeByName(activa.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior hasta que no quede ni una, claro, no te dejara por que un documento de hoja de calculo por lo menos debe de tener una hoja, para evitar el error que te da al tratar de borrar la ultima hoja, valida que siempre quede más de una.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;borrame&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre) and hojas.getCount() &amp;gt; 1:&lt;br /&gt;
        hojas.removeByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;La hoja no existe o solo queda una&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219901</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219901"/>
		<updated>2013-05-08T05:30:47Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Insertando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Otra hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, hojas.getCount())&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por &amp;#039;&amp;#039;&amp;#039;getCount()&amp;#039;&amp;#039;&amp;#039; pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    indice = activa.getRangeAddress().Sheet &lt;br /&gt;
    msgbox(u&amp;#039;El índice de la hoja activa es: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir en una submacro. Nota como estamos estableciendo un &amp;#039;&amp;#039;&amp;#039;valor por default&amp;#039;&amp;#039;&amp;#039; para el ultimo argumento que será la posición deseada para la nueva hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nueva_hoja(doc, nombre, pos=0):&lt;br /&gt;
    hojas = doc.getSheets() &lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
        indice = activa.getRangeAddress().Sheet&lt;br /&gt;
        if pos == 1:&lt;br /&gt;
            pos = indice&lt;br /&gt;
        elif pos == 2:&lt;br /&gt;
            pos = indice + 1&lt;br /&gt;
        elif pos &amp;gt; 2:&lt;br /&gt;
            pos = hojas.getCount()&lt;br /&gt;
        hojas.insertNewByName(nombre, pos)&lt;br /&gt;
        return hojas.getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora ya podemos insertar una nueva hoja en la posición que sea.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al inicio&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Antes de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 1)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Despues de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 2)&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al final&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 3)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219900</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219900"/>
		<updated>2013-05-08T05:30:15Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Insertando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&amp;lt;source lang=paython&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Otra hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, hojas.getCount())&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por &amp;#039;&amp;#039;&amp;#039;getCount()&amp;#039;&amp;#039;&amp;#039; pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    indice = activa.getRangeAddress().Sheet &lt;br /&gt;
    msgbox(u&amp;#039;El índice de la hoja activa es: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir en una submacro. Nota como estamos estableciendo un &amp;#039;&amp;#039;&amp;#039;valor por default&amp;#039;&amp;#039;&amp;#039; para el ultimo argumento que será la posición deseada para la nueva hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def nueva_hoja(doc, nombre, pos=0):&lt;br /&gt;
    hojas = doc.getSheets() &lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        activa = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
        indice = activa.getRangeAddress().Sheet&lt;br /&gt;
        if pos == 1:&lt;br /&gt;
            pos = indice&lt;br /&gt;
        elif pos == 2:&lt;br /&gt;
            pos = indice + 1&lt;br /&gt;
        elif pos &amp;gt; 2:&lt;br /&gt;
            pos = hojas.getCount()&lt;br /&gt;
        hojas.insertNewByName(nombre, pos)&lt;br /&gt;
        return hojas.getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora ya podemos insertar una nueva hoja en la posición que sea.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al inicio&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Antes de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 1)&lt;br /&gt;
&lt;br /&gt;
    nombre = &amp;#039;Despues de la activa&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 2)&lt;br /&gt;
    &lt;br /&gt;
    nombre = &amp;#039;Al final&amp;#039;&lt;br /&gt;
    nueva = nueva_hoja(doc, nombre, 3)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219899</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219899"/>
		<updated>2013-05-08T05:03:07Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Insertando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219898</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219898"/>
		<updated>2013-05-08T05:01:14Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Insertando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if not hojas.hasByName(nombre):&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
    nueva_hoja = doc.getSheets().getByName(nombre)&lt;br /&gt;
    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub InsertarNuevaHoja3()&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHoja As Object&lt;br /&gt;
 Dim sNombre As String&lt;br /&gt;
&lt;br /&gt;
     sNombre &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; Trim(InputBox(&amp;quot;Nombre de la nueva hoja&amp;quot;))&lt;br /&gt;
     If sNombre &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         If Not oHojas.hasByName(sNombre) Then&lt;br /&gt;
             &amp;#039;Si no existe la insertamos al final&lt;br /&gt;
             oHojas.insertNewByName( sNombre, oHojas.getCount() )&lt;br /&gt;
         End If&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(sNombre)&lt;br /&gt;
         ThisComponent.getCurrentController.setActiveSheet(oHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por {{TextColor|Blue|getCount()}} pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub IndiceHojaActiva()&lt;br /&gt;
 Dim co1 As Integer&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 dim oHoja As Object&lt;br /&gt;
&lt;br /&gt;
     oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
&lt;br /&gt;
     For co1 &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0 To ThisComponent.getSheets.getCount() - 1&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByIndex(co1)&lt;br /&gt;
         If oHoja.getName() &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getName() then&lt;br /&gt;
             MsgBox &amp;quot;El indice de la hoja activa es: &amp;quot; &amp;amp; co1&lt;br /&gt;
             Exit For&lt;br /&gt;
         End If&lt;br /&gt;
     Next&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir a una función.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Function BuscarIndiceHoja(ByVal NombreHoja As String) As Integer&lt;br /&gt;
 Dim co1 As Integer&lt;br /&gt;
 dim oHoja As Object&lt;br /&gt;
&lt;br /&gt;
     For co1 &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0 To ThisComponent.getSheets.getCount() - 1&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByIndex(co1)&lt;br /&gt;
         If oHoja.getName() &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; NombreHoja then&lt;br /&gt;
             BuscarIndiceHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; co1&lt;br /&gt;
             Exit Function&lt;br /&gt;
         End If&lt;br /&gt;
     Next&lt;br /&gt;
     BuscarIndiceHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; -1&lt;br /&gt;
&lt;br /&gt;
 End Function&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que si no la encuentra el valor devuelto es -1, lo cual hay que evaluar en caso necesario. Para insertar antes de la hoja activa usamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub InsertarNuevaHoja4()&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHoja As Object&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 Dim sNombre As String&lt;br /&gt;
 Dim pos As Integer&lt;br /&gt;
&lt;br /&gt;
     sNombre &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; Trim(InputBox(&amp;quot;Nombre de la nueva hoja&amp;quot;))&lt;br /&gt;
     If sNombre &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
         If Not oHojas.hasByName(sNombre) Then&lt;br /&gt;
             &amp;#039;Buscamos el índice de la hoja activa&lt;br /&gt;
             pos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; BuscarIndiceHoja(oHojaActiva.getName())&lt;br /&gt;
             oHojas.insertNewByName( sNombre, pos )&lt;br /&gt;
         End If&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(sNombre)&lt;br /&gt;
         ThisComponent.getCurrentController.setActiveSheet(oHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para insertar después de la hoja activa, solo sumas uno al valor devuelto por la función {{TextColor|Blue|BuscarIndiceHoja}}.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 pos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; BuscarIndiceHoja(oHojaActiva.getName()) + 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos aventurar una primera versión de una función genérica para insertar una nueva hoja de calculo donde quieras.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;#039;Como función regresamos la nueva hoja insertada o la existente en su caso&lt;br /&gt;
 &amp;#039;Posición:    1 = Inicio&lt;br /&gt;
 &amp;#039;            2 = Final&lt;br /&gt;
 &amp;#039;            3 = Antes de la hoja activa&lt;br /&gt;
 &amp;#039;            4 = Después de la hoja activa&lt;br /&gt;
 Function getNuevaHoja(NombreHoja As String, Posicion As Integer) As Object&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 Dim iPos As Integer&lt;br /&gt;
&lt;br /&gt;
     If NombreHoja &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
         Select Case Posicion&lt;br /&gt;
             Case 1 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0&lt;br /&gt;
             Case 2 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojas.getCount()&lt;br /&gt;
             Case 3 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getRangeAddress.Sheet&lt;br /&gt;
             Case 4 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getRangeAddress.Sheet + 1&lt;br /&gt;
             Case Else : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0&lt;br /&gt;
         End Select&lt;br /&gt;
         If Not oHojas.hasByName(NombreHoja) Then&lt;br /&gt;
             oHojas.insertNewByName(NombreHoja, iPos)&lt;br /&gt;
         End If&lt;br /&gt;
         getNuevaHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(NombreHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Function&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota como estamos obteniendo el índice de la hoja activa ({{TextColor|Blue|oHoja.getRangeAddress.Sheet}}), con lo cual nos evitamos tener que hacer un ciclo por las hojas del documento. Puedes mejorar esta función para insertar la hoja en cualquier otro documento, así como ingeniártelas para pedirle al usuario el número de hojas nuevas que quiera insertar e insertarlas por supuesto, esa, es tu tarea.&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219897</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219897"/>
		<updated>2013-05-08T05:00:21Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Insertando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición)&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;    hojas = doc.getSheets()    if not hojas.hasByName(nombre):        hojas.insertNewByName(nombre, 0)    nueva_hoja = doc.getSheets().getByName(nombre)    doc.getCurrentController().setActiveSheet(nueva_hoja)   &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que solo agregamos la hoja si esta no existe, entonces solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. &lt;br /&gt;
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer &amp;#039;&amp;#039;&amp;#039;activar&amp;#039;&amp;#039;&amp;#039; toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub InsertarNuevaHoja3()&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHoja As Object&lt;br /&gt;
 Dim sNombre As String&lt;br /&gt;
&lt;br /&gt;
     sNombre &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; Trim(InputBox(&amp;quot;Nombre de la nueva hoja&amp;quot;))&lt;br /&gt;
     If sNombre &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         If Not oHojas.hasByName(sNombre) Then&lt;br /&gt;
             &amp;#039;Si no existe la insertamos al final&lt;br /&gt;
             oHojas.insertNewByName( sNombre, oHojas.getCount() )&lt;br /&gt;
         End If&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(sNombre)&lt;br /&gt;
         ThisComponent.getCurrentController.setActiveSheet(oHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por {{TextColor|Blue|getCount()}} pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub IndiceHojaActiva()&lt;br /&gt;
 Dim co1 As Integer&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 dim oHoja As Object&lt;br /&gt;
&lt;br /&gt;
     oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
&lt;br /&gt;
     For co1 &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0 To ThisComponent.getSheets.getCount() - 1&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByIndex(co1)&lt;br /&gt;
         If oHoja.getName() &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getName() then&lt;br /&gt;
             MsgBox &amp;quot;El indice de la hoja activa es: &amp;quot; &amp;amp; co1&lt;br /&gt;
             Exit For&lt;br /&gt;
         End If&lt;br /&gt;
     Next&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir a una función.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Function BuscarIndiceHoja(ByVal NombreHoja As String) As Integer&lt;br /&gt;
 Dim co1 As Integer&lt;br /&gt;
 dim oHoja As Object&lt;br /&gt;
&lt;br /&gt;
     For co1 &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0 To ThisComponent.getSheets.getCount() - 1&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByIndex(co1)&lt;br /&gt;
         If oHoja.getName() &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; NombreHoja then&lt;br /&gt;
             BuscarIndiceHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; co1&lt;br /&gt;
             Exit Function&lt;br /&gt;
         End If&lt;br /&gt;
     Next&lt;br /&gt;
     BuscarIndiceHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; -1&lt;br /&gt;
&lt;br /&gt;
 End Function&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que si no la encuentra el valor devuelto es -1, lo cual hay que evaluar en caso necesario. Para insertar antes de la hoja activa usamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub InsertarNuevaHoja4()&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHoja As Object&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 Dim sNombre As String&lt;br /&gt;
 Dim pos As Integer&lt;br /&gt;
&lt;br /&gt;
     sNombre &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; Trim(InputBox(&amp;quot;Nombre de la nueva hoja&amp;quot;))&lt;br /&gt;
     If sNombre &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
         If Not oHojas.hasByName(sNombre) Then&lt;br /&gt;
             &amp;#039;Buscamos el índice de la hoja activa&lt;br /&gt;
             pos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; BuscarIndiceHoja(oHojaActiva.getName())&lt;br /&gt;
             oHojas.insertNewByName( sNombre, pos )&lt;br /&gt;
         End If&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(sNombre)&lt;br /&gt;
         ThisComponent.getCurrentController.setActiveSheet(oHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para insertar después de la hoja activa, solo sumas uno al valor devuelto por la función {{TextColor|Blue|BuscarIndiceHoja}}.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 pos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; BuscarIndiceHoja(oHojaActiva.getName()) + 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos aventurar una primera versión de una función genérica para insertar una nueva hoja de calculo donde quieras.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;#039;Como función regresamos la nueva hoja insertada o la existente en su caso&lt;br /&gt;
 &amp;#039;Posición:    1 = Inicio&lt;br /&gt;
 &amp;#039;            2 = Final&lt;br /&gt;
 &amp;#039;            3 = Antes de la hoja activa&lt;br /&gt;
 &amp;#039;            4 = Después de la hoja activa&lt;br /&gt;
 Function getNuevaHoja(NombreHoja As String, Posicion As Integer) As Object&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 Dim iPos As Integer&lt;br /&gt;
&lt;br /&gt;
     If NombreHoja &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
         Select Case Posicion&lt;br /&gt;
             Case 1 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0&lt;br /&gt;
             Case 2 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojas.getCount()&lt;br /&gt;
             Case 3 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getRangeAddress.Sheet&lt;br /&gt;
             Case 4 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getRangeAddress.Sheet + 1&lt;br /&gt;
             Case Else : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0&lt;br /&gt;
         End Select&lt;br /&gt;
         If Not oHojas.hasByName(NombreHoja) Then&lt;br /&gt;
             oHojas.insertNewByName(NombreHoja, iPos)&lt;br /&gt;
         End If&lt;br /&gt;
         getNuevaHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(NombreHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Function&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota como estamos obteniendo el índice de la hoja activa ({{TextColor|Blue|oHoja.getRangeAddress.Sheet}}), con lo cual nos evitamos tener que hacer un ciclo por las hojas del documento. Puedes mejorar esta función para insertar la hoja en cualquier otro documento, así como ingeniártelas para pedirle al usuario el número de hojas nuevas que quiera insertar e insertarlas por supuesto, esa, es tu tarea.&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219896</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219896"/>
		<updated>2013-05-08T04:52:24Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Insertando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    nombre = &amp;#039;Nueva hoja&amp;#039;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        msgbox(&amp;#039;Ya existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        hojas.insertNewByName(nombre, 0)&lt;br /&gt;
        nueva_hoja = doc.getSheets.getByName(nombre)&lt;br /&gt;
        doc.getCurrentController().setActiveSheet(nueva_hoja)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que si la hoja ya existe, solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. Es sumamente frecuente en programadores noveles, querer “activar” toda hoja que se quiera manipular, esto no es necesariamente así, de hecho, la mayor parte de las veces, con la referencia es suficiente.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub InsertarNuevaHoja3()&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHoja As Object&lt;br /&gt;
 Dim sNombre As String&lt;br /&gt;
&lt;br /&gt;
     sNombre &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; Trim(InputBox(&amp;quot;Nombre de la nueva hoja&amp;quot;))&lt;br /&gt;
     If sNombre &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         If Not oHojas.hasByName(sNombre) Then&lt;br /&gt;
             &amp;#039;Si no existe la insertamos al final&lt;br /&gt;
             oHojas.insertNewByName( sNombre, oHojas.getCount() )&lt;br /&gt;
         End If&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(sNombre)&lt;br /&gt;
         ThisComponent.getCurrentController.setActiveSheet(oHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por {{TextColor|Blue|getCount()}} pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub IndiceHojaActiva()&lt;br /&gt;
 Dim co1 As Integer&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 dim oHoja As Object&lt;br /&gt;
&lt;br /&gt;
     oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
&lt;br /&gt;
     For co1 &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0 To ThisComponent.getSheets.getCount() - 1&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByIndex(co1)&lt;br /&gt;
         If oHoja.getName() &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getName() then&lt;br /&gt;
             MsgBox &amp;quot;El indice de la hoja activa es: &amp;quot; &amp;amp; co1&lt;br /&gt;
             Exit For&lt;br /&gt;
         End If&lt;br /&gt;
     Next&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir a una función.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Function BuscarIndiceHoja(ByVal NombreHoja As String) As Integer&lt;br /&gt;
 Dim co1 As Integer&lt;br /&gt;
 dim oHoja As Object&lt;br /&gt;
&lt;br /&gt;
     For co1 &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0 To ThisComponent.getSheets.getCount() - 1&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByIndex(co1)&lt;br /&gt;
         If oHoja.getName() &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; NombreHoja then&lt;br /&gt;
             BuscarIndiceHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; co1&lt;br /&gt;
             Exit Function&lt;br /&gt;
         End If&lt;br /&gt;
     Next&lt;br /&gt;
     BuscarIndiceHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; -1&lt;br /&gt;
&lt;br /&gt;
 End Function&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que si no la encuentra el valor devuelto es -1, lo cual hay que evaluar en caso necesario. Para insertar antes de la hoja activa usamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub InsertarNuevaHoja4()&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHoja As Object&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 Dim sNombre As String&lt;br /&gt;
 Dim pos As Integer&lt;br /&gt;
&lt;br /&gt;
     sNombre &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; Trim(InputBox(&amp;quot;Nombre de la nueva hoja&amp;quot;))&lt;br /&gt;
     If sNombre &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
         If Not oHojas.hasByName(sNombre) Then&lt;br /&gt;
             &amp;#039;Buscamos el índice de la hoja activa&lt;br /&gt;
             pos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; BuscarIndiceHoja(oHojaActiva.getName())&lt;br /&gt;
             oHojas.insertNewByName( sNombre, pos )&lt;br /&gt;
         End If&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(sNombre)&lt;br /&gt;
         ThisComponent.getCurrentController.setActiveSheet(oHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para insertar después de la hoja activa, solo sumas uno al valor devuelto por la función {{TextColor|Blue|BuscarIndiceHoja}}.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 pos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; BuscarIndiceHoja(oHojaActiva.getName()) + 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos aventurar una primera versión de una función genérica para insertar una nueva hoja de calculo donde quieras.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;#039;Como función regresamos la nueva hoja insertada o la existente en su caso&lt;br /&gt;
 &amp;#039;Posición:    1 = Inicio&lt;br /&gt;
 &amp;#039;            2 = Final&lt;br /&gt;
 &amp;#039;            3 = Antes de la hoja activa&lt;br /&gt;
 &amp;#039;            4 = Después de la hoja activa&lt;br /&gt;
 Function getNuevaHoja(NombreHoja As String, Posicion As Integer) As Object&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 Dim iPos As Integer&lt;br /&gt;
&lt;br /&gt;
     If NombreHoja &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
         Select Case Posicion&lt;br /&gt;
             Case 1 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0&lt;br /&gt;
             Case 2 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojas.getCount()&lt;br /&gt;
             Case 3 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getRangeAddress.Sheet&lt;br /&gt;
             Case 4 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getRangeAddress.Sheet + 1&lt;br /&gt;
             Case Else : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0&lt;br /&gt;
         End Select&lt;br /&gt;
         If Not oHojas.hasByName(NombreHoja) Then&lt;br /&gt;
             oHojas.insertNewByName(NombreHoja, iPos)&lt;br /&gt;
         End If&lt;br /&gt;
         getNuevaHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(NombreHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Function&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota como estamos obteniendo el índice de la hoja activa ({{TextColor|Blue|oHoja.getRangeAddress.Sheet}}), con lo cual nos evitamos tener que hacer un ciclo por las hojas del documento. Puedes mejorar esta función para insertar la hoja en cualquier otro documento, así como ingeniártelas para pedirle al usuario el número de hojas nuevas que quiera insertar e insertarlas por supuesto, esa, es tu tarea.&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219895</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=219895"/>
		<updated>2013-05-08T04:47:56Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Insertando hojas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas ==&lt;br /&gt;
Para insertar nuevas hojas, usamos el método: &amp;#039;&amp;#039;&amp;#039;insertNewByName(Nombre, Posición&amp;#039;&amp;#039;&amp;#039;, en donde necesitamos el nombre de la nueva hoja a insertar y la posición donde la queremos, la siguiente macro agrega una hoja nueva al inicio de las demás.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&lt;br /&gt;
    hojas.insertNewByName(&amp;#039;Nuevos datos&amp;#039;, 0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ejecuta la macro anterior dos veces y notaras que te dará un error, pues no puedes tener dos hojas con el mismo nombre, entonces, tenemos que verificar si la hoja existe o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
 Sub InsertarNuevaHoja2()&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHoja As Object&lt;br /&gt;
 Dim sNombre As String&lt;br /&gt;
&lt;br /&gt;
     &amp;#039;Solicitamos un nombre para la nueva hoja&lt;br /&gt;
     sNombre &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; Trim(InputBox(&amp;quot;Nombre de la nueva hoja&amp;quot;))&lt;br /&gt;
     &amp;#039;Verificamos que no este vacio&lt;br /&gt;
     If sNombre &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         &amp;#039;Referencia a todas las hojas&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         &amp;#039;Verificamos si ya existe la hoja&lt;br /&gt;
         If Not oHojas.hasByName(sNombre) Then&lt;br /&gt;
             &amp;#039;Si no existe la insertamos el inicio&lt;br /&gt;
             oHojas.insertNewByName(sNombre, 0)&lt;br /&gt;
         Else&lt;br /&gt;
             MsgBox &amp;quot;Esta hoja ya existe&amp;quot;&lt;br /&gt;
         End If&lt;br /&gt;
&lt;br /&gt;
         &amp;#039;Referencia a la nueva hoja o a la existente&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(sNombre)&lt;br /&gt;
         &amp;#039;La activamos&lt;br /&gt;
         ThisComponent.getCurrentController.setActiveSheet(oHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que si la hoja ya existe, solo hacemos una referencia a ella. La ultima linea para activar la hoja no es necesaria para que la manipules, solo en caso de que quieras que el usuario haga o manipule algo en ella, si no, puedes omitirla. Es sumamente frecuente en programadores noveles, querer “activar” toda hoja que se quiera manipular, esto no es necesariamente así, de hecho, la mayor parte de las veces, con la referencia es suficiente.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos agregar la hoja al final de todas las demás.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub InsertarNuevaHoja3()&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHoja As Object&lt;br /&gt;
 Dim sNombre As String&lt;br /&gt;
&lt;br /&gt;
     sNombre &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; Trim(InputBox(&amp;quot;Nombre de la nueva hoja&amp;quot;))&lt;br /&gt;
     If sNombre &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         If Not oHojas.hasByName(sNombre) Then&lt;br /&gt;
             &amp;#039;Si no existe la insertamos al final&lt;br /&gt;
             oHojas.insertNewByName( sNombre, oHojas.getCount() )&lt;br /&gt;
         End If&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(sNombre)&lt;br /&gt;
         ThisComponent.getCurrentController.setActiveSheet(oHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por {{TextColor|Blue|getCount()}} pero incluso si es mayor a este valor, no te dará error y la insertara al final de las demás hojas. Si quieres insertar la hoja antes o después de la hoja activa, primero tienes que encontrar el índice de la hoja activa.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub IndiceHojaActiva()&lt;br /&gt;
 Dim co1 As Integer&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 dim oHoja As Object&lt;br /&gt;
&lt;br /&gt;
     oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
&lt;br /&gt;
     For co1 &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0 To ThisComponent.getSheets.getCount() - 1&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByIndex(co1)&lt;br /&gt;
         If oHoja.getName() &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getName() then&lt;br /&gt;
             MsgBox &amp;quot;El indice de la hoja activa es: &amp;quot; &amp;amp; co1&lt;br /&gt;
             Exit For&lt;br /&gt;
         End If&lt;br /&gt;
     Next&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Que podemos convertir a una función.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Function BuscarIndiceHoja(ByVal NombreHoja As String) As Integer&lt;br /&gt;
 Dim co1 As Integer&lt;br /&gt;
 dim oHoja As Object&lt;br /&gt;
&lt;br /&gt;
     For co1 &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0 To ThisComponent.getSheets.getCount() - 1&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByIndex(co1)&lt;br /&gt;
         If oHoja.getName() &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; NombreHoja then&lt;br /&gt;
             BuscarIndiceHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; co1&lt;br /&gt;
             Exit Function&lt;br /&gt;
         End If&lt;br /&gt;
     Next&lt;br /&gt;
     BuscarIndiceHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; -1&lt;br /&gt;
&lt;br /&gt;
 End Function&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa que si no la encuentra el valor devuelto es -1, lo cual hay que evaluar en caso necesario. Para insertar antes de la hoja activa usamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 Sub InsertarNuevaHoja4()&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHoja As Object&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 Dim sNombre As String&lt;br /&gt;
 Dim pos As Integer&lt;br /&gt;
&lt;br /&gt;
     sNombre &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; Trim(InputBox(&amp;quot;Nombre de la nueva hoja&amp;quot;))&lt;br /&gt;
     If sNombre &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
         If Not oHojas.hasByName(sNombre) Then&lt;br /&gt;
             &amp;#039;Buscamos el índice de la hoja activa&lt;br /&gt;
             pos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; BuscarIndiceHoja(oHojaActiva.getName())&lt;br /&gt;
             oHojas.insertNewByName( sNombre, pos )&lt;br /&gt;
         End If&lt;br /&gt;
         oHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(sNombre)&lt;br /&gt;
         ThisComponent.getCurrentController.setActiveSheet(oHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Sub&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para insertar después de la hoja activa, solo sumas uno al valor devuelto por la función {{TextColor|Blue|BuscarIndiceHoja}}.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 pos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; BuscarIndiceHoja(oHojaActiva.getName()) + 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos aventurar una primera versión de una función genérica para insertar una nueva hoja de calculo donde quieras.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;oobas&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;#039;Como función regresamos la nueva hoja insertada o la existente en su caso&lt;br /&gt;
 &amp;#039;Posición:    1 = Inicio&lt;br /&gt;
 &amp;#039;            2 = Final&lt;br /&gt;
 &amp;#039;            3 = Antes de la hoja activa&lt;br /&gt;
 &amp;#039;            4 = Después de la hoja activa&lt;br /&gt;
 Function getNuevaHoja(NombreHoja As String, Posicion As Integer) As Object&lt;br /&gt;
 Dim oHojas As Object&lt;br /&gt;
 Dim oHojaActiva As Object&lt;br /&gt;
 Dim iPos As Integer&lt;br /&gt;
&lt;br /&gt;
     If NombreHoja &amp;lt;nowiki&amp;gt;&amp;lt;&amp;gt;&amp;lt;/nowiki&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
         oHojas &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets()&lt;br /&gt;
         oHojaActiva &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getCurrentController.getActiveSheet()&lt;br /&gt;
         Select Case Posicion&lt;br /&gt;
             Case 1 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0&lt;br /&gt;
             Case 2 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojas.getCount()&lt;br /&gt;
             Case 3 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getRangeAddress.Sheet&lt;br /&gt;
             Case 4 : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; oHojaActiva.getRangeAddress.Sheet + 1&lt;br /&gt;
             Case Else : iPos &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; 0&lt;br /&gt;
         End Select&lt;br /&gt;
         If Not oHojas.hasByName(NombreHoja) Then&lt;br /&gt;
             oHojas.insertNewByName(NombreHoja, iPos)&lt;br /&gt;
         End If&lt;br /&gt;
         getNuevaHoja &amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt; ThisComponent.getSheets.getByName(NombreHoja)&lt;br /&gt;
     End If&lt;br /&gt;
&lt;br /&gt;
 End Function&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota como estamos obteniendo el índice de la hoja activa ({{TextColor|Blue|oHoja.getRangeAddress.Sheet}}), con lo cual nos evitamos tener que hacer un ciclo por las hojas del documento. Puedes mejorar esta función para insertar la hoja en cualquier otro documento, así como ingeniártelas para pedirle al usuario el número de hojas nuevas que quiera insertar e insertarlas por supuesto, esa, es tu tarea.&lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc&amp;diff=219894</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc&amp;diff=219894"/>
		<updated>2013-05-08T04:27:48Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En todos los temas de esta sección, asumimos que el lector ha leído y comprendido, todos los temas introductorios a este.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas|Trabajando con hojas]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ReferenciaARangos|Referencia a rangos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ManipulandoRangos|Manipulando rangos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ManipulandoDatos|Manipulando datos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/DandoFormato|Dando formato]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/Imprimiendo|Imprimiendo]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/RangosDeDatos|Rangos de datos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/BasesDeDatos|Bases de datos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/GraficandoDatos|Graficando datos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConElementosGraficos|Trabajando con elementos gráficos]]&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/ConfiguracionGlobalCalc|Configuración global de Calc]]&lt;br /&gt;
&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:ES/Python]]&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218416</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218416"/>
		<updated>2013-04-29T04:55:27Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con hojas}}&lt;br /&gt;
&lt;br /&gt;
== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Insertando hojas == &lt;br /&gt;
&lt;br /&gt;
== Borrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Moviendo hojas ==&lt;br /&gt;
&lt;br /&gt;
== Copiando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Renombrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Ocultando y mostrando hojas ==&lt;br /&gt;
&lt;br /&gt;
== Protección y desprotección de hojas ==&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218415</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218415"/>
		<updated>2013-04-29T04:52:23Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Acceso a las hojas de un archivo Calc */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218414</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218414"/>
		<updated>2013-04-29T04:51:54Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Acceso a las hojas de un archivo Calc */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creamos una función genérica para devolver una hoja.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def devuelve_hoja(doc, nombre):&lt;br /&gt;
    if doc.getSheets().hasByName(nombre):&lt;br /&gt;
        return doc.getSheets().getByName(nombre)&lt;br /&gt;
&amp;lt;/source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para usarse de forma sencilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    nombre = &amp;#039;Hoja2&amp;#039;&lt;br /&gt;
    hoja = devuelve_hoja(doc, nombre)&lt;br /&gt;
    if hoja:&lt;br /&gt;
        msgbox(hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No se encontró la hoja: %s&amp;#039; % nombre)re)&lt;br /&gt;
&amp;lt;/source&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218413</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218413"/>
		<updated>2013-04-29T04:44:11Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Acceso a las hojas de un archivo Calc */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También es posible devolver la hoja activa.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hoja = doc.getCurrentController().getActiveSheet()&lt;br /&gt;
    msgbox(hoja.getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218412</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218412"/>
		<updated>2013-04-29T04:40:38Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Acceso a las hojas de un archivo Calc */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice, pero toma en cuenta que si mueves una hoja de posición en relación con las demás, su índice cambiara, no así su nombre, pero el nombre es susceptible de ser cambiado por el usuario, así que siempre comprueba que exista una hoja antes de intentar acceder a ella.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218411</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas&amp;diff=218411"/>
		<updated>2013-04-29T04:39:23Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: Created page with &amp;quot;== Acceso a las hojas de un archivo Calc ==  Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;. &amp;lt;source lang=python&amp;gt;     doc = desktop.getCurrentC...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Acceso a las hojas de un archivo Calc ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todas las hojas de un archivo usamos el método &amp;#039;&amp;#039;&amp;#039;getSheets&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos devolver todos los nombres de las mismas.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombres = hojas.getElementNames()&lt;br /&gt;
    msgbox(&amp;#039;\n&amp;#039;.join(nombres))&lt;br /&gt;
&amp;lt;/sourc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O acceder por nombre a la que nos interesa (&amp;#039;&amp;#039;&amp;#039;getByName&amp;#039;&amp;#039;&amp;#039;), tienes que validar (&amp;#039;&amp;#039;&amp;#039;hasByName&amp;#039;&amp;#039;&amp;#039;) primero que existe esta hoja.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    nombre = &amp;#039;Hoja1&amp;#039;&lt;br /&gt;
    if hojas.hasByName(nombre):&lt;br /&gt;
        hoja = hojas.getByName(nombre)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;No existe la hoja: %s&amp;#039; % nombre)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a una hoja por su índice, recuerda que los índices en AOO empiezan en cero, en las hojas, la numeración empieza de izquierda a derecha.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    hoja = hojas.getByIndex(indice)&lt;br /&gt;
    msgbox (hoja.getName()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Del mismo modo que por el nombre, si tratas de acceder a una hoja por un índice que no exista, te dará un error, lo podemos comprobar asegurándonos que el numero de índice a consultar siempre es menor al total de las hojas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    indice = 1&lt;br /&gt;
    if indice &amp;lt; hojas.getCount():&lt;br /&gt;
        hoja = hojas.getByIndex(indice)&lt;br /&gt;
        msgbox (hoja.getName())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;No existe este índice: %s&amp;#039; % indice)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Podemos acceder a cada hoja por su índice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    hojas = doc.getSheets()&lt;br /&gt;
    for i in range(hojas.getCount()):&lt;br /&gt;
        msgbox(hojas.getByIndex(i).getName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc&amp;diff=218410</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc&amp;diff=218410"/>
		<updated>2013-04-29T04:21:46Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En todos los temas de esta sección, asumimos que el lector ha leído y comprendido, todos los temas introductorios a este.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas|Trabajando con hojas]]&lt;br /&gt;
&amp;lt;/big&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc&amp;diff=218409</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc&amp;diff=218409"/>
		<updated>2013-04-29T04:17:30Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: Created page with &amp;quot;&amp;lt;big&amp;gt; :*Trabajando con hojas &amp;lt;/big&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;big&amp;gt;&lt;br /&gt;
:*[[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas|Trabajando con hojas]]&lt;br /&gt;
&amp;lt;/big&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218401</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218401"/>
		<updated>2013-04-28T19:55:02Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Cambiando posición y tamaño de ventana */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con Apache OpenOffice}}&lt;br /&gt;
&lt;br /&gt;
== Conceptos iniciales==&lt;br /&gt;
&lt;br /&gt;
Este es el tema más importante para crear macros, de forma sencilla, pero se ven las bases para trabajar con todo AOO, por eso es importante no avanzar en estas notas, sin antes haber comprendido a cabalidad los temas presentes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;UNO&amp;#039;&amp;#039;&amp;#039; (Universal Network Objects), es la especificación que da acceso a todos los objetos de Apache OpenOffice. Todo lo que quieras saber de esta especificación, lo puedes encontrar en la [[http://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide Guía del desarrollador]] (en ingles).&lt;br /&gt;
&lt;br /&gt;
El &amp;#039;&amp;#039;&amp;#039;API&amp;#039;&amp;#039;&amp;#039; (Application Programer Interface) de Apache OpenOffice proporciona el acceso a toda la funcionalidad de AOO, independientemente del lenguaje. Todo el API de AOO esta en &amp;lt;idl&amp;gt;com.sun.star.module-ix&amp;lt;/idl&amp;gt; (solo ingles).&lt;br /&gt;
&lt;br /&gt;
La comunicación entre objetos UNO se basa en &amp;#039;&amp;#039;&amp;#039;interfaces&amp;#039;&amp;#039;&amp;#039; de objeto.  Las interfaces pueden ser vistos desde el exterior o el interior de un objeto y proporcionan formas de ver o manipular el objeto.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;servicios&amp;#039;&amp;#039;&amp;#039; son agrupaciones lógicas de interfaces, son la forma en que un mismo objeto pueda ofrecer la funcionalidad de varias interfaces.&lt;br /&gt;
&lt;br /&gt;
Los servicios se pueden implementar en librerías compartidas llamadas &amp;#039;&amp;#039;&amp;#039;componentes UNO&amp;#039;&amp;#039;&amp;#039;, con Python podemos crear componentes nuevos y generalmente el usuario final las recibe como una extensión OXT.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;modulos&amp;#039;&amp;#039;&amp;#039; pueden agrupar submodulos, servicios, excepciones, constantes, enumeraciones, etc, se utilizan para especificar bloques coherentes en la API, esto permite tener un API bien estructurada.&lt;br /&gt;
&lt;br /&gt;
== Creando servicios ==&lt;br /&gt;
Para crear un servicio, usamos la &amp;#039;&amp;#039;&amp;#039;fabrica de servicios&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;), una interfaz especial para crear nuevos servicios, pero para llegar a ella, tenemos que hacerlo a traves de la interfaz &amp;#039;&amp;#039;&amp;#039;ComponentContext&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;), como puedes verlo en la siguiente imagen. &lt;br /&gt;
[[Image:UseServices1.png|none|thumb|400px|ComponentContext y ServiceManager]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En pyUNO tenemos dos formas de acceder a esta interfaz, las dos son equivalentes por lo que puedes usar la que prefieras. En la introducción a Python se mencionó que la mayoría de sus herramientas están disponibles en librerias, estás librerias tienen que importarse &amp;#039;&amp;#039;&amp;#039;antes&amp;#039;&amp;#039;&amp;#039; de poder usarse, en nuestro caso importaremos la librería &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; que nos da acceso (entre otras cosas) al contexto de ejecución de AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx1 = XSCRIPTCONTEXT.getComponentContext()&lt;br /&gt;
    ctx2 = uno.getComponentContext()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si te gusta investigar, busca el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; en la carpeta de instalación de AOO, ahí puedes ver de donde sale XSCRIPTCONTEXT}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, podemos acceder a la fábrica de servicios con el &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿como sabemos que este &amp;#039;&amp;#039;&amp;#039;objeto (ComponentContext)&amp;#039;&amp;#039;&amp;#039; tiene este &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;? porque lo estamos demostrando, si, también por eso, pero también porque puedes ver su documentación (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;) en el API de AOO, pero más importante aún, porque podemos hacer que el mismo objeto te diga todo lo que sabe hacer. Para ello haremos uso de una magnifica extensión que te tiene que acompañar el resto de tus días como programador de macros Python, nos referimos a [http://extensions.services.openoffice.org/project/MRI MRI]. Instala (tal vez tengas que reiniciar AOO para poder usarla) y la probamos de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    # llamamos a la extensión MRI y le pasamos el objeto a inspeccionar&lt;br /&gt;
    mri(ctx)&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def mri(target):&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()    &lt;br /&gt;
    mri = sm.createInstanceWithContext(&amp;#039;mytools.Mri&amp;#039;, ctx)&lt;br /&gt;
    mri.inspect(target)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa en la imágen siguiente, como hemos seleccionado los métodos del objeto y nos lista todos los que tenga, hemos remarcado el que por ahora nos interesa &amp;#039;&amp;#039;&amp;#039;getServiceManager()&amp;#039;&amp;#039;&amp;#039;, observa al final de la línea que efectivamente este método nos devuelve una &amp;#039;&amp;#039;&amp;#039;instancia&amp;#039;&amp;#039;&amp;#039; de la interfaz &amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;. &lt;br /&gt;
[[Image:Py_img_0006.png|none|thumb|500px|Usando la extensión MRI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gran ventaja de usar esta extensión (que por cierto esta hecha en Python), es que siempre te devolverá la información directamente del objeto, a esto se le llama &amp;#039;&amp;#039;&amp;#039;instrospección&amp;#039;&amp;#039;&amp;#039;. Acostumbrate a usarla.&lt;br /&gt;
&lt;br /&gt;
Ahora si, ya podemos crear una instancia de cualquier servicio o interfaz disponible en AOO, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existe una forma alternativa de crear este servicio, usando &amp;#039;&amp;#039;&amp;#039;XSCRIPTCONTEXT&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    XSCRIPTCONTEXT.getDesktop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si vuelves a mirar el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; notaras que usa el mismo método para instanciar este servicio}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y para que sirve este servicio? Entre otras cosas para crear nuevos documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
nuevo = desktop.loadComponentFromURL(&amp;#039;private:factory/scalc&amp;#039;, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos a detalle este método y otros relacionados con los documentos de AOO. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; es la instancia de la administración central para todas las aplicaciones AOO.  Todas las ventanas de la aplicación AOO se organizan en una jerarquía de marcos que contienen componentes visibles.  &lt;br /&gt;
&lt;br /&gt;
[[Image:DesktopOverview.png|none|thumb|400px|Desktop administra los componentes y marcos.]]&lt;br /&gt;
&lt;br /&gt;
Para los fines de crear macros es suficiente que recuerdes que, Desktop es el marco raíz de toda la jerarquía de documentos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para crear la instancia del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; usamos un contexto y usamos el método &amp;#039;&amp;#039;&amp;#039;createInstanceWithContext&amp;#039;&amp;#039;&amp;#039;. Otros servicios no requieren de contexto para ser instanciados y usados, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.util.PathSettings&amp;lt;/idl&amp;gt; que nos sirve para obtener las rutas de trabajo actuales en AOO, para estos casos usamos el método &amp;#039;&amp;#039;&amp;#039;createInstance&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    rutas = sm.createInstance(&amp;#039;com.sun.star.util.PathSettings&amp;#039;)&lt;br /&gt;
    # mostramos la ruta de trabajo del usuario&lt;br /&gt;
    print (rutas.Work)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora que ya sabemos instanciar servicios, veamos de nuevo nuestra macro para mostrar un mensaje en pantalla y analicemosla línea a línea para que veas que sencillo es, además, nos servirá para ver otros detalles al programar con Python en AOO. La macro tiene ahora unos ligeros cambios para que trabaje mejor y para explicar algunas cosas, veamos cuales.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la primer línea &amp;#039;&amp;#039;&amp;#039;declaramos&amp;#039;&amp;#039;&amp;#039; nuestra macro, su nombre y los argumentos que necesita, en este caso solo uno &amp;#039;&amp;#039;&amp;#039;message&amp;#039;&amp;#039;&amp;#039; que será el mensaje a mostrar.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la segunda línea, estamos importando (&amp;#039;&amp;#039;&amp;#039;import&amp;#039;&amp;#039;&amp;#039;) la estructura &amp;#039;&amp;#039;&amp;#039;Rectangle&amp;#039;&amp;#039;&amp;#039; desde (&amp;#039;&amp;#039;&amp;#039;from&amp;#039;&amp;#039;&amp;#039;) el modulo &amp;lt;idl&amp;gt;com.sun.star.awt.module-ix&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Las estructuras son un conjunto de valores relacionados, valores que pueden ser de tipos diferentes, pero que son mostrados como una unidad lógica, por ejemplo, la estructura &amp;lt;idl&amp;gt;com.sun.star.awt.Rectangle&amp;lt;/idl&amp;gt; hace referencia a un área rectangular estableciendo su posición y tamaño, en este caso, solo sirve para cumplir los argumentos del método para mostrar nuestro mensaje.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la tercer línea, hacemos otra importación, pero esta vez la hacemos de una constante, específicamente la constante para mostrar el botón &amp;#039;&amp;#039;&amp;#039;Aceptar&amp;#039;&amp;#039;&amp;#039; (OK), estas constantes las puedes ver aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.MessageBoxButtons&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La cuarta línea esta vacía solo para separar la parte de importacion con el resto del código. En la siguiente línea hacemos una validación del argumento pasado a nuestra macro, si el argumento &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; es una instancia de la clase &amp;#039;&amp;#039;&amp;#039;unicode&amp;#039;&amp;#039;&amp;#039; o de la clase &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, entonces la convertimos a &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, esto nos permite pasar a nuestra macro, listas, tuplas, diccionarios y practicamente cualquier objeto, del cual, podremos ver su representación en texto, muchas veces, con información bastante útil.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea ya la hemos estudiado, creamos una instancia del contexto donde se ejecuta AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea también ya la hemos estudiado, creamos una instancia de la fabrica de servicios, una de las instancias más importantes y que usaras constantemente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la siguiente línea creamos una instancia con contexto de un nuevo servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt;, este servicio sirve, entre otras muchas cosas para crear ventanas y mensaje de texto, como el de nuestra macro.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la penultima línea, usamos el método &amp;#039;&amp;#039;&amp;#039;createMessageBox&amp;#039;&amp;#039;&amp;#039; del servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt; para crear nuestro cuadro de mensaje, todos los argumentos de este método puedes verlo aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.XMessageBoxFactory&amp;lt;/idl&amp;gt;, pero aquí los explicamos uno a uno.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Aunque veas muchas líneas, el interpete la considera una sola, esto se logra al estar todos los argumentos entre paréntesis.&lt;br /&gt;
* El primer argumento es la ventana padre (&amp;#039;&amp;#039;&amp;#039;parent&amp;#039;&amp;#039;&amp;#039;) donde será mostrado el cuadro de mensaje, observa como usamos de nuevo el servicio &amp;#039;&amp;#039;&amp;#039;toolkit&amp;#039;&amp;#039;&amp;#039; para recuperar (&amp;#039;&amp;#039;&amp;#039;getDesktopWindow&amp;#039;&amp;#039;&amp;#039;) la ventana padre de AOO.&lt;br /&gt;
* El segundo argumento es el área rectangular del cuadro de mensaje, observa los dos paréntesis al final del nombre de la estructura, son necesarios para inicializarla.&lt;br /&gt;
* El tercer argumento es el tipo de mensaje, dependiendo de este argumento se muestra el icono correspondiente, los valores permitidos son: &amp;#039;&amp;#039;&amp;#039;infobox, warningbox, errorbox, querybox y messbox&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;infobox&amp;#039;&amp;#039;&amp;#039;, el siguiente argumento es ignorado.&lt;br /&gt;
* El cuarto argumento sirve para mostrar botones de comando diferentes, como: &amp;#039;&amp;#039;&amp;#039;Si, No, Cancelar&amp;#039;&amp;#039;&amp;#039;, etc, que están establecidos en las constantes vistas más arriba.&lt;br /&gt;
* El quinto argumento es el título del cuadro de mensaje.&lt;br /&gt;
* Y por ultimo, el mensaje a mostrar, el cual ya validamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la ultima línea al mismo tiempo que mostramos (&amp;#039;&amp;#039;&amp;#039;ejecute&amp;#039;&amp;#039;&amp;#039;) estamos retornando el cuadro de mensaje, esto nos da la posibilidad de capturar el botón al que le haya dado click el usuario, lo cual, veremos más adelante. Todas las macros retornan un valor, aun y cuando este sea un valor vacío (None).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, los servicio los instanciamos y las estructuras y constantes las importamos, y el punto más importante; &amp;#039;&amp;#039;&amp;#039;acostúmbrate a usar, manejar y dominar, la extensión MRI&amp;#039;&amp;#039;&amp;#039;, ella te dice todo lo necesario para trabajar con los objetos UNO de AOO, los demás, es sencillo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== El documento activo ==&lt;br /&gt;
&lt;br /&gt;
Tenemos dos formas de acceder al documento activo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc1 = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
    doc2 = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc1.getIdentifier())&lt;br /&gt;
    print (doc2.getIdentifier())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note| Mira en el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; la forma en que trabaja el método &amp;#039;&amp;#039;&amp;#039;getDocument&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si seguiste nuestra recomendación de asignar la macro de pruebas a una combinación de teclas disponible en todo AOO, prueba a abrir cada uno de los tipos de documentos que puedes ver en el menú &amp;#039;&amp;#039;&amp;#039;Archivo-&amp;gt;Nuevo-&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
[[Image:Py_img_0007.png|none|thumb|500px|Tipos de documentos en AOO]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y a ejecutar la siguiente macro, teniendo como documento activo cada uno de ellos, es decir, activas uno y ejecutas la macro, activas otro y vuelves a llamar a la macro y así sucesivamente con todos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getIdentifier())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los mensajes devueltos en cada documento, son bastante ilustrativos de que &amp;#039;&amp;#039;&amp;#039;tipo de documento&amp;#039;&amp;#039;&amp;#039; se trata. Pero si probaste con todos, habrás notado que con la base de datos nos devuelve un error, si no lo has probado hazlo ahora. Para resolver este caso tenemos varias posibilidades, la primera es controlar la excepción como ya aprendimos en la introducción a Python.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿estamos realmente seguros que ese es el error?, es mejor especificarlo y asegurarnos de que este es el error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tenemos otra alternativa donde no usamos controlador de excepciónes, si no una función que nos dice si un cierto atributo lo posee o no un objeto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    if hasattr(doc, &amp;#039;getIdentifier&amp;#039;):&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Sin atributo getIdentifier&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es mucho mejor esta segunda opción. Aun así, no podemos estar 100% seguros de que cuando no la tenga, el documento sea una base de datos, simplemente estamos excluyendo la posibilidad pero no lo estamos asegurando, probemos con otra propiedad.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getImplementationName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mucho mejor, ahora ya no tenemos errores, pero si probaste de nuevo con todos los tipos de documentos, habrás notado que con &amp;#039;&amp;#039;&amp;#039;Impres&amp;#039;&amp;#039;&amp;#039; y con &amp;#039;&amp;#039;&amp;#039;Draw&amp;#039;&amp;#039;&amp;#039; obtenemos el mismo resultado, por lo que no tenemos la certeza de que tipo de documento es, por lo que descartamos esta propiedad para nuestra finalidad que es identificar fehacientemente cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
Ya vimos que cada objeto UNO soporta diferentes servicios e interfaces, asì que cada documento de AOO (&amp;#039;&amp;#039;&amp;#039;que son objetos&amp;#039;&amp;#039;&amp;#039;) soportan diferentes servicios, algunos son iguales, es decir, comúnes a todos, pero algunos pueden ser únicos para cada documento. Ya vimos como saber si un documento soporta una propiedad, pero para saber si soporta un servicio completo, cambiamos de método, ahora usamos &amp;#039;&amp;#039;&amp;#039;supportsService&amp;#039;&amp;#039;&amp;#039; que nos devuelve falso o verdadero según soporte o no el nombre del servicio pasado como argumento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    res = doc.supportsService(&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;)&lt;br /&gt;
    mensaje = u&amp;#039;No soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    if res:&lt;br /&gt;
        mensaje = u&amp;#039;Soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    print(mensaje)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y mejor aun, podemos saber todos los servicios que soporta un objeto con el método &amp;#039;&amp;#039;&amp;#039;getSupportedServiceNames&amp;#039;&amp;#039;&amp;#039; que nos devuelve una tupla con todos sus nombres.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    servicios = doc.getSupportedServiceNames()&lt;br /&gt;
    &lt;br /&gt;
    print(servicios)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Te queda de tarea probar esta macro en cada uno de los documentos abiertos, incluso puedes probar también el IDE para AOOBasic que incorpora AOO y determinar que servicio usar para diferenciar sin duda cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
== Los documentos abiertos ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todos los documentos abiertos en la sesión de AOO, usamos el método &amp;#039;&amp;#039;&amp;#039;getComponents&amp;#039;&amp;#039;&amp;#039; del objeto &amp;#039;&amp;#039;&amp;#039;Desktop&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;MRI&amp;#039;&amp;#039;&amp;#039;, notarás que este método nos devuelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta interfaz (&amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;) tiene un solo método llamado &amp;#039;&amp;#039;&amp;#039;createEnumeration&amp;#039;&amp;#039;&amp;#039; que nos duelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumeration&amp;lt;/idl&amp;gt; la cual a su vez tiene solo dos métodos, el primero para saber si tenemos más elementos en la enumeración: &amp;#039;&amp;#039;&amp;#039;hasMoreElements&amp;#039;&amp;#039;&amp;#039; y el segundo para acceder al siguiente elemento &amp;#039;&amp;#039;&amp;#039;nextElement&amp;#039;&amp;#039;&amp;#039;, veamoslo con un ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    # mientras tengamos elementos&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        # obtenemos el siguiente elemento&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # mostrámos el tipo de documento&lt;br /&gt;
        mensaje = obtener_tipo(doc)&lt;br /&gt;
        print(mensaje)&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;Calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;Writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;Impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;Draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;Base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;Math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;Basic&amp;#039;}&lt;br /&gt;
    # iteramos entre los tipos de documentos&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        # validamos si soporta el servicio&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            # devolvemos el tipo de documento&lt;br /&gt;
            return &amp;#039;Soy %s&amp;#039; % tipo[t]&lt;br /&gt;
    # si termina sin encontrar un tipo&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como usamos una macro de apoyo para saber que tipo de documento es. Una enumeración no es más que una lista de objetos y es una forma muy común y a veces la única de acceder a ciertos objetos en AOO, es importante que la recuerdes.&lt;br /&gt;
&lt;br /&gt;
== Rutas de archivos y directorios ==&lt;br /&gt;
&lt;br /&gt;
Apache OpenOffice, al ser multiplataforma, hace uso de las rutas de archivos y directorios, en el formato URL, por ejemplo.&lt;br /&gt;
&lt;br /&gt;
file:///home/usuario/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
file:///d:/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta que este formato hace uso de los caracteres 0-9, a-z y A-Z, y cualquier otro carácter será convertido y mostrado con su respectivo código, por ejemplo, los espacios los reemplazara con &amp;#039;&amp;#039;&amp;#039;%20&amp;#039;&amp;#039;&amp;#039;. Siempre que le pases una ruta de archivo a cualquier servicio de AOO, hazlo, casi como una regla, pasarle la ruta en formato Url, para ello, la libreria &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; cuenta con dos funciones muy útiles que hacen el trabajo &amp;#039;&amp;#039;&amp;#039;systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; y &amp;#039;&amp;#039;&amp;#039;fileUrlToSystemPath&amp;#039;&amp;#039;&amp;#039;, veamos como se usan.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def rutas():&lt;br /&gt;
    &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi archivo de Calc.ods&amp;quot;&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # La convertimos al formato URL&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # Regresamos al formato local&lt;br /&gt;
    ruta = uno.fileUrlToSystemPath(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Abre varios documentos existentes y ejecuta la siguiente macro desde cada uno:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def info_ruta():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
    &lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    # obtenemos la ruta en disco&lt;br /&gt;
    ruta =  doc.getURL()&lt;br /&gt;
    # obtenemos las diferentes partes de la ruta&lt;br /&gt;
    ruta, archivo = os.path.split(ruta)&lt;br /&gt;
    nombre, extension = os.path.splitext(archivo)&lt;br /&gt;
    &lt;br /&gt;
    print (ruta)&lt;br /&gt;
    print (uno.fileUrlToSystemPath(ruta))&lt;br /&gt;
    print (archivo)&lt;br /&gt;
    print (nombre)&lt;br /&gt;
    print (extension)&lt;br /&gt;
    &lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hemos importado una nueva librería de Python, &amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; que entre otras muchas cosas, nos permite obtener información de las rutas de archivos como en la macro anterior.&lt;br /&gt;
&lt;br /&gt;
En nuestros siguientes temas, veremos la importancia de usar las rutas de archivos y directorios en formato Url y recuerda que en S.O. Linux, se tiene en cuenta la diferencia entre mayúsculas y minúsculas.&lt;br /&gt;
&lt;br /&gt;
== Creando nuevos documentos ==&lt;br /&gt;
&lt;br /&gt;
El método que nos permite crear nuevos documentos se llama &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039; y es un método del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, por ejemplo, para crear una nueva hoja de calculo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo hay que hacer un pequeño cambio para crear un nuevo documento de texto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y los demás tipos de documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/simpress&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/sdraw&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/smath&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y una base de datos?, probemos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/sbase&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos da un error ¿verdad?&lt;br /&gt;
[[Image:Py_img_0008.png|none|thumb|500px|Error al crear base de datos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No esta soportado. Para saber por que nos da un error, intenta abrir una base de datos nueva, observa como primero, si queremos trabajar con ella, el asistente nos “obliga” primero a guardarla con un nombre y después ya podemos manipularla, esto, solo pasa con las bases de datos, de los demás documentos podemos crear tantos nuevos documentos como queramos sin tener que guardar nada, entonces ¿como creamos una nueva base de datos?, la respuesta es sencilla, del mismo modo que lo hacemos desde la interfaz de usuario, es decir, tenemos que guardar primero la base de datos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
 &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi_Base_Datos.odb&amp;quot;&lt;br /&gt;
    # Creamos el servicio que nos permite manipular bases de datos&lt;br /&gt;
    dbcon = sm.createInstance(&amp;#039;com.sun.star.sdb.DatabaseContext&amp;#039;)&lt;br /&gt;
    # creamos una instancia de una nueva base de datos&lt;br /&gt;
    base = dbcon.createInstance()&lt;br /&gt;
    # establecemos el tipo de base&lt;br /&gt;
    base.URL = &amp;quot;sdbc:embedded:hsqldb&amp;quot;&lt;br /&gt;
    # y la guardamos&lt;br /&gt;
    base.DatabaseDocument.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta dos cosas muy importantes en la macro anterior, el nombre que uses, si ya existe, simplemente lo reemplazara, no te preguntara nada, así que ten cuidado de no usar una ruta o nombre de una base importante que tengas y segundo, la base de datos así creada, no quedara “registrada” en AOO, con lo que no tendrás acceso desde otros programas de la aplicación, más adelante veremos como registrar una base de datos por código.&lt;br /&gt;
&lt;br /&gt;
== Abriendo, guardando y cerrando documentos ==&lt;br /&gt;
Abrir archivos existentes es sumamente sencillo, usamos el mismo método usado&lt;br /&gt;
para crear nuevos documentos &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, pero en el parámetro ruta, le especificamos la ubicación del archivo a abrir de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def documento1():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si tus archivos existen (esto se puede validar), el código anterior los abrirá, &amp;#039;&amp;#039;&amp;#039;siempre&amp;#039;&amp;#039;&amp;#039; utiliza&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;uno.systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; cuando uses rutas de archivos o directorios en&lt;br /&gt;
funciones de AOO que las requieran como argumentos. Ya vimos que el primer&lt;br /&gt;
agumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, es la ruta del archivo a&lt;br /&gt;
abrir, el segundo argumento es una cadena con el nombre del macro (frame)&lt;br /&gt;
donde será mostrado el documento abierto, generalmente si existe este frame se&lt;br /&gt;
usa si no se crea uno nuevo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_cal&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_writer&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existen nombre especiales para este agumento, los más usuales son dos, primero&lt;br /&gt;
que ya hemos estado usando &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; que usa el frame actual y&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039; que siempre crea un nuevo frame.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La recomendación es que uses siempre &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; o &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, un&lt;br /&gt;
escenario puede ser que habrás con &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; una instancia, y después de&lt;br /&gt;
forma oculta uno nuevo con &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, más abajo vemos como abrir un&lt;br /&gt;
documento de forma oculta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si abres una plantilla, esta se comportará de forma normal, es decir, te abrirá una copia de dicha plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_plantilla.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero también podrías querer abrir la plantilla para editarla, en este caso,&lt;br /&gt;
le indicamos en las opciones de apertura esta opción, y aquí vemos como usar&lt;br /&gt;
el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como hemos importado una nueva estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como la instanciamos y asignamos sus valores.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Muy importante, el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
espera una tupla, por eso es que usamos la coma al final del nombre del&lt;br /&gt;
argumento &amp;#039;&amp;#039;&amp;#039;(opciones,)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt; esta conformada por&lt;br /&gt;
un par de valores, un nombre y un valor y es muy frecuentemente usada cuando se&lt;br /&gt;
programa en AOO, para este ejemplo solo hemos usado un par de agumentos,&lt;br /&gt;
siempre van en pares, pero muy bien puede tener más opciones como veremos más&lt;br /&gt;
adelante. En la macro anterior le estamos indicando la propiedad&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (que seria algo así como Es Plantilla), si el valor es&lt;br /&gt;
falso (False), le estamos indicando que queremos abrir la plantilla para&lt;br /&gt;
editarla, en caso contrario (True) abrirá una copia de la plantilla. Lo&lt;br /&gt;
interesante de esta propiedad es que perfectamente la puedes aplicar a archivos&lt;br /&gt;
existentes, es decir, archivos que &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; necesariamente sean plantillas, con&lt;br /&gt;
esta propiedad podemos forzarlos a comportarse como plantillas, por ejemplo, prueba el siguiente código con algún archivo existente que no sea plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como el archivo es un documento de texto normal (ODT), pero con la&lt;br /&gt;
propiedad &amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;, forzamos su apertura como una plantilla.&lt;br /&gt;
&lt;br /&gt;
Otras propiedades interesantes son &amp;#039;&amp;#039;&amp;#039;ReadOnly&amp;#039;&amp;#039;&amp;#039; (Solo Lectura) para abrir un&lt;br /&gt;
archivo como solo lectura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y &amp;#039;&amp;#039;&amp;#039;Password&amp;#039;&amp;#039;&amp;#039; (Contraseña) para abrir archivos con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto puedes combinar cualquier cantidad de opciones siempre y cuando no&lt;br /&gt;
entren en conflicto, es importante que al final, sea una tupla lo que le pasas&lt;br /&gt;
al método, si no, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # creamos una lista vacía&lt;br /&gt;
    opciones = []&lt;br /&gt;
    # creamos la primer propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opcion.Value = True&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
    # creamos la segunda propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opcion.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    # nota que la lista la convertimos en tupla&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, tuple(opciones))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si la contraseña es incorrecta, no obtendrás ningún mensaje, simplemente no&lt;br /&gt;
lo abrira y la variable &amp;#039;&amp;#039;&amp;#039;doc&amp;#039;&amp;#039;&amp;#039; será vacía, puedes validar esto:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if doc is None:&lt;br /&gt;
        print (&amp;#039;No se abrio el documento&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos otras formas de validar y depurar nuestras macros para&lt;br /&gt;
los dificiles casos en donde no obtengamos ningún mensaje de error, pero&lt;br /&gt;
simplemente nuestra macro se niega a hacer su trabajo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mientras un formato de archivo sea soportado por AOO, lo podrás abrir con el&lt;br /&gt;
método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, en el siguiente ejemplo, abrimos un archivo tipo Doc, un Html y un Xls.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_web.html&amp;#039;)&lt;br /&gt;
    doc_h = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_excel.xls&amp;#039;)&lt;br /&gt;
    doc_x = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Qué otras opciones tengo para abrir archivos?. La mayoría están descritas&lt;br /&gt;
en el servicio &amp;lt;idl&amp;gt;com.sun.star.document.MediaDescriptor&amp;lt;/idl&amp;gt;, aquí veremos&lt;br /&gt;
las más usadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cuando abres un archivo por código y este contiene macros, tu puedes&lt;br /&gt;
establecer si se abre con las macros activadas, de forma predeterminada lo abre&lt;br /&gt;
con las macros desactivadas, así que solo nos resta saber como abrirlo con las&lt;br /&gt;
macros activadas, las constanes que puedes usar puedes verlas aquí&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.document.MacroExecMode&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.document.MacroExecMode import ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;MacroExecutionMode&amp;#039;&lt;br /&gt;
    opciones.Value = ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Otra opción interesante, es la que nos permite abrir una presentación e iniciarla inmediatamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;StartPresentation&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_impress.odp&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes abrir un archivo como vista previa, útil para evitar que el usuario haga cambios en el, en este estado, los cambios que intente hacer el usuario no se guardaran.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Preview&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, la idea general de abrir un archivo es para obtener datos de el o para manipularlo, ya sea un documento nuevo o uno existente, veamos como guardar los cambios realizados y cerrar el archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    # aquí va todo el código que quieras para manipular el archivo&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto correctamente, presiona Aceptar para gaurdarlo y cerrarlo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # guardamos los cambios&lt;br /&gt;
    doc.store()&lt;br /&gt;
    # cerramos el archivo&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El código anterior funcionara con un archivo existente, pero con uno nuevo no,&lt;br /&gt;
te dará un error, por supuesto no me creas, compruébalo. Los documentos&lt;br /&gt;
tienen un método (&amp;#039;&amp;#039;&amp;#039;hasLocation&amp;#039;&amp;#039;&amp;#039;) que nos informa si un documento ya esta guardado o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
    &lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El primer mensaje debe mostrarte falso (False) porque es un documento nuevo y&lt;br /&gt;
el segundo verdadero (True) por ser un archivo abierto del disco.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También tenemos una propiedad que nos ayuda a saber si un documento ha sido modificado o no, ejecuta la siguiente macro, llamándola desde diferentes documentos, unos ábrelos y modifícalos antes de ejecutarla, otros, solo ábrelos y ejecútala para que notes la diferencia.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def esta_modificado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
 &lt;br /&gt;
    msgbox(doc.isModified())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y otra más que nos informa si el documento es de solo lectura (&amp;#039;&amp;#039;&amp;#039;isReadonly&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que valides antes de intentar guardar un archivo, si este ha sido&lt;br /&gt;
modificado o es de solo lectura. Ahora veamos como guardar un archivo nuevo con el método &amp;#039;&amp;#039;&amp;#039;storeAsUrl&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como requiere dos parámetros, la ruta del archivo y una matriz de&lt;br /&gt;
propiedades, algunas de las cuales veremos a continuación. Toma nota de que si&lt;br /&gt;
el archivo ya existe lo reemplazara sin avisarte por lo que es buena practica&lt;br /&gt;
de programación validar esto, observa como volvemos a usar la librería&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; para saber si un archivo existe ya.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    documentos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def documentos():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;&lt;br /&gt;
    if os.path.exists(ruta):&lt;br /&gt;
        msgbox(u&amp;#039;El archivo existe, no se guardará el nuevo&amp;#039;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
De la macro anterior, &amp;#039;&amp;#039;&amp;#039;es muy importante&amp;#039;&amp;#039;&amp;#039; que tomes nota que para todos&lt;br /&gt;
los métodos de Python que usen rutas de archivos o directorios, se les tienen&lt;br /&gt;
que pasar en las rutas nativas del sistema operativo donde estes trabajando,&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;solo&amp;#039;&amp;#039;&amp;#039; a los métodos de AOO, es a los que se les pasa en notación URL.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Veamos algunas propiedades interesantes para guardar archivos, por ejemplo, guardar con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo pero con contraseña&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_protegido.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como sabes, AOO, soporta la importación/exportación de múltiples formatos de archivos, veamos como guardar, por ejemplo, en formato DOC.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo en formato DOC&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;MS Word 97&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que cuando exportes, uses un formato compatible, es decir, no&lt;br /&gt;
puedes guardar una hoja de calculo como documento de texto. En el [[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices|Apéndice]]&lt;br /&gt;
mostramos una macro para obtener todos los filtros que soporta AOO.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El método storeAsURL también lo puedes usar para abrir un archivo existente y guardarlo con otro nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos con otro nombre&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc_nuevo.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para terminar esta sección, vamos a hacer un poco más interactiva la apertura&lt;br /&gt;
y guardado de archivos, permitamos que el usuario escoja la ruta y el archivo&lt;br /&gt;
desde un cuadro de dialogo, para ello, usaremos el servicio&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt;, que nos permite hacer esto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    # podemos establecer el título&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        # el primer elemento es la ruta seleccionada&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si estableces la propiedad &amp;#039;&amp;#039;&amp;#039;MultiSelectionMode&amp;#039;&amp;#039;&amp;#039; en verdadero, le&lt;br /&gt;
permitiras al usuario seleccionar más de un archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    dlg.setMultiSelectionMode(True)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        archivos = dlg.getFiles()&lt;br /&gt;
        if len(archivos) == 1:&lt;br /&gt;
            # si selecciona uno, devuelve la ruta completa&lt;br /&gt;
            desktop.loadComponentFromURL(archivos[0], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
        else:&lt;br /&gt;
            # si selecciona varios, el primer elemento es la carpeta&lt;br /&gt;
            folder = archivos[0]&lt;br /&gt;
            # los demás elementos son los archivos seleccionados&lt;br /&gt;
            for f in range(1, len(archivos)):&lt;br /&gt;
                desktop.loadComponentFromURL(folder + archivos[f], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si lo notaste, con la macro anterior el usuario puede seleccionar cualquier&lt;br /&gt;
archivo, para limitar las opciones, agrega un filtro con el método&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;appendFilter&amp;#039;&amp;#039;&amp;#039; con solo los tipos de&lt;br /&gt;
archivos que necesites, usa una línea por cada filtro, este método requiere&lt;br /&gt;
dos argumentos, el primero es el título, lo que verá el usuario y el segundo&lt;br /&gt;
es el filtro en si.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, mostramos el cuadro de dialogo Guardar Como, para permitir al usuario&lt;br /&gt;
seleccionar carpeta y nombre de archivo donde guardar su archivo, se usa el&lt;br /&gt;
mismo servicio &amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt; solo cambiando&lt;br /&gt;
algunas de sus propiedades.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_AUTOEXTENSION_PASSWORD&lt;br /&gt;
    &lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Guardar archivo&amp;#039;)&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
    # con esta opción le indicamos que use guardar como con otras opciones&lt;br /&gt;
    dlg.initialize((FILESAVE_AUTOEXTENSION_PASSWORD,))&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        msgbox(ruta)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota que el argumento del método &amp;#039;&amp;#039;&amp;#039;initialize&amp;#039;&amp;#039;&amp;#039; es una tupla.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, para terminar, te mostramos como abrir un archivo de forma oculta.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo cerraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.store()&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es &amp;#039;&amp;#039;&amp;#039;muy importante&amp;#039;&amp;#039;&amp;#039;, que cuando abras un archivo oculto siempre uses el argumento &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, a menos claro esta, que sepas lo que haces, y que, mantengas una referencia a el, para poder cerrarlo en cuanto no lo necesites.&lt;br /&gt;
&lt;br /&gt;
== Algunas tareas comunes en documentos ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exportando a PDF ===&lt;br /&gt;
&lt;br /&gt;
Para exportar a PDF solo hay que establecer el filtro correcto, nota como construimos el nombre del filtro de acuerdo al tipo de documento y como construimos la ruta de acuerdo a la ruta actual donde este guardado el documento solo reemplazando la extensión para que quede en PDF. Estamos haciendo uso de la macro &amp;#039;&amp;#039;&amp;#039;obtener_tipo&amp;#039;&amp;#039;&amp;#039; con unos ligeros cambios para este propósito.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    export_pdf()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def export_pdf():&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    tipo = obtener_tipo(doc)&lt;br /&gt;
    soportados = &amp;#039;calc,writer,draw,impress,math&amp;#039;&lt;br /&gt;
    if tipo in soportados:&lt;br /&gt;
        # establecemos el filtro como PDF&lt;br /&gt;
        opciones = PropertyValue()&lt;br /&gt;
        opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
        opciones.Value = &amp;#039;%s_pdf_Export&amp;#039; % tipo&lt;br /&gt;
        # obtenemos la ruta y reemplazados la extensión por PDF&lt;br /&gt;
        ruta, archivo = os.path.split(doc.getURL())&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
        ruta = os.path.join(ruta, nombre + &amp;#039;.pdf&amp;#039;)&lt;br /&gt;
        # guardamos&lt;br /&gt;
        doc.storeToURL(ruta, (opciones,))&lt;br /&gt;
        msgbox(u&amp;#039;Documento exportado correctamente a PDF&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;Aplicación no soportada&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;basic&amp;#039;}&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            return tipo[t]&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La forma de descomponer la ruta en sus diferentes partes, ya la vimos anteriormente, en este caso, observa como la extensión actual del documento ya no la usaremos por lo que la omitimos con un guión bajo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ocultando y mostrando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para ocultar una ventana, hay que acceder a la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # y la ocultamos&lt;br /&gt;
        ventana.setVisible(False)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Se han ocultado todas las ventanas, presiona Aceptar para mostrarlas&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # tienes que crear de nuevo la enumeración&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # ahora las mostramos&lt;br /&gt;
        ventana.setVisible(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta técnica la puedes usar también para mostrar un archivo que abriste de forma oculta previamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo mostraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    ventana.setVisible(True)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo visible, ahora lo cerramos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Activando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para usamos el método &amp;#039;&amp;#039;&amp;#039;setFocus&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # esperamos 3 segundos y mostramos la ventana&lt;br /&gt;
        time.sleep(3)&lt;br /&gt;
        ventana.setFocus()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando la barra de estado ===&lt;br /&gt;
&lt;br /&gt;
La barra de estado, generalmente en la parte inferior de las aplicaciones, es útil para dar información al usuario, generalmente de un proceso en progreso.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def barra_estado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    barra = doc.getCurrentController().getStatusIndicator()&lt;br /&gt;
    barra.start(u&amp;#039;Se procesaran líneas en tres segundos&amp;#039;, 10)&lt;br /&gt;
    # esta pausa es solo para que veas el mensaje anterior en la barra de estado&lt;br /&gt;
    time.sleep(3)&lt;br /&gt;
    for i in range(1, 11):&lt;br /&gt;
        barra.setValue(i)&lt;br /&gt;
        barra.setText(u&amp;#039;Procesando línea: %s&amp;#039; % i)&lt;br /&gt;
        # pausa de un segundo&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
    # importante para regresar el control a la aplicación&lt;br /&gt;
    barra.end()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando el zoom de la vista ===&lt;br /&gt;
La porcentaje del zoom de la vista del documento se puede modificar con la propiedad &amp;#039;&amp;#039;&amp;#039;ZoomValue&amp;#039;&amp;#039;&amp;#039; del controlador del documento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    ctl = doc.getCurrentController()&lt;br /&gt;
    # cambiamos el zoom a 120%&lt;br /&gt;
    ctl.ZoomValue = 120&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Cambiando posición y tamaño de ventana ===&lt;br /&gt;
&lt;br /&gt;
Para eso usamos el método &amp;#039;&amp;#039;&amp;#039;setPosSize&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora, es importante decirle que valores queremos aplicar con las constantes &amp;lt;idl&amp;gt;com.sun.star.awt.PosSize&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.PosSize import POSSIZE&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    # movemos la ventana a la posicion X = 0, Y = 0&lt;br /&gt;
    # establecemos el ancho (width) = 800 y el alto (height) = 600&lt;br /&gt;
    ventana.setPosSize(0, 0, 800, 600, POSSIZE)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218400</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218400"/>
		<updated>2013-04-28T19:54:30Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Cambiando posición y tamaño de ventana */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con Apache OpenOffice}}&lt;br /&gt;
&lt;br /&gt;
== Conceptos iniciales==&lt;br /&gt;
&lt;br /&gt;
Este es el tema más importante para crear macros, de forma sencilla, pero se ven las bases para trabajar con todo AOO, por eso es importante no avanzar en estas notas, sin antes haber comprendido a cabalidad los temas presentes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;UNO&amp;#039;&amp;#039;&amp;#039; (Universal Network Objects), es la especificación que da acceso a todos los objetos de Apache OpenOffice. Todo lo que quieras saber de esta especificación, lo puedes encontrar en la [[http://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide Guía del desarrollador]] (en ingles).&lt;br /&gt;
&lt;br /&gt;
El &amp;#039;&amp;#039;&amp;#039;API&amp;#039;&amp;#039;&amp;#039; (Application Programer Interface) de Apache OpenOffice proporciona el acceso a toda la funcionalidad de AOO, independientemente del lenguaje. Todo el API de AOO esta en &amp;lt;idl&amp;gt;com.sun.star.module-ix&amp;lt;/idl&amp;gt; (solo ingles).&lt;br /&gt;
&lt;br /&gt;
La comunicación entre objetos UNO se basa en &amp;#039;&amp;#039;&amp;#039;interfaces&amp;#039;&amp;#039;&amp;#039; de objeto.  Las interfaces pueden ser vistos desde el exterior o el interior de un objeto y proporcionan formas de ver o manipular el objeto.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;servicios&amp;#039;&amp;#039;&amp;#039; son agrupaciones lógicas de interfaces, son la forma en que un mismo objeto pueda ofrecer la funcionalidad de varias interfaces.&lt;br /&gt;
&lt;br /&gt;
Los servicios se pueden implementar en librerías compartidas llamadas &amp;#039;&amp;#039;&amp;#039;componentes UNO&amp;#039;&amp;#039;&amp;#039;, con Python podemos crear componentes nuevos y generalmente el usuario final las recibe como una extensión OXT.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;modulos&amp;#039;&amp;#039;&amp;#039; pueden agrupar submodulos, servicios, excepciones, constantes, enumeraciones, etc, se utilizan para especificar bloques coherentes en la API, esto permite tener un API bien estructurada.&lt;br /&gt;
&lt;br /&gt;
== Creando servicios ==&lt;br /&gt;
Para crear un servicio, usamos la &amp;#039;&amp;#039;&amp;#039;fabrica de servicios&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;), una interfaz especial para crear nuevos servicios, pero para llegar a ella, tenemos que hacerlo a traves de la interfaz &amp;#039;&amp;#039;&amp;#039;ComponentContext&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;), como puedes verlo en la siguiente imagen. &lt;br /&gt;
[[Image:UseServices1.png|none|thumb|400px|ComponentContext y ServiceManager]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En pyUNO tenemos dos formas de acceder a esta interfaz, las dos son equivalentes por lo que puedes usar la que prefieras. En la introducción a Python se mencionó que la mayoría de sus herramientas están disponibles en librerias, estás librerias tienen que importarse &amp;#039;&amp;#039;&amp;#039;antes&amp;#039;&amp;#039;&amp;#039; de poder usarse, en nuestro caso importaremos la librería &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; que nos da acceso (entre otras cosas) al contexto de ejecución de AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx1 = XSCRIPTCONTEXT.getComponentContext()&lt;br /&gt;
    ctx2 = uno.getComponentContext()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si te gusta investigar, busca el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; en la carpeta de instalación de AOO, ahí puedes ver de donde sale XSCRIPTCONTEXT}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, podemos acceder a la fábrica de servicios con el &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿como sabemos que este &amp;#039;&amp;#039;&amp;#039;objeto (ComponentContext)&amp;#039;&amp;#039;&amp;#039; tiene este &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;? porque lo estamos demostrando, si, también por eso, pero también porque puedes ver su documentación (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;) en el API de AOO, pero más importante aún, porque podemos hacer que el mismo objeto te diga todo lo que sabe hacer. Para ello haremos uso de una magnifica extensión que te tiene que acompañar el resto de tus días como programador de macros Python, nos referimos a [http://extensions.services.openoffice.org/project/MRI MRI]. Instala (tal vez tengas que reiniciar AOO para poder usarla) y la probamos de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    # llamamos a la extensión MRI y le pasamos el objeto a inspeccionar&lt;br /&gt;
    mri(ctx)&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def mri(target):&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()    &lt;br /&gt;
    mri = sm.createInstanceWithContext(&amp;#039;mytools.Mri&amp;#039;, ctx)&lt;br /&gt;
    mri.inspect(target)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa en la imágen siguiente, como hemos seleccionado los métodos del objeto y nos lista todos los que tenga, hemos remarcado el que por ahora nos interesa &amp;#039;&amp;#039;&amp;#039;getServiceManager()&amp;#039;&amp;#039;&amp;#039;, observa al final de la línea que efectivamente este método nos devuelve una &amp;#039;&amp;#039;&amp;#039;instancia&amp;#039;&amp;#039;&amp;#039; de la interfaz &amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;. &lt;br /&gt;
[[Image:Py_img_0006.png|none|thumb|500px|Usando la extensión MRI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gran ventaja de usar esta extensión (que por cierto esta hecha en Python), es que siempre te devolverá la información directamente del objeto, a esto se le llama &amp;#039;&amp;#039;&amp;#039;instrospección&amp;#039;&amp;#039;&amp;#039;. Acostumbrate a usarla.&lt;br /&gt;
&lt;br /&gt;
Ahora si, ya podemos crear una instancia de cualquier servicio o interfaz disponible en AOO, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existe una forma alternativa de crear este servicio, usando &amp;#039;&amp;#039;&amp;#039;XSCRIPTCONTEXT&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    XSCRIPTCONTEXT.getDesktop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si vuelves a mirar el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; notaras que usa el mismo método para instanciar este servicio}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y para que sirve este servicio? Entre otras cosas para crear nuevos documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
nuevo = desktop.loadComponentFromURL(&amp;#039;private:factory/scalc&amp;#039;, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos a detalle este método y otros relacionados con los documentos de AOO. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; es la instancia de la administración central para todas las aplicaciones AOO.  Todas las ventanas de la aplicación AOO se organizan en una jerarquía de marcos que contienen componentes visibles.  &lt;br /&gt;
&lt;br /&gt;
[[Image:DesktopOverview.png|none|thumb|400px|Desktop administra los componentes y marcos.]]&lt;br /&gt;
&lt;br /&gt;
Para los fines de crear macros es suficiente que recuerdes que, Desktop es el marco raíz de toda la jerarquía de documentos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para crear la instancia del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; usamos un contexto y usamos el método &amp;#039;&amp;#039;&amp;#039;createInstanceWithContext&amp;#039;&amp;#039;&amp;#039;. Otros servicios no requieren de contexto para ser instanciados y usados, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.util.PathSettings&amp;lt;/idl&amp;gt; que nos sirve para obtener las rutas de trabajo actuales en AOO, para estos casos usamos el método &amp;#039;&amp;#039;&amp;#039;createInstance&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    rutas = sm.createInstance(&amp;#039;com.sun.star.util.PathSettings&amp;#039;)&lt;br /&gt;
    # mostramos la ruta de trabajo del usuario&lt;br /&gt;
    print (rutas.Work)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora que ya sabemos instanciar servicios, veamos de nuevo nuestra macro para mostrar un mensaje en pantalla y analicemosla línea a línea para que veas que sencillo es, además, nos servirá para ver otros detalles al programar con Python en AOO. La macro tiene ahora unos ligeros cambios para que trabaje mejor y para explicar algunas cosas, veamos cuales.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la primer línea &amp;#039;&amp;#039;&amp;#039;declaramos&amp;#039;&amp;#039;&amp;#039; nuestra macro, su nombre y los argumentos que necesita, en este caso solo uno &amp;#039;&amp;#039;&amp;#039;message&amp;#039;&amp;#039;&amp;#039; que será el mensaje a mostrar.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la segunda línea, estamos importando (&amp;#039;&amp;#039;&amp;#039;import&amp;#039;&amp;#039;&amp;#039;) la estructura &amp;#039;&amp;#039;&amp;#039;Rectangle&amp;#039;&amp;#039;&amp;#039; desde (&amp;#039;&amp;#039;&amp;#039;from&amp;#039;&amp;#039;&amp;#039;) el modulo &amp;lt;idl&amp;gt;com.sun.star.awt.module-ix&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Las estructuras son un conjunto de valores relacionados, valores que pueden ser de tipos diferentes, pero que son mostrados como una unidad lógica, por ejemplo, la estructura &amp;lt;idl&amp;gt;com.sun.star.awt.Rectangle&amp;lt;/idl&amp;gt; hace referencia a un área rectangular estableciendo su posición y tamaño, en este caso, solo sirve para cumplir los argumentos del método para mostrar nuestro mensaje.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la tercer línea, hacemos otra importación, pero esta vez la hacemos de una constante, específicamente la constante para mostrar el botón &amp;#039;&amp;#039;&amp;#039;Aceptar&amp;#039;&amp;#039;&amp;#039; (OK), estas constantes las puedes ver aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.MessageBoxButtons&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La cuarta línea esta vacía solo para separar la parte de importacion con el resto del código. En la siguiente línea hacemos una validación del argumento pasado a nuestra macro, si el argumento &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; es una instancia de la clase &amp;#039;&amp;#039;&amp;#039;unicode&amp;#039;&amp;#039;&amp;#039; o de la clase &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, entonces la convertimos a &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, esto nos permite pasar a nuestra macro, listas, tuplas, diccionarios y practicamente cualquier objeto, del cual, podremos ver su representación en texto, muchas veces, con información bastante útil.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea ya la hemos estudiado, creamos una instancia del contexto donde se ejecuta AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea también ya la hemos estudiado, creamos una instancia de la fabrica de servicios, una de las instancias más importantes y que usaras constantemente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la siguiente línea creamos una instancia con contexto de un nuevo servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt;, este servicio sirve, entre otras muchas cosas para crear ventanas y mensaje de texto, como el de nuestra macro.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la penultima línea, usamos el método &amp;#039;&amp;#039;&amp;#039;createMessageBox&amp;#039;&amp;#039;&amp;#039; del servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt; para crear nuestro cuadro de mensaje, todos los argumentos de este método puedes verlo aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.XMessageBoxFactory&amp;lt;/idl&amp;gt;, pero aquí los explicamos uno a uno.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Aunque veas muchas líneas, el interpete la considera una sola, esto se logra al estar todos los argumentos entre paréntesis.&lt;br /&gt;
* El primer argumento es la ventana padre (&amp;#039;&amp;#039;&amp;#039;parent&amp;#039;&amp;#039;&amp;#039;) donde será mostrado el cuadro de mensaje, observa como usamos de nuevo el servicio &amp;#039;&amp;#039;&amp;#039;toolkit&amp;#039;&amp;#039;&amp;#039; para recuperar (&amp;#039;&amp;#039;&amp;#039;getDesktopWindow&amp;#039;&amp;#039;&amp;#039;) la ventana padre de AOO.&lt;br /&gt;
* El segundo argumento es el área rectangular del cuadro de mensaje, observa los dos paréntesis al final del nombre de la estructura, son necesarios para inicializarla.&lt;br /&gt;
* El tercer argumento es el tipo de mensaje, dependiendo de este argumento se muestra el icono correspondiente, los valores permitidos son: &amp;#039;&amp;#039;&amp;#039;infobox, warningbox, errorbox, querybox y messbox&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;infobox&amp;#039;&amp;#039;&amp;#039;, el siguiente argumento es ignorado.&lt;br /&gt;
* El cuarto argumento sirve para mostrar botones de comando diferentes, como: &amp;#039;&amp;#039;&amp;#039;Si, No, Cancelar&amp;#039;&amp;#039;&amp;#039;, etc, que están establecidos en las constantes vistas más arriba.&lt;br /&gt;
* El quinto argumento es el título del cuadro de mensaje.&lt;br /&gt;
* Y por ultimo, el mensaje a mostrar, el cual ya validamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la ultima línea al mismo tiempo que mostramos (&amp;#039;&amp;#039;&amp;#039;ejecute&amp;#039;&amp;#039;&amp;#039;) estamos retornando el cuadro de mensaje, esto nos da la posibilidad de capturar el botón al que le haya dado click el usuario, lo cual, veremos más adelante. Todas las macros retornan un valor, aun y cuando este sea un valor vacío (None).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, los servicio los instanciamos y las estructuras y constantes las importamos, y el punto más importante; &amp;#039;&amp;#039;&amp;#039;acostúmbrate a usar, manejar y dominar, la extensión MRI&amp;#039;&amp;#039;&amp;#039;, ella te dice todo lo necesario para trabajar con los objetos UNO de AOO, los demás, es sencillo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== El documento activo ==&lt;br /&gt;
&lt;br /&gt;
Tenemos dos formas de acceder al documento activo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc1 = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
    doc2 = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc1.getIdentifier())&lt;br /&gt;
    print (doc2.getIdentifier())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note| Mira en el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; la forma en que trabaja el método &amp;#039;&amp;#039;&amp;#039;getDocument&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si seguiste nuestra recomendación de asignar la macro de pruebas a una combinación de teclas disponible en todo AOO, prueba a abrir cada uno de los tipos de documentos que puedes ver en el menú &amp;#039;&amp;#039;&amp;#039;Archivo-&amp;gt;Nuevo-&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
[[Image:Py_img_0007.png|none|thumb|500px|Tipos de documentos en AOO]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y a ejecutar la siguiente macro, teniendo como documento activo cada uno de ellos, es decir, activas uno y ejecutas la macro, activas otro y vuelves a llamar a la macro y así sucesivamente con todos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getIdentifier())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los mensajes devueltos en cada documento, son bastante ilustrativos de que &amp;#039;&amp;#039;&amp;#039;tipo de documento&amp;#039;&amp;#039;&amp;#039; se trata. Pero si probaste con todos, habrás notado que con la base de datos nos devuelve un error, si no lo has probado hazlo ahora. Para resolver este caso tenemos varias posibilidades, la primera es controlar la excepción como ya aprendimos en la introducción a Python.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿estamos realmente seguros que ese es el error?, es mejor especificarlo y asegurarnos de que este es el error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tenemos otra alternativa donde no usamos controlador de excepciónes, si no una función que nos dice si un cierto atributo lo posee o no un objeto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    if hasattr(doc, &amp;#039;getIdentifier&amp;#039;):&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Sin atributo getIdentifier&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es mucho mejor esta segunda opción. Aun así, no podemos estar 100% seguros de que cuando no la tenga, el documento sea una base de datos, simplemente estamos excluyendo la posibilidad pero no lo estamos asegurando, probemos con otra propiedad.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getImplementationName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mucho mejor, ahora ya no tenemos errores, pero si probaste de nuevo con todos los tipos de documentos, habrás notado que con &amp;#039;&amp;#039;&amp;#039;Impres&amp;#039;&amp;#039;&amp;#039; y con &amp;#039;&amp;#039;&amp;#039;Draw&amp;#039;&amp;#039;&amp;#039; obtenemos el mismo resultado, por lo que no tenemos la certeza de que tipo de documento es, por lo que descartamos esta propiedad para nuestra finalidad que es identificar fehacientemente cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
Ya vimos que cada objeto UNO soporta diferentes servicios e interfaces, asì que cada documento de AOO (&amp;#039;&amp;#039;&amp;#039;que son objetos&amp;#039;&amp;#039;&amp;#039;) soportan diferentes servicios, algunos son iguales, es decir, comúnes a todos, pero algunos pueden ser únicos para cada documento. Ya vimos como saber si un documento soporta una propiedad, pero para saber si soporta un servicio completo, cambiamos de método, ahora usamos &amp;#039;&amp;#039;&amp;#039;supportsService&amp;#039;&amp;#039;&amp;#039; que nos devuelve falso o verdadero según soporte o no el nombre del servicio pasado como argumento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    res = doc.supportsService(&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;)&lt;br /&gt;
    mensaje = u&amp;#039;No soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    if res:&lt;br /&gt;
        mensaje = u&amp;#039;Soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    print(mensaje)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y mejor aun, podemos saber todos los servicios que soporta un objeto con el método &amp;#039;&amp;#039;&amp;#039;getSupportedServiceNames&amp;#039;&amp;#039;&amp;#039; que nos devuelve una tupla con todos sus nombres.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    servicios = doc.getSupportedServiceNames()&lt;br /&gt;
    &lt;br /&gt;
    print(servicios)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Te queda de tarea probar esta macro en cada uno de los documentos abiertos, incluso puedes probar también el IDE para AOOBasic que incorpora AOO y determinar que servicio usar para diferenciar sin duda cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
== Los documentos abiertos ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todos los documentos abiertos en la sesión de AOO, usamos el método &amp;#039;&amp;#039;&amp;#039;getComponents&amp;#039;&amp;#039;&amp;#039; del objeto &amp;#039;&amp;#039;&amp;#039;Desktop&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;MRI&amp;#039;&amp;#039;&amp;#039;, notarás que este método nos devuelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta interfaz (&amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;) tiene un solo método llamado &amp;#039;&amp;#039;&amp;#039;createEnumeration&amp;#039;&amp;#039;&amp;#039; que nos duelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumeration&amp;lt;/idl&amp;gt; la cual a su vez tiene solo dos métodos, el primero para saber si tenemos más elementos en la enumeración: &amp;#039;&amp;#039;&amp;#039;hasMoreElements&amp;#039;&amp;#039;&amp;#039; y el segundo para acceder al siguiente elemento &amp;#039;&amp;#039;&amp;#039;nextElement&amp;#039;&amp;#039;&amp;#039;, veamoslo con un ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    # mientras tengamos elementos&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        # obtenemos el siguiente elemento&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # mostrámos el tipo de documento&lt;br /&gt;
        mensaje = obtener_tipo(doc)&lt;br /&gt;
        print(mensaje)&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;Calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;Writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;Impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;Draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;Base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;Math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;Basic&amp;#039;}&lt;br /&gt;
    # iteramos entre los tipos de documentos&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        # validamos si soporta el servicio&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            # devolvemos el tipo de documento&lt;br /&gt;
            return &amp;#039;Soy %s&amp;#039; % tipo[t]&lt;br /&gt;
    # si termina sin encontrar un tipo&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como usamos una macro de apoyo para saber que tipo de documento es. Una enumeración no es más que una lista de objetos y es una forma muy común y a veces la única de acceder a ciertos objetos en AOO, es importante que la recuerdes.&lt;br /&gt;
&lt;br /&gt;
== Rutas de archivos y directorios ==&lt;br /&gt;
&lt;br /&gt;
Apache OpenOffice, al ser multiplataforma, hace uso de las rutas de archivos y directorios, en el formato URL, por ejemplo.&lt;br /&gt;
&lt;br /&gt;
file:///home/usuario/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
file:///d:/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta que este formato hace uso de los caracteres 0-9, a-z y A-Z, y cualquier otro carácter será convertido y mostrado con su respectivo código, por ejemplo, los espacios los reemplazara con &amp;#039;&amp;#039;&amp;#039;%20&amp;#039;&amp;#039;&amp;#039;. Siempre que le pases una ruta de archivo a cualquier servicio de AOO, hazlo, casi como una regla, pasarle la ruta en formato Url, para ello, la libreria &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; cuenta con dos funciones muy útiles que hacen el trabajo &amp;#039;&amp;#039;&amp;#039;systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; y &amp;#039;&amp;#039;&amp;#039;fileUrlToSystemPath&amp;#039;&amp;#039;&amp;#039;, veamos como se usan.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def rutas():&lt;br /&gt;
    &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi archivo de Calc.ods&amp;quot;&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # La convertimos al formato URL&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # Regresamos al formato local&lt;br /&gt;
    ruta = uno.fileUrlToSystemPath(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Abre varios documentos existentes y ejecuta la siguiente macro desde cada uno:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def info_ruta():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
    &lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    # obtenemos la ruta en disco&lt;br /&gt;
    ruta =  doc.getURL()&lt;br /&gt;
    # obtenemos las diferentes partes de la ruta&lt;br /&gt;
    ruta, archivo = os.path.split(ruta)&lt;br /&gt;
    nombre, extension = os.path.splitext(archivo)&lt;br /&gt;
    &lt;br /&gt;
    print (ruta)&lt;br /&gt;
    print (uno.fileUrlToSystemPath(ruta))&lt;br /&gt;
    print (archivo)&lt;br /&gt;
    print (nombre)&lt;br /&gt;
    print (extension)&lt;br /&gt;
    &lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hemos importado una nueva librería de Python, &amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; que entre otras muchas cosas, nos permite obtener información de las rutas de archivos como en la macro anterior.&lt;br /&gt;
&lt;br /&gt;
En nuestros siguientes temas, veremos la importancia de usar las rutas de archivos y directorios en formato Url y recuerda que en S.O. Linux, se tiene en cuenta la diferencia entre mayúsculas y minúsculas.&lt;br /&gt;
&lt;br /&gt;
== Creando nuevos documentos ==&lt;br /&gt;
&lt;br /&gt;
El método que nos permite crear nuevos documentos se llama &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039; y es un método del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, por ejemplo, para crear una nueva hoja de calculo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo hay que hacer un pequeño cambio para crear un nuevo documento de texto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y los demás tipos de documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/simpress&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/sdraw&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/smath&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y una base de datos?, probemos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/sbase&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos da un error ¿verdad?&lt;br /&gt;
[[Image:Py_img_0008.png|none|thumb|500px|Error al crear base de datos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No esta soportado. Para saber por que nos da un error, intenta abrir una base de datos nueva, observa como primero, si queremos trabajar con ella, el asistente nos “obliga” primero a guardarla con un nombre y después ya podemos manipularla, esto, solo pasa con las bases de datos, de los demás documentos podemos crear tantos nuevos documentos como queramos sin tener que guardar nada, entonces ¿como creamos una nueva base de datos?, la respuesta es sencilla, del mismo modo que lo hacemos desde la interfaz de usuario, es decir, tenemos que guardar primero la base de datos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
 &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi_Base_Datos.odb&amp;quot;&lt;br /&gt;
    # Creamos el servicio que nos permite manipular bases de datos&lt;br /&gt;
    dbcon = sm.createInstance(&amp;#039;com.sun.star.sdb.DatabaseContext&amp;#039;)&lt;br /&gt;
    # creamos una instancia de una nueva base de datos&lt;br /&gt;
    base = dbcon.createInstance()&lt;br /&gt;
    # establecemos el tipo de base&lt;br /&gt;
    base.URL = &amp;quot;sdbc:embedded:hsqldb&amp;quot;&lt;br /&gt;
    # y la guardamos&lt;br /&gt;
    base.DatabaseDocument.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta dos cosas muy importantes en la macro anterior, el nombre que uses, si ya existe, simplemente lo reemplazara, no te preguntara nada, así que ten cuidado de no usar una ruta o nombre de una base importante que tengas y segundo, la base de datos así creada, no quedara “registrada” en AOO, con lo que no tendrás acceso desde otros programas de la aplicación, más adelante veremos como registrar una base de datos por código.&lt;br /&gt;
&lt;br /&gt;
== Abriendo, guardando y cerrando documentos ==&lt;br /&gt;
Abrir archivos existentes es sumamente sencillo, usamos el mismo método usado&lt;br /&gt;
para crear nuevos documentos &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, pero en el parámetro ruta, le especificamos la ubicación del archivo a abrir de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def documento1():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si tus archivos existen (esto se puede validar), el código anterior los abrirá, &amp;#039;&amp;#039;&amp;#039;siempre&amp;#039;&amp;#039;&amp;#039; utiliza&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;uno.systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; cuando uses rutas de archivos o directorios en&lt;br /&gt;
funciones de AOO que las requieran como argumentos. Ya vimos que el primer&lt;br /&gt;
agumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, es la ruta del archivo a&lt;br /&gt;
abrir, el segundo argumento es una cadena con el nombre del macro (frame)&lt;br /&gt;
donde será mostrado el documento abierto, generalmente si existe este frame se&lt;br /&gt;
usa si no se crea uno nuevo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_cal&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_writer&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existen nombre especiales para este agumento, los más usuales son dos, primero&lt;br /&gt;
que ya hemos estado usando &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; que usa el frame actual y&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039; que siempre crea un nuevo frame.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La recomendación es que uses siempre &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; o &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, un&lt;br /&gt;
escenario puede ser que habrás con &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; una instancia, y después de&lt;br /&gt;
forma oculta uno nuevo con &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, más abajo vemos como abrir un&lt;br /&gt;
documento de forma oculta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si abres una plantilla, esta se comportará de forma normal, es decir, te abrirá una copia de dicha plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_plantilla.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero también podrías querer abrir la plantilla para editarla, en este caso,&lt;br /&gt;
le indicamos en las opciones de apertura esta opción, y aquí vemos como usar&lt;br /&gt;
el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como hemos importado una nueva estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como la instanciamos y asignamos sus valores.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Muy importante, el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
espera una tupla, por eso es que usamos la coma al final del nombre del&lt;br /&gt;
argumento &amp;#039;&amp;#039;&amp;#039;(opciones,)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt; esta conformada por&lt;br /&gt;
un par de valores, un nombre y un valor y es muy frecuentemente usada cuando se&lt;br /&gt;
programa en AOO, para este ejemplo solo hemos usado un par de agumentos,&lt;br /&gt;
siempre van en pares, pero muy bien puede tener más opciones como veremos más&lt;br /&gt;
adelante. En la macro anterior le estamos indicando la propiedad&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (que seria algo así como Es Plantilla), si el valor es&lt;br /&gt;
falso (False), le estamos indicando que queremos abrir la plantilla para&lt;br /&gt;
editarla, en caso contrario (True) abrirá una copia de la plantilla. Lo&lt;br /&gt;
interesante de esta propiedad es que perfectamente la puedes aplicar a archivos&lt;br /&gt;
existentes, es decir, archivos que &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; necesariamente sean plantillas, con&lt;br /&gt;
esta propiedad podemos forzarlos a comportarse como plantillas, por ejemplo, prueba el siguiente código con algún archivo existente que no sea plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como el archivo es un documento de texto normal (ODT), pero con la&lt;br /&gt;
propiedad &amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;, forzamos su apertura como una plantilla.&lt;br /&gt;
&lt;br /&gt;
Otras propiedades interesantes son &amp;#039;&amp;#039;&amp;#039;ReadOnly&amp;#039;&amp;#039;&amp;#039; (Solo Lectura) para abrir un&lt;br /&gt;
archivo como solo lectura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y &amp;#039;&amp;#039;&amp;#039;Password&amp;#039;&amp;#039;&amp;#039; (Contraseña) para abrir archivos con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto puedes combinar cualquier cantidad de opciones siempre y cuando no&lt;br /&gt;
entren en conflicto, es importante que al final, sea una tupla lo que le pasas&lt;br /&gt;
al método, si no, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # creamos una lista vacía&lt;br /&gt;
    opciones = []&lt;br /&gt;
    # creamos la primer propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opcion.Value = True&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
    # creamos la segunda propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opcion.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    # nota que la lista la convertimos en tupla&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, tuple(opciones))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si la contraseña es incorrecta, no obtendrás ningún mensaje, simplemente no&lt;br /&gt;
lo abrira y la variable &amp;#039;&amp;#039;&amp;#039;doc&amp;#039;&amp;#039;&amp;#039; será vacía, puedes validar esto:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if doc is None:&lt;br /&gt;
        print (&amp;#039;No se abrio el documento&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos otras formas de validar y depurar nuestras macros para&lt;br /&gt;
los dificiles casos en donde no obtengamos ningún mensaje de error, pero&lt;br /&gt;
simplemente nuestra macro se niega a hacer su trabajo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mientras un formato de archivo sea soportado por AOO, lo podrás abrir con el&lt;br /&gt;
método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, en el siguiente ejemplo, abrimos un archivo tipo Doc, un Html y un Xls.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_web.html&amp;#039;)&lt;br /&gt;
    doc_h = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_excel.xls&amp;#039;)&lt;br /&gt;
    doc_x = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Qué otras opciones tengo para abrir archivos?. La mayoría están descritas&lt;br /&gt;
en el servicio &amp;lt;idl&amp;gt;com.sun.star.document.MediaDescriptor&amp;lt;/idl&amp;gt;, aquí veremos&lt;br /&gt;
las más usadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cuando abres un archivo por código y este contiene macros, tu puedes&lt;br /&gt;
establecer si se abre con las macros activadas, de forma predeterminada lo abre&lt;br /&gt;
con las macros desactivadas, así que solo nos resta saber como abrirlo con las&lt;br /&gt;
macros activadas, las constanes que puedes usar puedes verlas aquí&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.document.MacroExecMode&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.document.MacroExecMode import ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;MacroExecutionMode&amp;#039;&lt;br /&gt;
    opciones.Value = ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Otra opción interesante, es la que nos permite abrir una presentación e iniciarla inmediatamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;StartPresentation&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_impress.odp&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes abrir un archivo como vista previa, útil para evitar que el usuario haga cambios en el, en este estado, los cambios que intente hacer el usuario no se guardaran.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Preview&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, la idea general de abrir un archivo es para obtener datos de el o para manipularlo, ya sea un documento nuevo o uno existente, veamos como guardar los cambios realizados y cerrar el archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    # aquí va todo el código que quieras para manipular el archivo&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto correctamente, presiona Aceptar para gaurdarlo y cerrarlo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # guardamos los cambios&lt;br /&gt;
    doc.store()&lt;br /&gt;
    # cerramos el archivo&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El código anterior funcionara con un archivo existente, pero con uno nuevo no,&lt;br /&gt;
te dará un error, por supuesto no me creas, compruébalo. Los documentos&lt;br /&gt;
tienen un método (&amp;#039;&amp;#039;&amp;#039;hasLocation&amp;#039;&amp;#039;&amp;#039;) que nos informa si un documento ya esta guardado o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
    &lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El primer mensaje debe mostrarte falso (False) porque es un documento nuevo y&lt;br /&gt;
el segundo verdadero (True) por ser un archivo abierto del disco.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También tenemos una propiedad que nos ayuda a saber si un documento ha sido modificado o no, ejecuta la siguiente macro, llamándola desde diferentes documentos, unos ábrelos y modifícalos antes de ejecutarla, otros, solo ábrelos y ejecútala para que notes la diferencia.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def esta_modificado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
 &lt;br /&gt;
    msgbox(doc.isModified())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y otra más que nos informa si el documento es de solo lectura (&amp;#039;&amp;#039;&amp;#039;isReadonly&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que valides antes de intentar guardar un archivo, si este ha sido&lt;br /&gt;
modificado o es de solo lectura. Ahora veamos como guardar un archivo nuevo con el método &amp;#039;&amp;#039;&amp;#039;storeAsUrl&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como requiere dos parámetros, la ruta del archivo y una matriz de&lt;br /&gt;
propiedades, algunas de las cuales veremos a continuación. Toma nota de que si&lt;br /&gt;
el archivo ya existe lo reemplazara sin avisarte por lo que es buena practica&lt;br /&gt;
de programación validar esto, observa como volvemos a usar la librería&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; para saber si un archivo existe ya.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    documentos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def documentos():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;&lt;br /&gt;
    if os.path.exists(ruta):&lt;br /&gt;
        msgbox(u&amp;#039;El archivo existe, no se guardará el nuevo&amp;#039;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
De la macro anterior, &amp;#039;&amp;#039;&amp;#039;es muy importante&amp;#039;&amp;#039;&amp;#039; que tomes nota que para todos&lt;br /&gt;
los métodos de Python que usen rutas de archivos o directorios, se les tienen&lt;br /&gt;
que pasar en las rutas nativas del sistema operativo donde estes trabajando,&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;solo&amp;#039;&amp;#039;&amp;#039; a los métodos de AOO, es a los que se les pasa en notación URL.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Veamos algunas propiedades interesantes para guardar archivos, por ejemplo, guardar con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo pero con contraseña&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_protegido.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como sabes, AOO, soporta la importación/exportación de múltiples formatos de archivos, veamos como guardar, por ejemplo, en formato DOC.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo en formato DOC&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;MS Word 97&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que cuando exportes, uses un formato compatible, es decir, no&lt;br /&gt;
puedes guardar una hoja de calculo como documento de texto. En el [[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices|Apéndice]]&lt;br /&gt;
mostramos una macro para obtener todos los filtros que soporta AOO.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El método storeAsURL también lo puedes usar para abrir un archivo existente y guardarlo con otro nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos con otro nombre&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc_nuevo.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para terminar esta sección, vamos a hacer un poco más interactiva la apertura&lt;br /&gt;
y guardado de archivos, permitamos que el usuario escoja la ruta y el archivo&lt;br /&gt;
desde un cuadro de dialogo, para ello, usaremos el servicio&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt;, que nos permite hacer esto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    # podemos establecer el título&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        # el primer elemento es la ruta seleccionada&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si estableces la propiedad &amp;#039;&amp;#039;&amp;#039;MultiSelectionMode&amp;#039;&amp;#039;&amp;#039; en verdadero, le&lt;br /&gt;
permitiras al usuario seleccionar más de un archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    dlg.setMultiSelectionMode(True)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        archivos = dlg.getFiles()&lt;br /&gt;
        if len(archivos) == 1:&lt;br /&gt;
            # si selecciona uno, devuelve la ruta completa&lt;br /&gt;
            desktop.loadComponentFromURL(archivos[0], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
        else:&lt;br /&gt;
            # si selecciona varios, el primer elemento es la carpeta&lt;br /&gt;
            folder = archivos[0]&lt;br /&gt;
            # los demás elementos son los archivos seleccionados&lt;br /&gt;
            for f in range(1, len(archivos)):&lt;br /&gt;
                desktop.loadComponentFromURL(folder + archivos[f], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si lo notaste, con la macro anterior el usuario puede seleccionar cualquier&lt;br /&gt;
archivo, para limitar las opciones, agrega un filtro con el método&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;appendFilter&amp;#039;&amp;#039;&amp;#039; con solo los tipos de&lt;br /&gt;
archivos que necesites, usa una línea por cada filtro, este método requiere&lt;br /&gt;
dos argumentos, el primero es el título, lo que verá el usuario y el segundo&lt;br /&gt;
es el filtro en si.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, mostramos el cuadro de dialogo Guardar Como, para permitir al usuario&lt;br /&gt;
seleccionar carpeta y nombre de archivo donde guardar su archivo, se usa el&lt;br /&gt;
mismo servicio &amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt; solo cambiando&lt;br /&gt;
algunas de sus propiedades.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_AUTOEXTENSION_PASSWORD&lt;br /&gt;
    &lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Guardar archivo&amp;#039;)&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
    # con esta opción le indicamos que use guardar como con otras opciones&lt;br /&gt;
    dlg.initialize((FILESAVE_AUTOEXTENSION_PASSWORD,))&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        msgbox(ruta)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota que el argumento del método &amp;#039;&amp;#039;&amp;#039;initialize&amp;#039;&amp;#039;&amp;#039; es una tupla.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, para terminar, te mostramos como abrir un archivo de forma oculta.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo cerraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.store()&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es &amp;#039;&amp;#039;&amp;#039;muy importante&amp;#039;&amp;#039;&amp;#039;, que cuando abras un archivo oculto siempre uses el argumento &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, a menos claro esta, que sepas lo que haces, y que, mantengas una referencia a el, para poder cerrarlo en cuanto no lo necesites.&lt;br /&gt;
&lt;br /&gt;
== Algunas tareas comunes en documentos ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exportando a PDF ===&lt;br /&gt;
&lt;br /&gt;
Para exportar a PDF solo hay que establecer el filtro correcto, nota como construimos el nombre del filtro de acuerdo al tipo de documento y como construimos la ruta de acuerdo a la ruta actual donde este guardado el documento solo reemplazando la extensión para que quede en PDF. Estamos haciendo uso de la macro &amp;#039;&amp;#039;&amp;#039;obtener_tipo&amp;#039;&amp;#039;&amp;#039; con unos ligeros cambios para este propósito.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    export_pdf()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def export_pdf():&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    tipo = obtener_tipo(doc)&lt;br /&gt;
    soportados = &amp;#039;calc,writer,draw,impress,math&amp;#039;&lt;br /&gt;
    if tipo in soportados:&lt;br /&gt;
        # establecemos el filtro como PDF&lt;br /&gt;
        opciones = PropertyValue()&lt;br /&gt;
        opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
        opciones.Value = &amp;#039;%s_pdf_Export&amp;#039; % tipo&lt;br /&gt;
        # obtenemos la ruta y reemplazados la extensión por PDF&lt;br /&gt;
        ruta, archivo = os.path.split(doc.getURL())&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
        ruta = os.path.join(ruta, nombre + &amp;#039;.pdf&amp;#039;)&lt;br /&gt;
        # guardamos&lt;br /&gt;
        doc.storeToURL(ruta, (opciones,))&lt;br /&gt;
        msgbox(u&amp;#039;Documento exportado correctamente a PDF&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;Aplicación no soportada&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;basic&amp;#039;}&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            return tipo[t]&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La forma de descomponer la ruta en sus diferentes partes, ya la vimos anteriormente, en este caso, observa como la extensión actual del documento ya no la usaremos por lo que la omitimos con un guión bajo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ocultando y mostrando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para ocultar una ventana, hay que acceder a la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # y la ocultamos&lt;br /&gt;
        ventana.setVisible(False)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Se han ocultado todas las ventanas, presiona Aceptar para mostrarlas&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # tienes que crear de nuevo la enumeración&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # ahora las mostramos&lt;br /&gt;
        ventana.setVisible(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta técnica la puedes usar también para mostrar un archivo que abriste de forma oculta previamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo mostraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    ventana.setVisible(True)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo visible, ahora lo cerramos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Activando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para usamos el método &amp;#039;&amp;#039;&amp;#039;setFocus&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # esperamos 3 segundos y mostramos la ventana&lt;br /&gt;
        time.sleep(3)&lt;br /&gt;
        ventana.setFocus()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando la barra de estado ===&lt;br /&gt;
&lt;br /&gt;
La barra de estado, generalmente en la parte inferior de las aplicaciones, es útil para dar información al usuario, generalmente de un proceso en progreso.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def barra_estado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    barra = doc.getCurrentController().getStatusIndicator()&lt;br /&gt;
    barra.start(u&amp;#039;Se procesaran líneas en tres segundos&amp;#039;, 10)&lt;br /&gt;
    # esta pausa es solo para que veas el mensaje anterior en la barra de estado&lt;br /&gt;
    time.sleep(3)&lt;br /&gt;
    for i in range(1, 11):&lt;br /&gt;
        barra.setValue(i)&lt;br /&gt;
        barra.setText(u&amp;#039;Procesando línea: %s&amp;#039; % i)&lt;br /&gt;
        # pausa de un segundo&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
    # importante para regresar el control a la aplicación&lt;br /&gt;
    barra.end()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando el zoom de la vista ===&lt;br /&gt;
La porcentaje del zoom de la vista del documento se puede modificar con la propiedad &amp;#039;&amp;#039;&amp;#039;ZoomValue&amp;#039;&amp;#039;&amp;#039; del controlador del documento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    ctl = doc.getCurrentController()&lt;br /&gt;
    # cambiamos el zoom a 120%&lt;br /&gt;
    ctl.ZoomValue = 120&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Cambiando posición y tamaño de ventana ===&lt;br /&gt;
&lt;br /&gt;
Para eso usamos el método &amp;#039;&amp;#039;&amp;#039;setPosSize&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora, es importante decirle que valores queremos aplicar con las constantes &amp;lt;idl&amp;gt;com.sun.star.aw.PosSize&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.PosSize import POSSIZE&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    # movemos la ventana a la posicion X = 0, Y = 0&lt;br /&gt;
    # establecemos el ancho (width) = 800 y el alto (height) = 600&lt;br /&gt;
    ventana.setPosSize(0, 0, 800, 600, POSSIZE)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218399</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218399"/>
		<updated>2013-04-28T19:54:03Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Controlando el zoom de la vista */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con Apache OpenOffice}}&lt;br /&gt;
&lt;br /&gt;
== Conceptos iniciales==&lt;br /&gt;
&lt;br /&gt;
Este es el tema más importante para crear macros, de forma sencilla, pero se ven las bases para trabajar con todo AOO, por eso es importante no avanzar en estas notas, sin antes haber comprendido a cabalidad los temas presentes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;UNO&amp;#039;&amp;#039;&amp;#039; (Universal Network Objects), es la especificación que da acceso a todos los objetos de Apache OpenOffice. Todo lo que quieras saber de esta especificación, lo puedes encontrar en la [[http://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide Guía del desarrollador]] (en ingles).&lt;br /&gt;
&lt;br /&gt;
El &amp;#039;&amp;#039;&amp;#039;API&amp;#039;&amp;#039;&amp;#039; (Application Programer Interface) de Apache OpenOffice proporciona el acceso a toda la funcionalidad de AOO, independientemente del lenguaje. Todo el API de AOO esta en &amp;lt;idl&amp;gt;com.sun.star.module-ix&amp;lt;/idl&amp;gt; (solo ingles).&lt;br /&gt;
&lt;br /&gt;
La comunicación entre objetos UNO se basa en &amp;#039;&amp;#039;&amp;#039;interfaces&amp;#039;&amp;#039;&amp;#039; de objeto.  Las interfaces pueden ser vistos desde el exterior o el interior de un objeto y proporcionan formas de ver o manipular el objeto.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;servicios&amp;#039;&amp;#039;&amp;#039; son agrupaciones lógicas de interfaces, son la forma en que un mismo objeto pueda ofrecer la funcionalidad de varias interfaces.&lt;br /&gt;
&lt;br /&gt;
Los servicios se pueden implementar en librerías compartidas llamadas &amp;#039;&amp;#039;&amp;#039;componentes UNO&amp;#039;&amp;#039;&amp;#039;, con Python podemos crear componentes nuevos y generalmente el usuario final las recibe como una extensión OXT.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;modulos&amp;#039;&amp;#039;&amp;#039; pueden agrupar submodulos, servicios, excepciones, constantes, enumeraciones, etc, se utilizan para especificar bloques coherentes en la API, esto permite tener un API bien estructurada.&lt;br /&gt;
&lt;br /&gt;
== Creando servicios ==&lt;br /&gt;
Para crear un servicio, usamos la &amp;#039;&amp;#039;&amp;#039;fabrica de servicios&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;), una interfaz especial para crear nuevos servicios, pero para llegar a ella, tenemos que hacerlo a traves de la interfaz &amp;#039;&amp;#039;&amp;#039;ComponentContext&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;), como puedes verlo en la siguiente imagen. &lt;br /&gt;
[[Image:UseServices1.png|none|thumb|400px|ComponentContext y ServiceManager]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En pyUNO tenemos dos formas de acceder a esta interfaz, las dos son equivalentes por lo que puedes usar la que prefieras. En la introducción a Python se mencionó que la mayoría de sus herramientas están disponibles en librerias, estás librerias tienen que importarse &amp;#039;&amp;#039;&amp;#039;antes&amp;#039;&amp;#039;&amp;#039; de poder usarse, en nuestro caso importaremos la librería &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; que nos da acceso (entre otras cosas) al contexto de ejecución de AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx1 = XSCRIPTCONTEXT.getComponentContext()&lt;br /&gt;
    ctx2 = uno.getComponentContext()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si te gusta investigar, busca el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; en la carpeta de instalación de AOO, ahí puedes ver de donde sale XSCRIPTCONTEXT}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, podemos acceder a la fábrica de servicios con el &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿como sabemos que este &amp;#039;&amp;#039;&amp;#039;objeto (ComponentContext)&amp;#039;&amp;#039;&amp;#039; tiene este &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;? porque lo estamos demostrando, si, también por eso, pero también porque puedes ver su documentación (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;) en el API de AOO, pero más importante aún, porque podemos hacer que el mismo objeto te diga todo lo que sabe hacer. Para ello haremos uso de una magnifica extensión que te tiene que acompañar el resto de tus días como programador de macros Python, nos referimos a [http://extensions.services.openoffice.org/project/MRI MRI]. Instala (tal vez tengas que reiniciar AOO para poder usarla) y la probamos de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    # llamamos a la extensión MRI y le pasamos el objeto a inspeccionar&lt;br /&gt;
    mri(ctx)&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def mri(target):&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()    &lt;br /&gt;
    mri = sm.createInstanceWithContext(&amp;#039;mytools.Mri&amp;#039;, ctx)&lt;br /&gt;
    mri.inspect(target)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa en la imágen siguiente, como hemos seleccionado los métodos del objeto y nos lista todos los que tenga, hemos remarcado el que por ahora nos interesa &amp;#039;&amp;#039;&amp;#039;getServiceManager()&amp;#039;&amp;#039;&amp;#039;, observa al final de la línea que efectivamente este método nos devuelve una &amp;#039;&amp;#039;&amp;#039;instancia&amp;#039;&amp;#039;&amp;#039; de la interfaz &amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;. &lt;br /&gt;
[[Image:Py_img_0006.png|none|thumb|500px|Usando la extensión MRI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gran ventaja de usar esta extensión (que por cierto esta hecha en Python), es que siempre te devolverá la información directamente del objeto, a esto se le llama &amp;#039;&amp;#039;&amp;#039;instrospección&amp;#039;&amp;#039;&amp;#039;. Acostumbrate a usarla.&lt;br /&gt;
&lt;br /&gt;
Ahora si, ya podemos crear una instancia de cualquier servicio o interfaz disponible en AOO, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existe una forma alternativa de crear este servicio, usando &amp;#039;&amp;#039;&amp;#039;XSCRIPTCONTEXT&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    XSCRIPTCONTEXT.getDesktop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si vuelves a mirar el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; notaras que usa el mismo método para instanciar este servicio}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y para que sirve este servicio? Entre otras cosas para crear nuevos documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
nuevo = desktop.loadComponentFromURL(&amp;#039;private:factory/scalc&amp;#039;, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos a detalle este método y otros relacionados con los documentos de AOO. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; es la instancia de la administración central para todas las aplicaciones AOO.  Todas las ventanas de la aplicación AOO se organizan en una jerarquía de marcos que contienen componentes visibles.  &lt;br /&gt;
&lt;br /&gt;
[[Image:DesktopOverview.png|none|thumb|400px|Desktop administra los componentes y marcos.]]&lt;br /&gt;
&lt;br /&gt;
Para los fines de crear macros es suficiente que recuerdes que, Desktop es el marco raíz de toda la jerarquía de documentos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para crear la instancia del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; usamos un contexto y usamos el método &amp;#039;&amp;#039;&amp;#039;createInstanceWithContext&amp;#039;&amp;#039;&amp;#039;. Otros servicios no requieren de contexto para ser instanciados y usados, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.util.PathSettings&amp;lt;/idl&amp;gt; que nos sirve para obtener las rutas de trabajo actuales en AOO, para estos casos usamos el método &amp;#039;&amp;#039;&amp;#039;createInstance&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    rutas = sm.createInstance(&amp;#039;com.sun.star.util.PathSettings&amp;#039;)&lt;br /&gt;
    # mostramos la ruta de trabajo del usuario&lt;br /&gt;
    print (rutas.Work)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora que ya sabemos instanciar servicios, veamos de nuevo nuestra macro para mostrar un mensaje en pantalla y analicemosla línea a línea para que veas que sencillo es, además, nos servirá para ver otros detalles al programar con Python en AOO. La macro tiene ahora unos ligeros cambios para que trabaje mejor y para explicar algunas cosas, veamos cuales.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la primer línea &amp;#039;&amp;#039;&amp;#039;declaramos&amp;#039;&amp;#039;&amp;#039; nuestra macro, su nombre y los argumentos que necesita, en este caso solo uno &amp;#039;&amp;#039;&amp;#039;message&amp;#039;&amp;#039;&amp;#039; que será el mensaje a mostrar.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la segunda línea, estamos importando (&amp;#039;&amp;#039;&amp;#039;import&amp;#039;&amp;#039;&amp;#039;) la estructura &amp;#039;&amp;#039;&amp;#039;Rectangle&amp;#039;&amp;#039;&amp;#039; desde (&amp;#039;&amp;#039;&amp;#039;from&amp;#039;&amp;#039;&amp;#039;) el modulo &amp;lt;idl&amp;gt;com.sun.star.awt.module-ix&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Las estructuras son un conjunto de valores relacionados, valores que pueden ser de tipos diferentes, pero que son mostrados como una unidad lógica, por ejemplo, la estructura &amp;lt;idl&amp;gt;com.sun.star.awt.Rectangle&amp;lt;/idl&amp;gt; hace referencia a un área rectangular estableciendo su posición y tamaño, en este caso, solo sirve para cumplir los argumentos del método para mostrar nuestro mensaje.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la tercer línea, hacemos otra importación, pero esta vez la hacemos de una constante, específicamente la constante para mostrar el botón &amp;#039;&amp;#039;&amp;#039;Aceptar&amp;#039;&amp;#039;&amp;#039; (OK), estas constantes las puedes ver aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.MessageBoxButtons&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La cuarta línea esta vacía solo para separar la parte de importacion con el resto del código. En la siguiente línea hacemos una validación del argumento pasado a nuestra macro, si el argumento &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; es una instancia de la clase &amp;#039;&amp;#039;&amp;#039;unicode&amp;#039;&amp;#039;&amp;#039; o de la clase &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, entonces la convertimos a &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, esto nos permite pasar a nuestra macro, listas, tuplas, diccionarios y practicamente cualquier objeto, del cual, podremos ver su representación en texto, muchas veces, con información bastante útil.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea ya la hemos estudiado, creamos una instancia del contexto donde se ejecuta AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea también ya la hemos estudiado, creamos una instancia de la fabrica de servicios, una de las instancias más importantes y que usaras constantemente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la siguiente línea creamos una instancia con contexto de un nuevo servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt;, este servicio sirve, entre otras muchas cosas para crear ventanas y mensaje de texto, como el de nuestra macro.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la penultima línea, usamos el método &amp;#039;&amp;#039;&amp;#039;createMessageBox&amp;#039;&amp;#039;&amp;#039; del servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt; para crear nuestro cuadro de mensaje, todos los argumentos de este método puedes verlo aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.XMessageBoxFactory&amp;lt;/idl&amp;gt;, pero aquí los explicamos uno a uno.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Aunque veas muchas líneas, el interpete la considera una sola, esto se logra al estar todos los argumentos entre paréntesis.&lt;br /&gt;
* El primer argumento es la ventana padre (&amp;#039;&amp;#039;&amp;#039;parent&amp;#039;&amp;#039;&amp;#039;) donde será mostrado el cuadro de mensaje, observa como usamos de nuevo el servicio &amp;#039;&amp;#039;&amp;#039;toolkit&amp;#039;&amp;#039;&amp;#039; para recuperar (&amp;#039;&amp;#039;&amp;#039;getDesktopWindow&amp;#039;&amp;#039;&amp;#039;) la ventana padre de AOO.&lt;br /&gt;
* El segundo argumento es el área rectangular del cuadro de mensaje, observa los dos paréntesis al final del nombre de la estructura, son necesarios para inicializarla.&lt;br /&gt;
* El tercer argumento es el tipo de mensaje, dependiendo de este argumento se muestra el icono correspondiente, los valores permitidos son: &amp;#039;&amp;#039;&amp;#039;infobox, warningbox, errorbox, querybox y messbox&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;infobox&amp;#039;&amp;#039;&amp;#039;, el siguiente argumento es ignorado.&lt;br /&gt;
* El cuarto argumento sirve para mostrar botones de comando diferentes, como: &amp;#039;&amp;#039;&amp;#039;Si, No, Cancelar&amp;#039;&amp;#039;&amp;#039;, etc, que están establecidos en las constantes vistas más arriba.&lt;br /&gt;
* El quinto argumento es el título del cuadro de mensaje.&lt;br /&gt;
* Y por ultimo, el mensaje a mostrar, el cual ya validamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la ultima línea al mismo tiempo que mostramos (&amp;#039;&amp;#039;&amp;#039;ejecute&amp;#039;&amp;#039;&amp;#039;) estamos retornando el cuadro de mensaje, esto nos da la posibilidad de capturar el botón al que le haya dado click el usuario, lo cual, veremos más adelante. Todas las macros retornan un valor, aun y cuando este sea un valor vacío (None).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, los servicio los instanciamos y las estructuras y constantes las importamos, y el punto más importante; &amp;#039;&amp;#039;&amp;#039;acostúmbrate a usar, manejar y dominar, la extensión MRI&amp;#039;&amp;#039;&amp;#039;, ella te dice todo lo necesario para trabajar con los objetos UNO de AOO, los demás, es sencillo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== El documento activo ==&lt;br /&gt;
&lt;br /&gt;
Tenemos dos formas de acceder al documento activo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc1 = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
    doc2 = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc1.getIdentifier())&lt;br /&gt;
    print (doc2.getIdentifier())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note| Mira en el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; la forma en que trabaja el método &amp;#039;&amp;#039;&amp;#039;getDocument&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si seguiste nuestra recomendación de asignar la macro de pruebas a una combinación de teclas disponible en todo AOO, prueba a abrir cada uno de los tipos de documentos que puedes ver en el menú &amp;#039;&amp;#039;&amp;#039;Archivo-&amp;gt;Nuevo-&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
[[Image:Py_img_0007.png|none|thumb|500px|Tipos de documentos en AOO]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y a ejecutar la siguiente macro, teniendo como documento activo cada uno de ellos, es decir, activas uno y ejecutas la macro, activas otro y vuelves a llamar a la macro y así sucesivamente con todos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getIdentifier())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los mensajes devueltos en cada documento, son bastante ilustrativos de que &amp;#039;&amp;#039;&amp;#039;tipo de documento&amp;#039;&amp;#039;&amp;#039; se trata. Pero si probaste con todos, habrás notado que con la base de datos nos devuelve un error, si no lo has probado hazlo ahora. Para resolver este caso tenemos varias posibilidades, la primera es controlar la excepción como ya aprendimos en la introducción a Python.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿estamos realmente seguros que ese es el error?, es mejor especificarlo y asegurarnos de que este es el error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tenemos otra alternativa donde no usamos controlador de excepciónes, si no una función que nos dice si un cierto atributo lo posee o no un objeto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    if hasattr(doc, &amp;#039;getIdentifier&amp;#039;):&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Sin atributo getIdentifier&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es mucho mejor esta segunda opción. Aun así, no podemos estar 100% seguros de que cuando no la tenga, el documento sea una base de datos, simplemente estamos excluyendo la posibilidad pero no lo estamos asegurando, probemos con otra propiedad.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getImplementationName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mucho mejor, ahora ya no tenemos errores, pero si probaste de nuevo con todos los tipos de documentos, habrás notado que con &amp;#039;&amp;#039;&amp;#039;Impres&amp;#039;&amp;#039;&amp;#039; y con &amp;#039;&amp;#039;&amp;#039;Draw&amp;#039;&amp;#039;&amp;#039; obtenemos el mismo resultado, por lo que no tenemos la certeza de que tipo de documento es, por lo que descartamos esta propiedad para nuestra finalidad que es identificar fehacientemente cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
Ya vimos que cada objeto UNO soporta diferentes servicios e interfaces, asì que cada documento de AOO (&amp;#039;&amp;#039;&amp;#039;que son objetos&amp;#039;&amp;#039;&amp;#039;) soportan diferentes servicios, algunos son iguales, es decir, comúnes a todos, pero algunos pueden ser únicos para cada documento. Ya vimos como saber si un documento soporta una propiedad, pero para saber si soporta un servicio completo, cambiamos de método, ahora usamos &amp;#039;&amp;#039;&amp;#039;supportsService&amp;#039;&amp;#039;&amp;#039; que nos devuelve falso o verdadero según soporte o no el nombre del servicio pasado como argumento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    res = doc.supportsService(&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;)&lt;br /&gt;
    mensaje = u&amp;#039;No soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    if res:&lt;br /&gt;
        mensaje = u&amp;#039;Soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    print(mensaje)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y mejor aun, podemos saber todos los servicios que soporta un objeto con el método &amp;#039;&amp;#039;&amp;#039;getSupportedServiceNames&amp;#039;&amp;#039;&amp;#039; que nos devuelve una tupla con todos sus nombres.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    servicios = doc.getSupportedServiceNames()&lt;br /&gt;
    &lt;br /&gt;
    print(servicios)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Te queda de tarea probar esta macro en cada uno de los documentos abiertos, incluso puedes probar también el IDE para AOOBasic que incorpora AOO y determinar que servicio usar para diferenciar sin duda cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
== Los documentos abiertos ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todos los documentos abiertos en la sesión de AOO, usamos el método &amp;#039;&amp;#039;&amp;#039;getComponents&amp;#039;&amp;#039;&amp;#039; del objeto &amp;#039;&amp;#039;&amp;#039;Desktop&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;MRI&amp;#039;&amp;#039;&amp;#039;, notarás que este método nos devuelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta interfaz (&amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;) tiene un solo método llamado &amp;#039;&amp;#039;&amp;#039;createEnumeration&amp;#039;&amp;#039;&amp;#039; que nos duelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumeration&amp;lt;/idl&amp;gt; la cual a su vez tiene solo dos métodos, el primero para saber si tenemos más elementos en la enumeración: &amp;#039;&amp;#039;&amp;#039;hasMoreElements&amp;#039;&amp;#039;&amp;#039; y el segundo para acceder al siguiente elemento &amp;#039;&amp;#039;&amp;#039;nextElement&amp;#039;&amp;#039;&amp;#039;, veamoslo con un ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    # mientras tengamos elementos&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        # obtenemos el siguiente elemento&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # mostrámos el tipo de documento&lt;br /&gt;
        mensaje = obtener_tipo(doc)&lt;br /&gt;
        print(mensaje)&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;Calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;Writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;Impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;Draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;Base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;Math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;Basic&amp;#039;}&lt;br /&gt;
    # iteramos entre los tipos de documentos&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        # validamos si soporta el servicio&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            # devolvemos el tipo de documento&lt;br /&gt;
            return &amp;#039;Soy %s&amp;#039; % tipo[t]&lt;br /&gt;
    # si termina sin encontrar un tipo&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como usamos una macro de apoyo para saber que tipo de documento es. Una enumeración no es más que una lista de objetos y es una forma muy común y a veces la única de acceder a ciertos objetos en AOO, es importante que la recuerdes.&lt;br /&gt;
&lt;br /&gt;
== Rutas de archivos y directorios ==&lt;br /&gt;
&lt;br /&gt;
Apache OpenOffice, al ser multiplataforma, hace uso de las rutas de archivos y directorios, en el formato URL, por ejemplo.&lt;br /&gt;
&lt;br /&gt;
file:///home/usuario/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
file:///d:/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta que este formato hace uso de los caracteres 0-9, a-z y A-Z, y cualquier otro carácter será convertido y mostrado con su respectivo código, por ejemplo, los espacios los reemplazara con &amp;#039;&amp;#039;&amp;#039;%20&amp;#039;&amp;#039;&amp;#039;. Siempre que le pases una ruta de archivo a cualquier servicio de AOO, hazlo, casi como una regla, pasarle la ruta en formato Url, para ello, la libreria &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; cuenta con dos funciones muy útiles que hacen el trabajo &amp;#039;&amp;#039;&amp;#039;systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; y &amp;#039;&amp;#039;&amp;#039;fileUrlToSystemPath&amp;#039;&amp;#039;&amp;#039;, veamos como se usan.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def rutas():&lt;br /&gt;
    &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi archivo de Calc.ods&amp;quot;&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # La convertimos al formato URL&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # Regresamos al formato local&lt;br /&gt;
    ruta = uno.fileUrlToSystemPath(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Abre varios documentos existentes y ejecuta la siguiente macro desde cada uno:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def info_ruta():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
    &lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    # obtenemos la ruta en disco&lt;br /&gt;
    ruta =  doc.getURL()&lt;br /&gt;
    # obtenemos las diferentes partes de la ruta&lt;br /&gt;
    ruta, archivo = os.path.split(ruta)&lt;br /&gt;
    nombre, extension = os.path.splitext(archivo)&lt;br /&gt;
    &lt;br /&gt;
    print (ruta)&lt;br /&gt;
    print (uno.fileUrlToSystemPath(ruta))&lt;br /&gt;
    print (archivo)&lt;br /&gt;
    print (nombre)&lt;br /&gt;
    print (extension)&lt;br /&gt;
    &lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hemos importado una nueva librería de Python, &amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; que entre otras muchas cosas, nos permite obtener información de las rutas de archivos como en la macro anterior.&lt;br /&gt;
&lt;br /&gt;
En nuestros siguientes temas, veremos la importancia de usar las rutas de archivos y directorios en formato Url y recuerda que en S.O. Linux, se tiene en cuenta la diferencia entre mayúsculas y minúsculas.&lt;br /&gt;
&lt;br /&gt;
== Creando nuevos documentos ==&lt;br /&gt;
&lt;br /&gt;
El método que nos permite crear nuevos documentos se llama &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039; y es un método del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, por ejemplo, para crear una nueva hoja de calculo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo hay que hacer un pequeño cambio para crear un nuevo documento de texto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y los demás tipos de documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/simpress&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/sdraw&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/smath&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y una base de datos?, probemos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/sbase&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos da un error ¿verdad?&lt;br /&gt;
[[Image:Py_img_0008.png|none|thumb|500px|Error al crear base de datos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No esta soportado. Para saber por que nos da un error, intenta abrir una base de datos nueva, observa como primero, si queremos trabajar con ella, el asistente nos “obliga” primero a guardarla con un nombre y después ya podemos manipularla, esto, solo pasa con las bases de datos, de los demás documentos podemos crear tantos nuevos documentos como queramos sin tener que guardar nada, entonces ¿como creamos una nueva base de datos?, la respuesta es sencilla, del mismo modo que lo hacemos desde la interfaz de usuario, es decir, tenemos que guardar primero la base de datos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
 &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi_Base_Datos.odb&amp;quot;&lt;br /&gt;
    # Creamos el servicio que nos permite manipular bases de datos&lt;br /&gt;
    dbcon = sm.createInstance(&amp;#039;com.sun.star.sdb.DatabaseContext&amp;#039;)&lt;br /&gt;
    # creamos una instancia de una nueva base de datos&lt;br /&gt;
    base = dbcon.createInstance()&lt;br /&gt;
    # establecemos el tipo de base&lt;br /&gt;
    base.URL = &amp;quot;sdbc:embedded:hsqldb&amp;quot;&lt;br /&gt;
    # y la guardamos&lt;br /&gt;
    base.DatabaseDocument.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta dos cosas muy importantes en la macro anterior, el nombre que uses, si ya existe, simplemente lo reemplazara, no te preguntara nada, así que ten cuidado de no usar una ruta o nombre de una base importante que tengas y segundo, la base de datos así creada, no quedara “registrada” en AOO, con lo que no tendrás acceso desde otros programas de la aplicación, más adelante veremos como registrar una base de datos por código.&lt;br /&gt;
&lt;br /&gt;
== Abriendo, guardando y cerrando documentos ==&lt;br /&gt;
Abrir archivos existentes es sumamente sencillo, usamos el mismo método usado&lt;br /&gt;
para crear nuevos documentos &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, pero en el parámetro ruta, le especificamos la ubicación del archivo a abrir de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def documento1():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si tus archivos existen (esto se puede validar), el código anterior los abrirá, &amp;#039;&amp;#039;&amp;#039;siempre&amp;#039;&amp;#039;&amp;#039; utiliza&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;uno.systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; cuando uses rutas de archivos o directorios en&lt;br /&gt;
funciones de AOO que las requieran como argumentos. Ya vimos que el primer&lt;br /&gt;
agumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, es la ruta del archivo a&lt;br /&gt;
abrir, el segundo argumento es una cadena con el nombre del macro (frame)&lt;br /&gt;
donde será mostrado el documento abierto, generalmente si existe este frame se&lt;br /&gt;
usa si no se crea uno nuevo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_cal&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_writer&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existen nombre especiales para este agumento, los más usuales son dos, primero&lt;br /&gt;
que ya hemos estado usando &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; que usa el frame actual y&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039; que siempre crea un nuevo frame.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La recomendación es que uses siempre &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; o &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, un&lt;br /&gt;
escenario puede ser que habrás con &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; una instancia, y después de&lt;br /&gt;
forma oculta uno nuevo con &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, más abajo vemos como abrir un&lt;br /&gt;
documento de forma oculta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si abres una plantilla, esta se comportará de forma normal, es decir, te abrirá una copia de dicha plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_plantilla.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero también podrías querer abrir la plantilla para editarla, en este caso,&lt;br /&gt;
le indicamos en las opciones de apertura esta opción, y aquí vemos como usar&lt;br /&gt;
el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como hemos importado una nueva estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como la instanciamos y asignamos sus valores.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Muy importante, el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
espera una tupla, por eso es que usamos la coma al final del nombre del&lt;br /&gt;
argumento &amp;#039;&amp;#039;&amp;#039;(opciones,)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt; esta conformada por&lt;br /&gt;
un par de valores, un nombre y un valor y es muy frecuentemente usada cuando se&lt;br /&gt;
programa en AOO, para este ejemplo solo hemos usado un par de agumentos,&lt;br /&gt;
siempre van en pares, pero muy bien puede tener más opciones como veremos más&lt;br /&gt;
adelante. En la macro anterior le estamos indicando la propiedad&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (que seria algo así como Es Plantilla), si el valor es&lt;br /&gt;
falso (False), le estamos indicando que queremos abrir la plantilla para&lt;br /&gt;
editarla, en caso contrario (True) abrirá una copia de la plantilla. Lo&lt;br /&gt;
interesante de esta propiedad es que perfectamente la puedes aplicar a archivos&lt;br /&gt;
existentes, es decir, archivos que &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; necesariamente sean plantillas, con&lt;br /&gt;
esta propiedad podemos forzarlos a comportarse como plantillas, por ejemplo, prueba el siguiente código con algún archivo existente que no sea plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como el archivo es un documento de texto normal (ODT), pero con la&lt;br /&gt;
propiedad &amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;, forzamos su apertura como una plantilla.&lt;br /&gt;
&lt;br /&gt;
Otras propiedades interesantes son &amp;#039;&amp;#039;&amp;#039;ReadOnly&amp;#039;&amp;#039;&amp;#039; (Solo Lectura) para abrir un&lt;br /&gt;
archivo como solo lectura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y &amp;#039;&amp;#039;&amp;#039;Password&amp;#039;&amp;#039;&amp;#039; (Contraseña) para abrir archivos con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto puedes combinar cualquier cantidad de opciones siempre y cuando no&lt;br /&gt;
entren en conflicto, es importante que al final, sea una tupla lo que le pasas&lt;br /&gt;
al método, si no, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # creamos una lista vacía&lt;br /&gt;
    opciones = []&lt;br /&gt;
    # creamos la primer propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opcion.Value = True&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
    # creamos la segunda propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opcion.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    # nota que la lista la convertimos en tupla&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, tuple(opciones))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si la contraseña es incorrecta, no obtendrás ningún mensaje, simplemente no&lt;br /&gt;
lo abrira y la variable &amp;#039;&amp;#039;&amp;#039;doc&amp;#039;&amp;#039;&amp;#039; será vacía, puedes validar esto:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if doc is None:&lt;br /&gt;
        print (&amp;#039;No se abrio el documento&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos otras formas de validar y depurar nuestras macros para&lt;br /&gt;
los dificiles casos en donde no obtengamos ningún mensaje de error, pero&lt;br /&gt;
simplemente nuestra macro se niega a hacer su trabajo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mientras un formato de archivo sea soportado por AOO, lo podrás abrir con el&lt;br /&gt;
método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, en el siguiente ejemplo, abrimos un archivo tipo Doc, un Html y un Xls.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_web.html&amp;#039;)&lt;br /&gt;
    doc_h = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_excel.xls&amp;#039;)&lt;br /&gt;
    doc_x = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Qué otras opciones tengo para abrir archivos?. La mayoría están descritas&lt;br /&gt;
en el servicio &amp;lt;idl&amp;gt;com.sun.star.document.MediaDescriptor&amp;lt;/idl&amp;gt;, aquí veremos&lt;br /&gt;
las más usadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cuando abres un archivo por código y este contiene macros, tu puedes&lt;br /&gt;
establecer si se abre con las macros activadas, de forma predeterminada lo abre&lt;br /&gt;
con las macros desactivadas, así que solo nos resta saber como abrirlo con las&lt;br /&gt;
macros activadas, las constanes que puedes usar puedes verlas aquí&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.document.MacroExecMode&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.document.MacroExecMode import ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;MacroExecutionMode&amp;#039;&lt;br /&gt;
    opciones.Value = ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Otra opción interesante, es la que nos permite abrir una presentación e iniciarla inmediatamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;StartPresentation&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_impress.odp&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes abrir un archivo como vista previa, útil para evitar que el usuario haga cambios en el, en este estado, los cambios que intente hacer el usuario no se guardaran.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Preview&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, la idea general de abrir un archivo es para obtener datos de el o para manipularlo, ya sea un documento nuevo o uno existente, veamos como guardar los cambios realizados y cerrar el archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    # aquí va todo el código que quieras para manipular el archivo&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto correctamente, presiona Aceptar para gaurdarlo y cerrarlo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # guardamos los cambios&lt;br /&gt;
    doc.store()&lt;br /&gt;
    # cerramos el archivo&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El código anterior funcionara con un archivo existente, pero con uno nuevo no,&lt;br /&gt;
te dará un error, por supuesto no me creas, compruébalo. Los documentos&lt;br /&gt;
tienen un método (&amp;#039;&amp;#039;&amp;#039;hasLocation&amp;#039;&amp;#039;&amp;#039;) que nos informa si un documento ya esta guardado o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
    &lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El primer mensaje debe mostrarte falso (False) porque es un documento nuevo y&lt;br /&gt;
el segundo verdadero (True) por ser un archivo abierto del disco.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También tenemos una propiedad que nos ayuda a saber si un documento ha sido modificado o no, ejecuta la siguiente macro, llamándola desde diferentes documentos, unos ábrelos y modifícalos antes de ejecutarla, otros, solo ábrelos y ejecútala para que notes la diferencia.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def esta_modificado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
 &lt;br /&gt;
    msgbox(doc.isModified())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y otra más que nos informa si el documento es de solo lectura (&amp;#039;&amp;#039;&amp;#039;isReadonly&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que valides antes de intentar guardar un archivo, si este ha sido&lt;br /&gt;
modificado o es de solo lectura. Ahora veamos como guardar un archivo nuevo con el método &amp;#039;&amp;#039;&amp;#039;storeAsUrl&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como requiere dos parámetros, la ruta del archivo y una matriz de&lt;br /&gt;
propiedades, algunas de las cuales veremos a continuación. Toma nota de que si&lt;br /&gt;
el archivo ya existe lo reemplazara sin avisarte por lo que es buena practica&lt;br /&gt;
de programación validar esto, observa como volvemos a usar la librería&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; para saber si un archivo existe ya.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    documentos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def documentos():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;&lt;br /&gt;
    if os.path.exists(ruta):&lt;br /&gt;
        msgbox(u&amp;#039;El archivo existe, no se guardará el nuevo&amp;#039;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
De la macro anterior, &amp;#039;&amp;#039;&amp;#039;es muy importante&amp;#039;&amp;#039;&amp;#039; que tomes nota que para todos&lt;br /&gt;
los métodos de Python que usen rutas de archivos o directorios, se les tienen&lt;br /&gt;
que pasar en las rutas nativas del sistema operativo donde estes trabajando,&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;solo&amp;#039;&amp;#039;&amp;#039; a los métodos de AOO, es a los que se les pasa en notación URL.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Veamos algunas propiedades interesantes para guardar archivos, por ejemplo, guardar con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo pero con contraseña&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_protegido.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como sabes, AOO, soporta la importación/exportación de múltiples formatos de archivos, veamos como guardar, por ejemplo, en formato DOC.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo en formato DOC&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;MS Word 97&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que cuando exportes, uses un formato compatible, es decir, no&lt;br /&gt;
puedes guardar una hoja de calculo como documento de texto. En el [[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices|Apéndice]]&lt;br /&gt;
mostramos una macro para obtener todos los filtros que soporta AOO.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El método storeAsURL también lo puedes usar para abrir un archivo existente y guardarlo con otro nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos con otro nombre&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc_nuevo.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para terminar esta sección, vamos a hacer un poco más interactiva la apertura&lt;br /&gt;
y guardado de archivos, permitamos que el usuario escoja la ruta y el archivo&lt;br /&gt;
desde un cuadro de dialogo, para ello, usaremos el servicio&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt;, que nos permite hacer esto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    # podemos establecer el título&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        # el primer elemento es la ruta seleccionada&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si estableces la propiedad &amp;#039;&amp;#039;&amp;#039;MultiSelectionMode&amp;#039;&amp;#039;&amp;#039; en verdadero, le&lt;br /&gt;
permitiras al usuario seleccionar más de un archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    dlg.setMultiSelectionMode(True)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        archivos = dlg.getFiles()&lt;br /&gt;
        if len(archivos) == 1:&lt;br /&gt;
            # si selecciona uno, devuelve la ruta completa&lt;br /&gt;
            desktop.loadComponentFromURL(archivos[0], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
        else:&lt;br /&gt;
            # si selecciona varios, el primer elemento es la carpeta&lt;br /&gt;
            folder = archivos[0]&lt;br /&gt;
            # los demás elementos son los archivos seleccionados&lt;br /&gt;
            for f in range(1, len(archivos)):&lt;br /&gt;
                desktop.loadComponentFromURL(folder + archivos[f], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si lo notaste, con la macro anterior el usuario puede seleccionar cualquier&lt;br /&gt;
archivo, para limitar las opciones, agrega un filtro con el método&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;appendFilter&amp;#039;&amp;#039;&amp;#039; con solo los tipos de&lt;br /&gt;
archivos que necesites, usa una línea por cada filtro, este método requiere&lt;br /&gt;
dos argumentos, el primero es el título, lo que verá el usuario y el segundo&lt;br /&gt;
es el filtro en si.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, mostramos el cuadro de dialogo Guardar Como, para permitir al usuario&lt;br /&gt;
seleccionar carpeta y nombre de archivo donde guardar su archivo, se usa el&lt;br /&gt;
mismo servicio &amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt; solo cambiando&lt;br /&gt;
algunas de sus propiedades.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_AUTOEXTENSION_PASSWORD&lt;br /&gt;
    &lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Guardar archivo&amp;#039;)&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
    # con esta opción le indicamos que use guardar como con otras opciones&lt;br /&gt;
    dlg.initialize((FILESAVE_AUTOEXTENSION_PASSWORD,))&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        msgbox(ruta)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota que el argumento del método &amp;#039;&amp;#039;&amp;#039;initialize&amp;#039;&amp;#039;&amp;#039; es una tupla.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, para terminar, te mostramos como abrir un archivo de forma oculta.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo cerraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.store()&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es &amp;#039;&amp;#039;&amp;#039;muy importante&amp;#039;&amp;#039;&amp;#039;, que cuando abras un archivo oculto siempre uses el argumento &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, a menos claro esta, que sepas lo que haces, y que, mantengas una referencia a el, para poder cerrarlo en cuanto no lo necesites.&lt;br /&gt;
&lt;br /&gt;
== Algunas tareas comunes en documentos ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exportando a PDF ===&lt;br /&gt;
&lt;br /&gt;
Para exportar a PDF solo hay que establecer el filtro correcto, nota como construimos el nombre del filtro de acuerdo al tipo de documento y como construimos la ruta de acuerdo a la ruta actual donde este guardado el documento solo reemplazando la extensión para que quede en PDF. Estamos haciendo uso de la macro &amp;#039;&amp;#039;&amp;#039;obtener_tipo&amp;#039;&amp;#039;&amp;#039; con unos ligeros cambios para este propósito.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    export_pdf()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def export_pdf():&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    tipo = obtener_tipo(doc)&lt;br /&gt;
    soportados = &amp;#039;calc,writer,draw,impress,math&amp;#039;&lt;br /&gt;
    if tipo in soportados:&lt;br /&gt;
        # establecemos el filtro como PDF&lt;br /&gt;
        opciones = PropertyValue()&lt;br /&gt;
        opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
        opciones.Value = &amp;#039;%s_pdf_Export&amp;#039; % tipo&lt;br /&gt;
        # obtenemos la ruta y reemplazados la extensión por PDF&lt;br /&gt;
        ruta, archivo = os.path.split(doc.getURL())&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
        ruta = os.path.join(ruta, nombre + &amp;#039;.pdf&amp;#039;)&lt;br /&gt;
        # guardamos&lt;br /&gt;
        doc.storeToURL(ruta, (opciones,))&lt;br /&gt;
        msgbox(u&amp;#039;Documento exportado correctamente a PDF&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;Aplicación no soportada&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;basic&amp;#039;}&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            return tipo[t]&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La forma de descomponer la ruta en sus diferentes partes, ya la vimos anteriormente, en este caso, observa como la extensión actual del documento ya no la usaremos por lo que la omitimos con un guión bajo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ocultando y mostrando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para ocultar una ventana, hay que acceder a la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # y la ocultamos&lt;br /&gt;
        ventana.setVisible(False)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Se han ocultado todas las ventanas, presiona Aceptar para mostrarlas&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # tienes que crear de nuevo la enumeración&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # ahora las mostramos&lt;br /&gt;
        ventana.setVisible(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta técnica la puedes usar también para mostrar un archivo que abriste de forma oculta previamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo mostraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    ventana.setVisible(True)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo visible, ahora lo cerramos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Activando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para usamos el método &amp;#039;&amp;#039;&amp;#039;setFocus&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # esperamos 3 segundos y mostramos la ventana&lt;br /&gt;
        time.sleep(3)&lt;br /&gt;
        ventana.setFocus()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando la barra de estado ===&lt;br /&gt;
&lt;br /&gt;
La barra de estado, generalmente en la parte inferior de las aplicaciones, es útil para dar información al usuario, generalmente de un proceso en progreso.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def barra_estado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    barra = doc.getCurrentController().getStatusIndicator()&lt;br /&gt;
    barra.start(u&amp;#039;Se procesaran líneas en tres segundos&amp;#039;, 10)&lt;br /&gt;
    # esta pausa es solo para que veas el mensaje anterior en la barra de estado&lt;br /&gt;
    time.sleep(3)&lt;br /&gt;
    for i in range(1, 11):&lt;br /&gt;
        barra.setValue(i)&lt;br /&gt;
        barra.setText(u&amp;#039;Procesando línea: %s&amp;#039; % i)&lt;br /&gt;
        # pausa de un segundo&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
    # importante para regresar el control a la aplicación&lt;br /&gt;
    barra.end()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando el zoom de la vista ===&lt;br /&gt;
La porcentaje del zoom de la vista del documento se puede modificar con la propiedad &amp;#039;&amp;#039;&amp;#039;ZoomValue&amp;#039;&amp;#039;&amp;#039; del controlador del documento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    ctl = doc.getCurrentController()&lt;br /&gt;
    # cambiamos el zoom a 120%&lt;br /&gt;
    ctl.ZoomValue = 120&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Cambiando posición y tamaño de ventana ===&lt;br /&gt;
&lt;br /&gt;
Para eso usamos el método &amp;#039;&amp;#039;&amp;#039;setPosSize&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora, es importante decirle que valores queremos aplicar con las constantes &amp;lt;idl&amp;gt;com.sun.star.aw./PosSize&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.PosSize import POSSIZE&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    # movemos la ventana a la posicion X = 0, Y = 0&lt;br /&gt;
    # establecemos el ancho (width) = 800 y el alto (height) = 600&lt;br /&gt;
    ventana.setPosSize(0, 0, 800, 600, POSSIZE)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218398</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218398"/>
		<updated>2013-04-28T19:43:46Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Controlando la barra de estado */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con Apache OpenOffice}}&lt;br /&gt;
&lt;br /&gt;
== Conceptos iniciales==&lt;br /&gt;
&lt;br /&gt;
Este es el tema más importante para crear macros, de forma sencilla, pero se ven las bases para trabajar con todo AOO, por eso es importante no avanzar en estas notas, sin antes haber comprendido a cabalidad los temas presentes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;UNO&amp;#039;&amp;#039;&amp;#039; (Universal Network Objects), es la especificación que da acceso a todos los objetos de Apache OpenOffice. Todo lo que quieras saber de esta especificación, lo puedes encontrar en la [[http://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide Guía del desarrollador]] (en ingles).&lt;br /&gt;
&lt;br /&gt;
El &amp;#039;&amp;#039;&amp;#039;API&amp;#039;&amp;#039;&amp;#039; (Application Programer Interface) de Apache OpenOffice proporciona el acceso a toda la funcionalidad de AOO, independientemente del lenguaje. Todo el API de AOO esta en &amp;lt;idl&amp;gt;com.sun.star.module-ix&amp;lt;/idl&amp;gt; (solo ingles).&lt;br /&gt;
&lt;br /&gt;
La comunicación entre objetos UNO se basa en &amp;#039;&amp;#039;&amp;#039;interfaces&amp;#039;&amp;#039;&amp;#039; de objeto.  Las interfaces pueden ser vistos desde el exterior o el interior de un objeto y proporcionan formas de ver o manipular el objeto.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;servicios&amp;#039;&amp;#039;&amp;#039; son agrupaciones lógicas de interfaces, son la forma en que un mismo objeto pueda ofrecer la funcionalidad de varias interfaces.&lt;br /&gt;
&lt;br /&gt;
Los servicios se pueden implementar en librerías compartidas llamadas &amp;#039;&amp;#039;&amp;#039;componentes UNO&amp;#039;&amp;#039;&amp;#039;, con Python podemos crear componentes nuevos y generalmente el usuario final las recibe como una extensión OXT.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;modulos&amp;#039;&amp;#039;&amp;#039; pueden agrupar submodulos, servicios, excepciones, constantes, enumeraciones, etc, se utilizan para especificar bloques coherentes en la API, esto permite tener un API bien estructurada.&lt;br /&gt;
&lt;br /&gt;
== Creando servicios ==&lt;br /&gt;
Para crear un servicio, usamos la &amp;#039;&amp;#039;&amp;#039;fabrica de servicios&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;), una interfaz especial para crear nuevos servicios, pero para llegar a ella, tenemos que hacerlo a traves de la interfaz &amp;#039;&amp;#039;&amp;#039;ComponentContext&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;), como puedes verlo en la siguiente imagen. &lt;br /&gt;
[[Image:UseServices1.png|none|thumb|400px|ComponentContext y ServiceManager]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En pyUNO tenemos dos formas de acceder a esta interfaz, las dos son equivalentes por lo que puedes usar la que prefieras. En la introducción a Python se mencionó que la mayoría de sus herramientas están disponibles en librerias, estás librerias tienen que importarse &amp;#039;&amp;#039;&amp;#039;antes&amp;#039;&amp;#039;&amp;#039; de poder usarse, en nuestro caso importaremos la librería &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; que nos da acceso (entre otras cosas) al contexto de ejecución de AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx1 = XSCRIPTCONTEXT.getComponentContext()&lt;br /&gt;
    ctx2 = uno.getComponentContext()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si te gusta investigar, busca el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; en la carpeta de instalación de AOO, ahí puedes ver de donde sale XSCRIPTCONTEXT}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, podemos acceder a la fábrica de servicios con el &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿como sabemos que este &amp;#039;&amp;#039;&amp;#039;objeto (ComponentContext)&amp;#039;&amp;#039;&amp;#039; tiene este &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;? porque lo estamos demostrando, si, también por eso, pero también porque puedes ver su documentación (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;) en el API de AOO, pero más importante aún, porque podemos hacer que el mismo objeto te diga todo lo que sabe hacer. Para ello haremos uso de una magnifica extensión que te tiene que acompañar el resto de tus días como programador de macros Python, nos referimos a [http://extensions.services.openoffice.org/project/MRI MRI]. Instala (tal vez tengas que reiniciar AOO para poder usarla) y la probamos de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    # llamamos a la extensión MRI y le pasamos el objeto a inspeccionar&lt;br /&gt;
    mri(ctx)&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def mri(target):&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()    &lt;br /&gt;
    mri = sm.createInstanceWithContext(&amp;#039;mytools.Mri&amp;#039;, ctx)&lt;br /&gt;
    mri.inspect(target)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa en la imágen siguiente, como hemos seleccionado los métodos del objeto y nos lista todos los que tenga, hemos remarcado el que por ahora nos interesa &amp;#039;&amp;#039;&amp;#039;getServiceManager()&amp;#039;&amp;#039;&amp;#039;, observa al final de la línea que efectivamente este método nos devuelve una &amp;#039;&amp;#039;&amp;#039;instancia&amp;#039;&amp;#039;&amp;#039; de la interfaz &amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;. &lt;br /&gt;
[[Image:Py_img_0006.png|none|thumb|500px|Usando la extensión MRI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gran ventaja de usar esta extensión (que por cierto esta hecha en Python), es que siempre te devolverá la información directamente del objeto, a esto se le llama &amp;#039;&amp;#039;&amp;#039;instrospección&amp;#039;&amp;#039;&amp;#039;. Acostumbrate a usarla.&lt;br /&gt;
&lt;br /&gt;
Ahora si, ya podemos crear una instancia de cualquier servicio o interfaz disponible en AOO, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existe una forma alternativa de crear este servicio, usando &amp;#039;&amp;#039;&amp;#039;XSCRIPTCONTEXT&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    XSCRIPTCONTEXT.getDesktop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si vuelves a mirar el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; notaras que usa el mismo método para instanciar este servicio}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y para que sirve este servicio? Entre otras cosas para crear nuevos documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
nuevo = desktop.loadComponentFromURL(&amp;#039;private:factory/scalc&amp;#039;, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos a detalle este método y otros relacionados con los documentos de AOO. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; es la instancia de la administración central para todas las aplicaciones AOO.  Todas las ventanas de la aplicación AOO se organizan en una jerarquía de marcos que contienen componentes visibles.  &lt;br /&gt;
&lt;br /&gt;
[[Image:DesktopOverview.png|none|thumb|400px|Desktop administra los componentes y marcos.]]&lt;br /&gt;
&lt;br /&gt;
Para los fines de crear macros es suficiente que recuerdes que, Desktop es el marco raíz de toda la jerarquía de documentos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para crear la instancia del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; usamos un contexto y usamos el método &amp;#039;&amp;#039;&amp;#039;createInstanceWithContext&amp;#039;&amp;#039;&amp;#039;. Otros servicios no requieren de contexto para ser instanciados y usados, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.util.PathSettings&amp;lt;/idl&amp;gt; que nos sirve para obtener las rutas de trabajo actuales en AOO, para estos casos usamos el método &amp;#039;&amp;#039;&amp;#039;createInstance&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    rutas = sm.createInstance(&amp;#039;com.sun.star.util.PathSettings&amp;#039;)&lt;br /&gt;
    # mostramos la ruta de trabajo del usuario&lt;br /&gt;
    print (rutas.Work)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora que ya sabemos instanciar servicios, veamos de nuevo nuestra macro para mostrar un mensaje en pantalla y analicemosla línea a línea para que veas que sencillo es, además, nos servirá para ver otros detalles al programar con Python en AOO. La macro tiene ahora unos ligeros cambios para que trabaje mejor y para explicar algunas cosas, veamos cuales.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la primer línea &amp;#039;&amp;#039;&amp;#039;declaramos&amp;#039;&amp;#039;&amp;#039; nuestra macro, su nombre y los argumentos que necesita, en este caso solo uno &amp;#039;&amp;#039;&amp;#039;message&amp;#039;&amp;#039;&amp;#039; que será el mensaje a mostrar.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la segunda línea, estamos importando (&amp;#039;&amp;#039;&amp;#039;import&amp;#039;&amp;#039;&amp;#039;) la estructura &amp;#039;&amp;#039;&amp;#039;Rectangle&amp;#039;&amp;#039;&amp;#039; desde (&amp;#039;&amp;#039;&amp;#039;from&amp;#039;&amp;#039;&amp;#039;) el modulo &amp;lt;idl&amp;gt;com.sun.star.awt.module-ix&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Las estructuras son un conjunto de valores relacionados, valores que pueden ser de tipos diferentes, pero que son mostrados como una unidad lógica, por ejemplo, la estructura &amp;lt;idl&amp;gt;com.sun.star.awt.Rectangle&amp;lt;/idl&amp;gt; hace referencia a un área rectangular estableciendo su posición y tamaño, en este caso, solo sirve para cumplir los argumentos del método para mostrar nuestro mensaje.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la tercer línea, hacemos otra importación, pero esta vez la hacemos de una constante, específicamente la constante para mostrar el botón &amp;#039;&amp;#039;&amp;#039;Aceptar&amp;#039;&amp;#039;&amp;#039; (OK), estas constantes las puedes ver aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.MessageBoxButtons&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La cuarta línea esta vacía solo para separar la parte de importacion con el resto del código. En la siguiente línea hacemos una validación del argumento pasado a nuestra macro, si el argumento &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; es una instancia de la clase &amp;#039;&amp;#039;&amp;#039;unicode&amp;#039;&amp;#039;&amp;#039; o de la clase &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, entonces la convertimos a &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, esto nos permite pasar a nuestra macro, listas, tuplas, diccionarios y practicamente cualquier objeto, del cual, podremos ver su representación en texto, muchas veces, con información bastante útil.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea ya la hemos estudiado, creamos una instancia del contexto donde se ejecuta AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea también ya la hemos estudiado, creamos una instancia de la fabrica de servicios, una de las instancias más importantes y que usaras constantemente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la siguiente línea creamos una instancia con contexto de un nuevo servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt;, este servicio sirve, entre otras muchas cosas para crear ventanas y mensaje de texto, como el de nuestra macro.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la penultima línea, usamos el método &amp;#039;&amp;#039;&amp;#039;createMessageBox&amp;#039;&amp;#039;&amp;#039; del servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt; para crear nuestro cuadro de mensaje, todos los argumentos de este método puedes verlo aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.XMessageBoxFactory&amp;lt;/idl&amp;gt;, pero aquí los explicamos uno a uno.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Aunque veas muchas líneas, el interpete la considera una sola, esto se logra al estar todos los argumentos entre paréntesis.&lt;br /&gt;
* El primer argumento es la ventana padre (&amp;#039;&amp;#039;&amp;#039;parent&amp;#039;&amp;#039;&amp;#039;) donde será mostrado el cuadro de mensaje, observa como usamos de nuevo el servicio &amp;#039;&amp;#039;&amp;#039;toolkit&amp;#039;&amp;#039;&amp;#039; para recuperar (&amp;#039;&amp;#039;&amp;#039;getDesktopWindow&amp;#039;&amp;#039;&amp;#039;) la ventana padre de AOO.&lt;br /&gt;
* El segundo argumento es el área rectangular del cuadro de mensaje, observa los dos paréntesis al final del nombre de la estructura, son necesarios para inicializarla.&lt;br /&gt;
* El tercer argumento es el tipo de mensaje, dependiendo de este argumento se muestra el icono correspondiente, los valores permitidos son: &amp;#039;&amp;#039;&amp;#039;infobox, warningbox, errorbox, querybox y messbox&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;infobox&amp;#039;&amp;#039;&amp;#039;, el siguiente argumento es ignorado.&lt;br /&gt;
* El cuarto argumento sirve para mostrar botones de comando diferentes, como: &amp;#039;&amp;#039;&amp;#039;Si, No, Cancelar&amp;#039;&amp;#039;&amp;#039;, etc, que están establecidos en las constantes vistas más arriba.&lt;br /&gt;
* El quinto argumento es el título del cuadro de mensaje.&lt;br /&gt;
* Y por ultimo, el mensaje a mostrar, el cual ya validamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la ultima línea al mismo tiempo que mostramos (&amp;#039;&amp;#039;&amp;#039;ejecute&amp;#039;&amp;#039;&amp;#039;) estamos retornando el cuadro de mensaje, esto nos da la posibilidad de capturar el botón al que le haya dado click el usuario, lo cual, veremos más adelante. Todas las macros retornan un valor, aun y cuando este sea un valor vacío (None).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, los servicio los instanciamos y las estructuras y constantes las importamos, y el punto más importante; &amp;#039;&amp;#039;&amp;#039;acostúmbrate a usar, manejar y dominar, la extensión MRI&amp;#039;&amp;#039;&amp;#039;, ella te dice todo lo necesario para trabajar con los objetos UNO de AOO, los demás, es sencillo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== El documento activo ==&lt;br /&gt;
&lt;br /&gt;
Tenemos dos formas de acceder al documento activo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc1 = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
    doc2 = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc1.getIdentifier())&lt;br /&gt;
    print (doc2.getIdentifier())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note| Mira en el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; la forma en que trabaja el método &amp;#039;&amp;#039;&amp;#039;getDocument&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si seguiste nuestra recomendación de asignar la macro de pruebas a una combinación de teclas disponible en todo AOO, prueba a abrir cada uno de los tipos de documentos que puedes ver en el menú &amp;#039;&amp;#039;&amp;#039;Archivo-&amp;gt;Nuevo-&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
[[Image:Py_img_0007.png|none|thumb|500px|Tipos de documentos en AOO]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y a ejecutar la siguiente macro, teniendo como documento activo cada uno de ellos, es decir, activas uno y ejecutas la macro, activas otro y vuelves a llamar a la macro y así sucesivamente con todos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getIdentifier())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los mensajes devueltos en cada documento, son bastante ilustrativos de que &amp;#039;&amp;#039;&amp;#039;tipo de documento&amp;#039;&amp;#039;&amp;#039; se trata. Pero si probaste con todos, habrás notado que con la base de datos nos devuelve un error, si no lo has probado hazlo ahora. Para resolver este caso tenemos varias posibilidades, la primera es controlar la excepción como ya aprendimos en la introducción a Python.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿estamos realmente seguros que ese es el error?, es mejor especificarlo y asegurarnos de que este es el error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tenemos otra alternativa donde no usamos controlador de excepciónes, si no una función que nos dice si un cierto atributo lo posee o no un objeto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    if hasattr(doc, &amp;#039;getIdentifier&amp;#039;):&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Sin atributo getIdentifier&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es mucho mejor esta segunda opción. Aun así, no podemos estar 100% seguros de que cuando no la tenga, el documento sea una base de datos, simplemente estamos excluyendo la posibilidad pero no lo estamos asegurando, probemos con otra propiedad.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getImplementationName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mucho mejor, ahora ya no tenemos errores, pero si probaste de nuevo con todos los tipos de documentos, habrás notado que con &amp;#039;&amp;#039;&amp;#039;Impres&amp;#039;&amp;#039;&amp;#039; y con &amp;#039;&amp;#039;&amp;#039;Draw&amp;#039;&amp;#039;&amp;#039; obtenemos el mismo resultado, por lo que no tenemos la certeza de que tipo de documento es, por lo que descartamos esta propiedad para nuestra finalidad que es identificar fehacientemente cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
Ya vimos que cada objeto UNO soporta diferentes servicios e interfaces, asì que cada documento de AOO (&amp;#039;&amp;#039;&amp;#039;que son objetos&amp;#039;&amp;#039;&amp;#039;) soportan diferentes servicios, algunos son iguales, es decir, comúnes a todos, pero algunos pueden ser únicos para cada documento. Ya vimos como saber si un documento soporta una propiedad, pero para saber si soporta un servicio completo, cambiamos de método, ahora usamos &amp;#039;&amp;#039;&amp;#039;supportsService&amp;#039;&amp;#039;&amp;#039; que nos devuelve falso o verdadero según soporte o no el nombre del servicio pasado como argumento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    res = doc.supportsService(&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;)&lt;br /&gt;
    mensaje = u&amp;#039;No soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    if res:&lt;br /&gt;
        mensaje = u&amp;#039;Soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    print(mensaje)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y mejor aun, podemos saber todos los servicios que soporta un objeto con el método &amp;#039;&amp;#039;&amp;#039;getSupportedServiceNames&amp;#039;&amp;#039;&amp;#039; que nos devuelve una tupla con todos sus nombres.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    servicios = doc.getSupportedServiceNames()&lt;br /&gt;
    &lt;br /&gt;
    print(servicios)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Te queda de tarea probar esta macro en cada uno de los documentos abiertos, incluso puedes probar también el IDE para AOOBasic que incorpora AOO y determinar que servicio usar para diferenciar sin duda cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
== Los documentos abiertos ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todos los documentos abiertos en la sesión de AOO, usamos el método &amp;#039;&amp;#039;&amp;#039;getComponents&amp;#039;&amp;#039;&amp;#039; del objeto &amp;#039;&amp;#039;&amp;#039;Desktop&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;MRI&amp;#039;&amp;#039;&amp;#039;, notarás que este método nos devuelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta interfaz (&amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;) tiene un solo método llamado &amp;#039;&amp;#039;&amp;#039;createEnumeration&amp;#039;&amp;#039;&amp;#039; que nos duelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumeration&amp;lt;/idl&amp;gt; la cual a su vez tiene solo dos métodos, el primero para saber si tenemos más elementos en la enumeración: &amp;#039;&amp;#039;&amp;#039;hasMoreElements&amp;#039;&amp;#039;&amp;#039; y el segundo para acceder al siguiente elemento &amp;#039;&amp;#039;&amp;#039;nextElement&amp;#039;&amp;#039;&amp;#039;, veamoslo con un ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    # mientras tengamos elementos&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        # obtenemos el siguiente elemento&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # mostrámos el tipo de documento&lt;br /&gt;
        mensaje = obtener_tipo(doc)&lt;br /&gt;
        print(mensaje)&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;Calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;Writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;Impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;Draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;Base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;Math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;Basic&amp;#039;}&lt;br /&gt;
    # iteramos entre los tipos de documentos&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        # validamos si soporta el servicio&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            # devolvemos el tipo de documento&lt;br /&gt;
            return &amp;#039;Soy %s&amp;#039; % tipo[t]&lt;br /&gt;
    # si termina sin encontrar un tipo&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como usamos una macro de apoyo para saber que tipo de documento es. Una enumeración no es más que una lista de objetos y es una forma muy común y a veces la única de acceder a ciertos objetos en AOO, es importante que la recuerdes.&lt;br /&gt;
&lt;br /&gt;
== Rutas de archivos y directorios ==&lt;br /&gt;
&lt;br /&gt;
Apache OpenOffice, al ser multiplataforma, hace uso de las rutas de archivos y directorios, en el formato URL, por ejemplo.&lt;br /&gt;
&lt;br /&gt;
file:///home/usuario/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
file:///d:/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta que este formato hace uso de los caracteres 0-9, a-z y A-Z, y cualquier otro carácter será convertido y mostrado con su respectivo código, por ejemplo, los espacios los reemplazara con &amp;#039;&amp;#039;&amp;#039;%20&amp;#039;&amp;#039;&amp;#039;. Siempre que le pases una ruta de archivo a cualquier servicio de AOO, hazlo, casi como una regla, pasarle la ruta en formato Url, para ello, la libreria &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; cuenta con dos funciones muy útiles que hacen el trabajo &amp;#039;&amp;#039;&amp;#039;systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; y &amp;#039;&amp;#039;&amp;#039;fileUrlToSystemPath&amp;#039;&amp;#039;&amp;#039;, veamos como se usan.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def rutas():&lt;br /&gt;
    &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi archivo de Calc.ods&amp;quot;&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # La convertimos al formato URL&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # Regresamos al formato local&lt;br /&gt;
    ruta = uno.fileUrlToSystemPath(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Abre varios documentos existentes y ejecuta la siguiente macro desde cada uno:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def info_ruta():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
    &lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    # obtenemos la ruta en disco&lt;br /&gt;
    ruta =  doc.getURL()&lt;br /&gt;
    # obtenemos las diferentes partes de la ruta&lt;br /&gt;
    ruta, archivo = os.path.split(ruta)&lt;br /&gt;
    nombre, extension = os.path.splitext(archivo)&lt;br /&gt;
    &lt;br /&gt;
    print (ruta)&lt;br /&gt;
    print (uno.fileUrlToSystemPath(ruta))&lt;br /&gt;
    print (archivo)&lt;br /&gt;
    print (nombre)&lt;br /&gt;
    print (extension)&lt;br /&gt;
    &lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hemos importado una nueva librería de Python, &amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; que entre otras muchas cosas, nos permite obtener información de las rutas de archivos como en la macro anterior.&lt;br /&gt;
&lt;br /&gt;
En nuestros siguientes temas, veremos la importancia de usar las rutas de archivos y directorios en formato Url y recuerda que en S.O. Linux, se tiene en cuenta la diferencia entre mayúsculas y minúsculas.&lt;br /&gt;
&lt;br /&gt;
== Creando nuevos documentos ==&lt;br /&gt;
&lt;br /&gt;
El método que nos permite crear nuevos documentos se llama &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039; y es un método del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, por ejemplo, para crear una nueva hoja de calculo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo hay que hacer un pequeño cambio para crear un nuevo documento de texto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y los demás tipos de documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/simpress&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/sdraw&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/smath&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y una base de datos?, probemos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/sbase&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos da un error ¿verdad?&lt;br /&gt;
[[Image:Py_img_0008.png|none|thumb|500px|Error al crear base de datos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No esta soportado. Para saber por que nos da un error, intenta abrir una base de datos nueva, observa como primero, si queremos trabajar con ella, el asistente nos “obliga” primero a guardarla con un nombre y después ya podemos manipularla, esto, solo pasa con las bases de datos, de los demás documentos podemos crear tantos nuevos documentos como queramos sin tener que guardar nada, entonces ¿como creamos una nueva base de datos?, la respuesta es sencilla, del mismo modo que lo hacemos desde la interfaz de usuario, es decir, tenemos que guardar primero la base de datos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
 &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi_Base_Datos.odb&amp;quot;&lt;br /&gt;
    # Creamos el servicio que nos permite manipular bases de datos&lt;br /&gt;
    dbcon = sm.createInstance(&amp;#039;com.sun.star.sdb.DatabaseContext&amp;#039;)&lt;br /&gt;
    # creamos una instancia de una nueva base de datos&lt;br /&gt;
    base = dbcon.createInstance()&lt;br /&gt;
    # establecemos el tipo de base&lt;br /&gt;
    base.URL = &amp;quot;sdbc:embedded:hsqldb&amp;quot;&lt;br /&gt;
    # y la guardamos&lt;br /&gt;
    base.DatabaseDocument.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta dos cosas muy importantes en la macro anterior, el nombre que uses, si ya existe, simplemente lo reemplazara, no te preguntara nada, así que ten cuidado de no usar una ruta o nombre de una base importante que tengas y segundo, la base de datos así creada, no quedara “registrada” en AOO, con lo que no tendrás acceso desde otros programas de la aplicación, más adelante veremos como registrar una base de datos por código.&lt;br /&gt;
&lt;br /&gt;
== Abriendo, guardando y cerrando documentos ==&lt;br /&gt;
Abrir archivos existentes es sumamente sencillo, usamos el mismo método usado&lt;br /&gt;
para crear nuevos documentos &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, pero en el parámetro ruta, le especificamos la ubicación del archivo a abrir de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def documento1():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si tus archivos existen (esto se puede validar), el código anterior los abrirá, &amp;#039;&amp;#039;&amp;#039;siempre&amp;#039;&amp;#039;&amp;#039; utiliza&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;uno.systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; cuando uses rutas de archivos o directorios en&lt;br /&gt;
funciones de AOO que las requieran como argumentos. Ya vimos que el primer&lt;br /&gt;
agumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, es la ruta del archivo a&lt;br /&gt;
abrir, el segundo argumento es una cadena con el nombre del macro (frame)&lt;br /&gt;
donde será mostrado el documento abierto, generalmente si existe este frame se&lt;br /&gt;
usa si no se crea uno nuevo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_cal&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_writer&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existen nombre especiales para este agumento, los más usuales son dos, primero&lt;br /&gt;
que ya hemos estado usando &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; que usa el frame actual y&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039; que siempre crea un nuevo frame.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La recomendación es que uses siempre &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; o &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, un&lt;br /&gt;
escenario puede ser que habrás con &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; una instancia, y después de&lt;br /&gt;
forma oculta uno nuevo con &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, más abajo vemos como abrir un&lt;br /&gt;
documento de forma oculta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si abres una plantilla, esta se comportará de forma normal, es decir, te abrirá una copia de dicha plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_plantilla.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero también podrías querer abrir la plantilla para editarla, en este caso,&lt;br /&gt;
le indicamos en las opciones de apertura esta opción, y aquí vemos como usar&lt;br /&gt;
el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como hemos importado una nueva estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como la instanciamos y asignamos sus valores.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Muy importante, el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
espera una tupla, por eso es que usamos la coma al final del nombre del&lt;br /&gt;
argumento &amp;#039;&amp;#039;&amp;#039;(opciones,)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt; esta conformada por&lt;br /&gt;
un par de valores, un nombre y un valor y es muy frecuentemente usada cuando se&lt;br /&gt;
programa en AOO, para este ejemplo solo hemos usado un par de agumentos,&lt;br /&gt;
siempre van en pares, pero muy bien puede tener más opciones como veremos más&lt;br /&gt;
adelante. En la macro anterior le estamos indicando la propiedad&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (que seria algo así como Es Plantilla), si el valor es&lt;br /&gt;
falso (False), le estamos indicando que queremos abrir la plantilla para&lt;br /&gt;
editarla, en caso contrario (True) abrirá una copia de la plantilla. Lo&lt;br /&gt;
interesante de esta propiedad es que perfectamente la puedes aplicar a archivos&lt;br /&gt;
existentes, es decir, archivos que &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; necesariamente sean plantillas, con&lt;br /&gt;
esta propiedad podemos forzarlos a comportarse como plantillas, por ejemplo, prueba el siguiente código con algún archivo existente que no sea plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como el archivo es un documento de texto normal (ODT), pero con la&lt;br /&gt;
propiedad &amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;, forzamos su apertura como una plantilla.&lt;br /&gt;
&lt;br /&gt;
Otras propiedades interesantes son &amp;#039;&amp;#039;&amp;#039;ReadOnly&amp;#039;&amp;#039;&amp;#039; (Solo Lectura) para abrir un&lt;br /&gt;
archivo como solo lectura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y &amp;#039;&amp;#039;&amp;#039;Password&amp;#039;&amp;#039;&amp;#039; (Contraseña) para abrir archivos con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto puedes combinar cualquier cantidad de opciones siempre y cuando no&lt;br /&gt;
entren en conflicto, es importante que al final, sea una tupla lo que le pasas&lt;br /&gt;
al método, si no, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # creamos una lista vacía&lt;br /&gt;
    opciones = []&lt;br /&gt;
    # creamos la primer propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opcion.Value = True&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
    # creamos la segunda propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opcion.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    # nota que la lista la convertimos en tupla&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, tuple(opciones))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si la contraseña es incorrecta, no obtendrás ningún mensaje, simplemente no&lt;br /&gt;
lo abrira y la variable &amp;#039;&amp;#039;&amp;#039;doc&amp;#039;&amp;#039;&amp;#039; será vacía, puedes validar esto:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if doc is None:&lt;br /&gt;
        print (&amp;#039;No se abrio el documento&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos otras formas de validar y depurar nuestras macros para&lt;br /&gt;
los dificiles casos en donde no obtengamos ningún mensaje de error, pero&lt;br /&gt;
simplemente nuestra macro se niega a hacer su trabajo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mientras un formato de archivo sea soportado por AOO, lo podrás abrir con el&lt;br /&gt;
método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, en el siguiente ejemplo, abrimos un archivo tipo Doc, un Html y un Xls.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_web.html&amp;#039;)&lt;br /&gt;
    doc_h = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_excel.xls&amp;#039;)&lt;br /&gt;
    doc_x = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Qué otras opciones tengo para abrir archivos?. La mayoría están descritas&lt;br /&gt;
en el servicio &amp;lt;idl&amp;gt;com.sun.star.document.MediaDescriptor&amp;lt;/idl&amp;gt;, aquí veremos&lt;br /&gt;
las más usadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cuando abres un archivo por código y este contiene macros, tu puedes&lt;br /&gt;
establecer si se abre con las macros activadas, de forma predeterminada lo abre&lt;br /&gt;
con las macros desactivadas, así que solo nos resta saber como abrirlo con las&lt;br /&gt;
macros activadas, las constanes que puedes usar puedes verlas aquí&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.document.MacroExecMode&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.document.MacroExecMode import ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;MacroExecutionMode&amp;#039;&lt;br /&gt;
    opciones.Value = ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Otra opción interesante, es la que nos permite abrir una presentación e iniciarla inmediatamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;StartPresentation&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_impress.odp&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes abrir un archivo como vista previa, útil para evitar que el usuario haga cambios en el, en este estado, los cambios que intente hacer el usuario no se guardaran.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Preview&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, la idea general de abrir un archivo es para obtener datos de el o para manipularlo, ya sea un documento nuevo o uno existente, veamos como guardar los cambios realizados y cerrar el archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    # aquí va todo el código que quieras para manipular el archivo&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto correctamente, presiona Aceptar para gaurdarlo y cerrarlo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # guardamos los cambios&lt;br /&gt;
    doc.store()&lt;br /&gt;
    # cerramos el archivo&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El código anterior funcionara con un archivo existente, pero con uno nuevo no,&lt;br /&gt;
te dará un error, por supuesto no me creas, compruébalo. Los documentos&lt;br /&gt;
tienen un método (&amp;#039;&amp;#039;&amp;#039;hasLocation&amp;#039;&amp;#039;&amp;#039;) que nos informa si un documento ya esta guardado o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
    &lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El primer mensaje debe mostrarte falso (False) porque es un documento nuevo y&lt;br /&gt;
el segundo verdadero (True) por ser un archivo abierto del disco.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También tenemos una propiedad que nos ayuda a saber si un documento ha sido modificado o no, ejecuta la siguiente macro, llamándola desde diferentes documentos, unos ábrelos y modifícalos antes de ejecutarla, otros, solo ábrelos y ejecútala para que notes la diferencia.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def esta_modificado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
 &lt;br /&gt;
    msgbox(doc.isModified())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y otra más que nos informa si el documento es de solo lectura (&amp;#039;&amp;#039;&amp;#039;isReadonly&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que valides antes de intentar guardar un archivo, si este ha sido&lt;br /&gt;
modificado o es de solo lectura. Ahora veamos como guardar un archivo nuevo con el método &amp;#039;&amp;#039;&amp;#039;storeAsUrl&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como requiere dos parámetros, la ruta del archivo y una matriz de&lt;br /&gt;
propiedades, algunas de las cuales veremos a continuación. Toma nota de que si&lt;br /&gt;
el archivo ya existe lo reemplazara sin avisarte por lo que es buena practica&lt;br /&gt;
de programación validar esto, observa como volvemos a usar la librería&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; para saber si un archivo existe ya.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    documentos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def documentos():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;&lt;br /&gt;
    if os.path.exists(ruta):&lt;br /&gt;
        msgbox(u&amp;#039;El archivo existe, no se guardará el nuevo&amp;#039;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
De la macro anterior, &amp;#039;&amp;#039;&amp;#039;es muy importante&amp;#039;&amp;#039;&amp;#039; que tomes nota que para todos&lt;br /&gt;
los métodos de Python que usen rutas de archivos o directorios, se les tienen&lt;br /&gt;
que pasar en las rutas nativas del sistema operativo donde estes trabajando,&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;solo&amp;#039;&amp;#039;&amp;#039; a los métodos de AOO, es a los que se les pasa en notación URL.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Veamos algunas propiedades interesantes para guardar archivos, por ejemplo, guardar con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo pero con contraseña&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_protegido.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como sabes, AOO, soporta la importación/exportación de múltiples formatos de archivos, veamos como guardar, por ejemplo, en formato DOC.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo en formato DOC&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;MS Word 97&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que cuando exportes, uses un formato compatible, es decir, no&lt;br /&gt;
puedes guardar una hoja de calculo como documento de texto. En el [[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices|Apéndice]]&lt;br /&gt;
mostramos una macro para obtener todos los filtros que soporta AOO.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El método storeAsURL también lo puedes usar para abrir un archivo existente y guardarlo con otro nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos con otro nombre&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc_nuevo.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para terminar esta sección, vamos a hacer un poco más interactiva la apertura&lt;br /&gt;
y guardado de archivos, permitamos que el usuario escoja la ruta y el archivo&lt;br /&gt;
desde un cuadro de dialogo, para ello, usaremos el servicio&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt;, que nos permite hacer esto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    # podemos establecer el título&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        # el primer elemento es la ruta seleccionada&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si estableces la propiedad &amp;#039;&amp;#039;&amp;#039;MultiSelectionMode&amp;#039;&amp;#039;&amp;#039; en verdadero, le&lt;br /&gt;
permitiras al usuario seleccionar más de un archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    dlg.setMultiSelectionMode(True)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        archivos = dlg.getFiles()&lt;br /&gt;
        if len(archivos) == 1:&lt;br /&gt;
            # si selecciona uno, devuelve la ruta completa&lt;br /&gt;
            desktop.loadComponentFromURL(archivos[0], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
        else:&lt;br /&gt;
            # si selecciona varios, el primer elemento es la carpeta&lt;br /&gt;
            folder = archivos[0]&lt;br /&gt;
            # los demás elementos son los archivos seleccionados&lt;br /&gt;
            for f in range(1, len(archivos)):&lt;br /&gt;
                desktop.loadComponentFromURL(folder + archivos[f], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si lo notaste, con la macro anterior el usuario puede seleccionar cualquier&lt;br /&gt;
archivo, para limitar las opciones, agrega un filtro con el método&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;appendFilter&amp;#039;&amp;#039;&amp;#039; con solo los tipos de&lt;br /&gt;
archivos que necesites, usa una línea por cada filtro, este método requiere&lt;br /&gt;
dos argumentos, el primero es el título, lo que verá el usuario y el segundo&lt;br /&gt;
es el filtro en si.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, mostramos el cuadro de dialogo Guardar Como, para permitir al usuario&lt;br /&gt;
seleccionar carpeta y nombre de archivo donde guardar su archivo, se usa el&lt;br /&gt;
mismo servicio &amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt; solo cambiando&lt;br /&gt;
algunas de sus propiedades.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_AUTOEXTENSION_PASSWORD&lt;br /&gt;
    &lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Guardar archivo&amp;#039;)&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
    # con esta opción le indicamos que use guardar como con otras opciones&lt;br /&gt;
    dlg.initialize((FILESAVE_AUTOEXTENSION_PASSWORD,))&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        msgbox(ruta)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota que el argumento del método &amp;#039;&amp;#039;&amp;#039;initialize&amp;#039;&amp;#039;&amp;#039; es una tupla.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, para terminar, te mostramos como abrir un archivo de forma oculta.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo cerraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.store()&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es &amp;#039;&amp;#039;&amp;#039;muy importante&amp;#039;&amp;#039;&amp;#039;, que cuando abras un archivo oculto siempre uses el argumento &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, a menos claro esta, que sepas lo que haces, y que, mantengas una referencia a el, para poder cerrarlo en cuanto no lo necesites.&lt;br /&gt;
&lt;br /&gt;
== Algunas tareas comunes en documentos ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exportando a PDF ===&lt;br /&gt;
&lt;br /&gt;
Para exportar a PDF solo hay que establecer el filtro correcto, nota como construimos el nombre del filtro de acuerdo al tipo de documento y como construimos la ruta de acuerdo a la ruta actual donde este guardado el documento solo reemplazando la extensión para que quede en PDF. Estamos haciendo uso de la macro &amp;#039;&amp;#039;&amp;#039;obtener_tipo&amp;#039;&amp;#039;&amp;#039; con unos ligeros cambios para este propósito.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    export_pdf()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def export_pdf():&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    tipo = obtener_tipo(doc)&lt;br /&gt;
    soportados = &amp;#039;calc,writer,draw,impress,math&amp;#039;&lt;br /&gt;
    if tipo in soportados:&lt;br /&gt;
        # establecemos el filtro como PDF&lt;br /&gt;
        opciones = PropertyValue()&lt;br /&gt;
        opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
        opciones.Value = &amp;#039;%s_pdf_Export&amp;#039; % tipo&lt;br /&gt;
        # obtenemos la ruta y reemplazados la extensión por PDF&lt;br /&gt;
        ruta, archivo = os.path.split(doc.getURL())&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
        ruta = os.path.join(ruta, nombre + &amp;#039;.pdf&amp;#039;)&lt;br /&gt;
        # guardamos&lt;br /&gt;
        doc.storeToURL(ruta, (opciones,))&lt;br /&gt;
        msgbox(u&amp;#039;Documento exportado correctamente a PDF&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;Aplicación no soportada&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;basic&amp;#039;}&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            return tipo[t]&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La forma de descomponer la ruta en sus diferentes partes, ya la vimos anteriormente, en este caso, observa como la extensión actual del documento ya no la usaremos por lo que la omitimos con un guión bajo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ocultando y mostrando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para ocultar una ventana, hay que acceder a la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # y la ocultamos&lt;br /&gt;
        ventana.setVisible(False)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Se han ocultado todas las ventanas, presiona Aceptar para mostrarlas&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # tienes que crear de nuevo la enumeración&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # ahora las mostramos&lt;br /&gt;
        ventana.setVisible(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta técnica la puedes usar también para mostrar un archivo que abriste de forma oculta previamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo mostraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    ventana.setVisible(True)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo visible, ahora lo cerramos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Activando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para usamos el método &amp;#039;&amp;#039;&amp;#039;setFocus&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # esperamos 3 segundos y mostramos la ventana&lt;br /&gt;
        time.sleep(3)&lt;br /&gt;
        ventana.setFocus()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando la barra de estado ===&lt;br /&gt;
&lt;br /&gt;
La barra de estado, generalmente en la parte inferior de las aplicaciones, es útil para dar información al usuario, generalmente de un proceso en progreso.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def barra_estado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    barra = doc.getCurrentController().getStatusIndicator()&lt;br /&gt;
    barra.start(u&amp;#039;Se procesaran líneas en tres segundos&amp;#039;, 10)&lt;br /&gt;
    # esta pausa es solo para que veas el mensaje anterior en la barra de estado&lt;br /&gt;
    time.sleep(3)&lt;br /&gt;
    for i in range(1, 11):&lt;br /&gt;
        barra.setValue(i)&lt;br /&gt;
        barra.setText(u&amp;#039;Procesando línea: %s&amp;#039; % i)&lt;br /&gt;
        # pausa de un segundo&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
    # importante para regresar el control a la aplicación&lt;br /&gt;
    barra.end()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando el zoom de la vista ===&lt;br /&gt;
La porcentaje del zoom de la vista del documento se puede modificar con la propiedad &amp;#039;&amp;#039;&amp;#039;ZoomValue&amp;#039;&amp;#039;&amp;#039; del controlador del documento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    ctl = doc.getCurrentController()&lt;br /&gt;
    # cambiamos el zoom a 120%&lt;br /&gt;
    ctl.ZoomValue = 120&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218397</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218397"/>
		<updated>2013-04-28T19:34:48Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Algunas tareas comunes en documentos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con Apache OpenOffice}}&lt;br /&gt;
&lt;br /&gt;
== Conceptos iniciales==&lt;br /&gt;
&lt;br /&gt;
Este es el tema más importante para crear macros, de forma sencilla, pero se ven las bases para trabajar con todo AOO, por eso es importante no avanzar en estas notas, sin antes haber comprendido a cabalidad los temas presentes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;UNO&amp;#039;&amp;#039;&amp;#039; (Universal Network Objects), es la especificación que da acceso a todos los objetos de Apache OpenOffice. Todo lo que quieras saber de esta especificación, lo puedes encontrar en la [[http://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide Guía del desarrollador]] (en ingles).&lt;br /&gt;
&lt;br /&gt;
El &amp;#039;&amp;#039;&amp;#039;API&amp;#039;&amp;#039;&amp;#039; (Application Programer Interface) de Apache OpenOffice proporciona el acceso a toda la funcionalidad de AOO, independientemente del lenguaje. Todo el API de AOO esta en &amp;lt;idl&amp;gt;com.sun.star.module-ix&amp;lt;/idl&amp;gt; (solo ingles).&lt;br /&gt;
&lt;br /&gt;
La comunicación entre objetos UNO se basa en &amp;#039;&amp;#039;&amp;#039;interfaces&amp;#039;&amp;#039;&amp;#039; de objeto.  Las interfaces pueden ser vistos desde el exterior o el interior de un objeto y proporcionan formas de ver o manipular el objeto.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;servicios&amp;#039;&amp;#039;&amp;#039; son agrupaciones lógicas de interfaces, son la forma en que un mismo objeto pueda ofrecer la funcionalidad de varias interfaces.&lt;br /&gt;
&lt;br /&gt;
Los servicios se pueden implementar en librerías compartidas llamadas &amp;#039;&amp;#039;&amp;#039;componentes UNO&amp;#039;&amp;#039;&amp;#039;, con Python podemos crear componentes nuevos y generalmente el usuario final las recibe como una extensión OXT.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;modulos&amp;#039;&amp;#039;&amp;#039; pueden agrupar submodulos, servicios, excepciones, constantes, enumeraciones, etc, se utilizan para especificar bloques coherentes en la API, esto permite tener un API bien estructurada.&lt;br /&gt;
&lt;br /&gt;
== Creando servicios ==&lt;br /&gt;
Para crear un servicio, usamos la &amp;#039;&amp;#039;&amp;#039;fabrica de servicios&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;), una interfaz especial para crear nuevos servicios, pero para llegar a ella, tenemos que hacerlo a traves de la interfaz &amp;#039;&amp;#039;&amp;#039;ComponentContext&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;), como puedes verlo en la siguiente imagen. &lt;br /&gt;
[[Image:UseServices1.png|none|thumb|400px|ComponentContext y ServiceManager]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En pyUNO tenemos dos formas de acceder a esta interfaz, las dos son equivalentes por lo que puedes usar la que prefieras. En la introducción a Python se mencionó que la mayoría de sus herramientas están disponibles en librerias, estás librerias tienen que importarse &amp;#039;&amp;#039;&amp;#039;antes&amp;#039;&amp;#039;&amp;#039; de poder usarse, en nuestro caso importaremos la librería &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; que nos da acceso (entre otras cosas) al contexto de ejecución de AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx1 = XSCRIPTCONTEXT.getComponentContext()&lt;br /&gt;
    ctx2 = uno.getComponentContext()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si te gusta investigar, busca el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; en la carpeta de instalación de AOO, ahí puedes ver de donde sale XSCRIPTCONTEXT}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, podemos acceder a la fábrica de servicios con el &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿como sabemos que este &amp;#039;&amp;#039;&amp;#039;objeto (ComponentContext)&amp;#039;&amp;#039;&amp;#039; tiene este &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;? porque lo estamos demostrando, si, también por eso, pero también porque puedes ver su documentación (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;) en el API de AOO, pero más importante aún, porque podemos hacer que el mismo objeto te diga todo lo que sabe hacer. Para ello haremos uso de una magnifica extensión que te tiene que acompañar el resto de tus días como programador de macros Python, nos referimos a [http://extensions.services.openoffice.org/project/MRI MRI]. Instala (tal vez tengas que reiniciar AOO para poder usarla) y la probamos de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    # llamamos a la extensión MRI y le pasamos el objeto a inspeccionar&lt;br /&gt;
    mri(ctx)&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def mri(target):&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()    &lt;br /&gt;
    mri = sm.createInstanceWithContext(&amp;#039;mytools.Mri&amp;#039;, ctx)&lt;br /&gt;
    mri.inspect(target)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa en la imágen siguiente, como hemos seleccionado los métodos del objeto y nos lista todos los que tenga, hemos remarcado el que por ahora nos interesa &amp;#039;&amp;#039;&amp;#039;getServiceManager()&amp;#039;&amp;#039;&amp;#039;, observa al final de la línea que efectivamente este método nos devuelve una &amp;#039;&amp;#039;&amp;#039;instancia&amp;#039;&amp;#039;&amp;#039; de la interfaz &amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;. &lt;br /&gt;
[[Image:Py_img_0006.png|none|thumb|500px|Usando la extensión MRI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gran ventaja de usar esta extensión (que por cierto esta hecha en Python), es que siempre te devolverá la información directamente del objeto, a esto se le llama &amp;#039;&amp;#039;&amp;#039;instrospección&amp;#039;&amp;#039;&amp;#039;. Acostumbrate a usarla.&lt;br /&gt;
&lt;br /&gt;
Ahora si, ya podemos crear una instancia de cualquier servicio o interfaz disponible en AOO, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existe una forma alternativa de crear este servicio, usando &amp;#039;&amp;#039;&amp;#039;XSCRIPTCONTEXT&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    XSCRIPTCONTEXT.getDesktop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si vuelves a mirar el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; notaras que usa el mismo método para instanciar este servicio}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y para que sirve este servicio? Entre otras cosas para crear nuevos documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
nuevo = desktop.loadComponentFromURL(&amp;#039;private:factory/scalc&amp;#039;, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos a detalle este método y otros relacionados con los documentos de AOO. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; es la instancia de la administración central para todas las aplicaciones AOO.  Todas las ventanas de la aplicación AOO se organizan en una jerarquía de marcos que contienen componentes visibles.  &lt;br /&gt;
&lt;br /&gt;
[[Image:DesktopOverview.png|none|thumb|400px|Desktop administra los componentes y marcos.]]&lt;br /&gt;
&lt;br /&gt;
Para los fines de crear macros es suficiente que recuerdes que, Desktop es el marco raíz de toda la jerarquía de documentos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para crear la instancia del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; usamos un contexto y usamos el método &amp;#039;&amp;#039;&amp;#039;createInstanceWithContext&amp;#039;&amp;#039;&amp;#039;. Otros servicios no requieren de contexto para ser instanciados y usados, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.util.PathSettings&amp;lt;/idl&amp;gt; que nos sirve para obtener las rutas de trabajo actuales en AOO, para estos casos usamos el método &amp;#039;&amp;#039;&amp;#039;createInstance&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    rutas = sm.createInstance(&amp;#039;com.sun.star.util.PathSettings&amp;#039;)&lt;br /&gt;
    # mostramos la ruta de trabajo del usuario&lt;br /&gt;
    print (rutas.Work)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora que ya sabemos instanciar servicios, veamos de nuevo nuestra macro para mostrar un mensaje en pantalla y analicemosla línea a línea para que veas que sencillo es, además, nos servirá para ver otros detalles al programar con Python en AOO. La macro tiene ahora unos ligeros cambios para que trabaje mejor y para explicar algunas cosas, veamos cuales.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la primer línea &amp;#039;&amp;#039;&amp;#039;declaramos&amp;#039;&amp;#039;&amp;#039; nuestra macro, su nombre y los argumentos que necesita, en este caso solo uno &amp;#039;&amp;#039;&amp;#039;message&amp;#039;&amp;#039;&amp;#039; que será el mensaje a mostrar.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la segunda línea, estamos importando (&amp;#039;&amp;#039;&amp;#039;import&amp;#039;&amp;#039;&amp;#039;) la estructura &amp;#039;&amp;#039;&amp;#039;Rectangle&amp;#039;&amp;#039;&amp;#039; desde (&amp;#039;&amp;#039;&amp;#039;from&amp;#039;&amp;#039;&amp;#039;) el modulo &amp;lt;idl&amp;gt;com.sun.star.awt.module-ix&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Las estructuras son un conjunto de valores relacionados, valores que pueden ser de tipos diferentes, pero que son mostrados como una unidad lógica, por ejemplo, la estructura &amp;lt;idl&amp;gt;com.sun.star.awt.Rectangle&amp;lt;/idl&amp;gt; hace referencia a un área rectangular estableciendo su posición y tamaño, en este caso, solo sirve para cumplir los argumentos del método para mostrar nuestro mensaje.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la tercer línea, hacemos otra importación, pero esta vez la hacemos de una constante, específicamente la constante para mostrar el botón &amp;#039;&amp;#039;&amp;#039;Aceptar&amp;#039;&amp;#039;&amp;#039; (OK), estas constantes las puedes ver aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.MessageBoxButtons&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La cuarta línea esta vacía solo para separar la parte de importacion con el resto del código. En la siguiente línea hacemos una validación del argumento pasado a nuestra macro, si el argumento &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; es una instancia de la clase &amp;#039;&amp;#039;&amp;#039;unicode&amp;#039;&amp;#039;&amp;#039; o de la clase &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, entonces la convertimos a &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, esto nos permite pasar a nuestra macro, listas, tuplas, diccionarios y practicamente cualquier objeto, del cual, podremos ver su representación en texto, muchas veces, con información bastante útil.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea ya la hemos estudiado, creamos una instancia del contexto donde se ejecuta AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea también ya la hemos estudiado, creamos una instancia de la fabrica de servicios, una de las instancias más importantes y que usaras constantemente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la siguiente línea creamos una instancia con contexto de un nuevo servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt;, este servicio sirve, entre otras muchas cosas para crear ventanas y mensaje de texto, como el de nuestra macro.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la penultima línea, usamos el método &amp;#039;&amp;#039;&amp;#039;createMessageBox&amp;#039;&amp;#039;&amp;#039; del servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt; para crear nuestro cuadro de mensaje, todos los argumentos de este método puedes verlo aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.XMessageBoxFactory&amp;lt;/idl&amp;gt;, pero aquí los explicamos uno a uno.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Aunque veas muchas líneas, el interpete la considera una sola, esto se logra al estar todos los argumentos entre paréntesis.&lt;br /&gt;
* El primer argumento es la ventana padre (&amp;#039;&amp;#039;&amp;#039;parent&amp;#039;&amp;#039;&amp;#039;) donde será mostrado el cuadro de mensaje, observa como usamos de nuevo el servicio &amp;#039;&amp;#039;&amp;#039;toolkit&amp;#039;&amp;#039;&amp;#039; para recuperar (&amp;#039;&amp;#039;&amp;#039;getDesktopWindow&amp;#039;&amp;#039;&amp;#039;) la ventana padre de AOO.&lt;br /&gt;
* El segundo argumento es el área rectangular del cuadro de mensaje, observa los dos paréntesis al final del nombre de la estructura, son necesarios para inicializarla.&lt;br /&gt;
* El tercer argumento es el tipo de mensaje, dependiendo de este argumento se muestra el icono correspondiente, los valores permitidos son: &amp;#039;&amp;#039;&amp;#039;infobox, warningbox, errorbox, querybox y messbox&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;infobox&amp;#039;&amp;#039;&amp;#039;, el siguiente argumento es ignorado.&lt;br /&gt;
* El cuarto argumento sirve para mostrar botones de comando diferentes, como: &amp;#039;&amp;#039;&amp;#039;Si, No, Cancelar&amp;#039;&amp;#039;&amp;#039;, etc, que están establecidos en las constantes vistas más arriba.&lt;br /&gt;
* El quinto argumento es el título del cuadro de mensaje.&lt;br /&gt;
* Y por ultimo, el mensaje a mostrar, el cual ya validamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la ultima línea al mismo tiempo que mostramos (&amp;#039;&amp;#039;&amp;#039;ejecute&amp;#039;&amp;#039;&amp;#039;) estamos retornando el cuadro de mensaje, esto nos da la posibilidad de capturar el botón al que le haya dado click el usuario, lo cual, veremos más adelante. Todas las macros retornan un valor, aun y cuando este sea un valor vacío (None).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, los servicio los instanciamos y las estructuras y constantes las importamos, y el punto más importante; &amp;#039;&amp;#039;&amp;#039;acostúmbrate a usar, manejar y dominar, la extensión MRI&amp;#039;&amp;#039;&amp;#039;, ella te dice todo lo necesario para trabajar con los objetos UNO de AOO, los demás, es sencillo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== El documento activo ==&lt;br /&gt;
&lt;br /&gt;
Tenemos dos formas de acceder al documento activo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc1 = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
    doc2 = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc1.getIdentifier())&lt;br /&gt;
    print (doc2.getIdentifier())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note| Mira en el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; la forma en que trabaja el método &amp;#039;&amp;#039;&amp;#039;getDocument&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si seguiste nuestra recomendación de asignar la macro de pruebas a una combinación de teclas disponible en todo AOO, prueba a abrir cada uno de los tipos de documentos que puedes ver en el menú &amp;#039;&amp;#039;&amp;#039;Archivo-&amp;gt;Nuevo-&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
[[Image:Py_img_0007.png|none|thumb|500px|Tipos de documentos en AOO]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y a ejecutar la siguiente macro, teniendo como documento activo cada uno de ellos, es decir, activas uno y ejecutas la macro, activas otro y vuelves a llamar a la macro y así sucesivamente con todos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getIdentifier())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los mensajes devueltos en cada documento, son bastante ilustrativos de que &amp;#039;&amp;#039;&amp;#039;tipo de documento&amp;#039;&amp;#039;&amp;#039; se trata. Pero si probaste con todos, habrás notado que con la base de datos nos devuelve un error, si no lo has probado hazlo ahora. Para resolver este caso tenemos varias posibilidades, la primera es controlar la excepción como ya aprendimos en la introducción a Python.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿estamos realmente seguros que ese es el error?, es mejor especificarlo y asegurarnos de que este es el error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tenemos otra alternativa donde no usamos controlador de excepciónes, si no una función que nos dice si un cierto atributo lo posee o no un objeto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    if hasattr(doc, &amp;#039;getIdentifier&amp;#039;):&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Sin atributo getIdentifier&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es mucho mejor esta segunda opción. Aun así, no podemos estar 100% seguros de que cuando no la tenga, el documento sea una base de datos, simplemente estamos excluyendo la posibilidad pero no lo estamos asegurando, probemos con otra propiedad.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getImplementationName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mucho mejor, ahora ya no tenemos errores, pero si probaste de nuevo con todos los tipos de documentos, habrás notado que con &amp;#039;&amp;#039;&amp;#039;Impres&amp;#039;&amp;#039;&amp;#039; y con &amp;#039;&amp;#039;&amp;#039;Draw&amp;#039;&amp;#039;&amp;#039; obtenemos el mismo resultado, por lo que no tenemos la certeza de que tipo de documento es, por lo que descartamos esta propiedad para nuestra finalidad que es identificar fehacientemente cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
Ya vimos que cada objeto UNO soporta diferentes servicios e interfaces, asì que cada documento de AOO (&amp;#039;&amp;#039;&amp;#039;que son objetos&amp;#039;&amp;#039;&amp;#039;) soportan diferentes servicios, algunos son iguales, es decir, comúnes a todos, pero algunos pueden ser únicos para cada documento. Ya vimos como saber si un documento soporta una propiedad, pero para saber si soporta un servicio completo, cambiamos de método, ahora usamos &amp;#039;&amp;#039;&amp;#039;supportsService&amp;#039;&amp;#039;&amp;#039; que nos devuelve falso o verdadero según soporte o no el nombre del servicio pasado como argumento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    res = doc.supportsService(&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;)&lt;br /&gt;
    mensaje = u&amp;#039;No soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    if res:&lt;br /&gt;
        mensaje = u&amp;#039;Soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    print(mensaje)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y mejor aun, podemos saber todos los servicios que soporta un objeto con el método &amp;#039;&amp;#039;&amp;#039;getSupportedServiceNames&amp;#039;&amp;#039;&amp;#039; que nos devuelve una tupla con todos sus nombres.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    servicios = doc.getSupportedServiceNames()&lt;br /&gt;
    &lt;br /&gt;
    print(servicios)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Te queda de tarea probar esta macro en cada uno de los documentos abiertos, incluso puedes probar también el IDE para AOOBasic que incorpora AOO y determinar que servicio usar para diferenciar sin duda cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
== Los documentos abiertos ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todos los documentos abiertos en la sesión de AOO, usamos el método &amp;#039;&amp;#039;&amp;#039;getComponents&amp;#039;&amp;#039;&amp;#039; del objeto &amp;#039;&amp;#039;&amp;#039;Desktop&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;MRI&amp;#039;&amp;#039;&amp;#039;, notarás que este método nos devuelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta interfaz (&amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;) tiene un solo método llamado &amp;#039;&amp;#039;&amp;#039;createEnumeration&amp;#039;&amp;#039;&amp;#039; que nos duelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumeration&amp;lt;/idl&amp;gt; la cual a su vez tiene solo dos métodos, el primero para saber si tenemos más elementos en la enumeración: &amp;#039;&amp;#039;&amp;#039;hasMoreElements&amp;#039;&amp;#039;&amp;#039; y el segundo para acceder al siguiente elemento &amp;#039;&amp;#039;&amp;#039;nextElement&amp;#039;&amp;#039;&amp;#039;, veamoslo con un ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    # mientras tengamos elementos&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        # obtenemos el siguiente elemento&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # mostrámos el tipo de documento&lt;br /&gt;
        mensaje = obtener_tipo(doc)&lt;br /&gt;
        print(mensaje)&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;Calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;Writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;Impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;Draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;Base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;Math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;Basic&amp;#039;}&lt;br /&gt;
    # iteramos entre los tipos de documentos&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        # validamos si soporta el servicio&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            # devolvemos el tipo de documento&lt;br /&gt;
            return &amp;#039;Soy %s&amp;#039; % tipo[t]&lt;br /&gt;
    # si termina sin encontrar un tipo&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como usamos una macro de apoyo para saber que tipo de documento es. Una enumeración no es más que una lista de objetos y es una forma muy común y a veces la única de acceder a ciertos objetos en AOO, es importante que la recuerdes.&lt;br /&gt;
&lt;br /&gt;
== Rutas de archivos y directorios ==&lt;br /&gt;
&lt;br /&gt;
Apache OpenOffice, al ser multiplataforma, hace uso de las rutas de archivos y directorios, en el formato URL, por ejemplo.&lt;br /&gt;
&lt;br /&gt;
file:///home/usuario/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
file:///d:/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta que este formato hace uso de los caracteres 0-9, a-z y A-Z, y cualquier otro carácter será convertido y mostrado con su respectivo código, por ejemplo, los espacios los reemplazara con &amp;#039;&amp;#039;&amp;#039;%20&amp;#039;&amp;#039;&amp;#039;. Siempre que le pases una ruta de archivo a cualquier servicio de AOO, hazlo, casi como una regla, pasarle la ruta en formato Url, para ello, la libreria &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; cuenta con dos funciones muy útiles que hacen el trabajo &amp;#039;&amp;#039;&amp;#039;systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; y &amp;#039;&amp;#039;&amp;#039;fileUrlToSystemPath&amp;#039;&amp;#039;&amp;#039;, veamos como se usan.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def rutas():&lt;br /&gt;
    &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi archivo de Calc.ods&amp;quot;&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # La convertimos al formato URL&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # Regresamos al formato local&lt;br /&gt;
    ruta = uno.fileUrlToSystemPath(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Abre varios documentos existentes y ejecuta la siguiente macro desde cada uno:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def info_ruta():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
    &lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    # obtenemos la ruta en disco&lt;br /&gt;
    ruta =  doc.getURL()&lt;br /&gt;
    # obtenemos las diferentes partes de la ruta&lt;br /&gt;
    ruta, archivo = os.path.split(ruta)&lt;br /&gt;
    nombre, extension = os.path.splitext(archivo)&lt;br /&gt;
    &lt;br /&gt;
    print (ruta)&lt;br /&gt;
    print (uno.fileUrlToSystemPath(ruta))&lt;br /&gt;
    print (archivo)&lt;br /&gt;
    print (nombre)&lt;br /&gt;
    print (extension)&lt;br /&gt;
    &lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hemos importado una nueva librería de Python, &amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; que entre otras muchas cosas, nos permite obtener información de las rutas de archivos como en la macro anterior.&lt;br /&gt;
&lt;br /&gt;
En nuestros siguientes temas, veremos la importancia de usar las rutas de archivos y directorios en formato Url y recuerda que en S.O. Linux, se tiene en cuenta la diferencia entre mayúsculas y minúsculas.&lt;br /&gt;
&lt;br /&gt;
== Creando nuevos documentos ==&lt;br /&gt;
&lt;br /&gt;
El método que nos permite crear nuevos documentos se llama &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039; y es un método del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, por ejemplo, para crear una nueva hoja de calculo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo hay que hacer un pequeño cambio para crear un nuevo documento de texto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y los demás tipos de documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/simpress&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/sdraw&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/smath&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y una base de datos?, probemos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/sbase&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos da un error ¿verdad?&lt;br /&gt;
[[Image:Py_img_0008.png|none|thumb|500px|Error al crear base de datos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No esta soportado. Para saber por que nos da un error, intenta abrir una base de datos nueva, observa como primero, si queremos trabajar con ella, el asistente nos “obliga” primero a guardarla con un nombre y después ya podemos manipularla, esto, solo pasa con las bases de datos, de los demás documentos podemos crear tantos nuevos documentos como queramos sin tener que guardar nada, entonces ¿como creamos una nueva base de datos?, la respuesta es sencilla, del mismo modo que lo hacemos desde la interfaz de usuario, es decir, tenemos que guardar primero la base de datos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
 &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi_Base_Datos.odb&amp;quot;&lt;br /&gt;
    # Creamos el servicio que nos permite manipular bases de datos&lt;br /&gt;
    dbcon = sm.createInstance(&amp;#039;com.sun.star.sdb.DatabaseContext&amp;#039;)&lt;br /&gt;
    # creamos una instancia de una nueva base de datos&lt;br /&gt;
    base = dbcon.createInstance()&lt;br /&gt;
    # establecemos el tipo de base&lt;br /&gt;
    base.URL = &amp;quot;sdbc:embedded:hsqldb&amp;quot;&lt;br /&gt;
    # y la guardamos&lt;br /&gt;
    base.DatabaseDocument.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta dos cosas muy importantes en la macro anterior, el nombre que uses, si ya existe, simplemente lo reemplazara, no te preguntara nada, así que ten cuidado de no usar una ruta o nombre de una base importante que tengas y segundo, la base de datos así creada, no quedara “registrada” en AOO, con lo que no tendrás acceso desde otros programas de la aplicación, más adelante veremos como registrar una base de datos por código.&lt;br /&gt;
&lt;br /&gt;
== Abriendo, guardando y cerrando documentos ==&lt;br /&gt;
Abrir archivos existentes es sumamente sencillo, usamos el mismo método usado&lt;br /&gt;
para crear nuevos documentos &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, pero en el parámetro ruta, le especificamos la ubicación del archivo a abrir de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def documento1():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si tus archivos existen (esto se puede validar), el código anterior los abrirá, &amp;#039;&amp;#039;&amp;#039;siempre&amp;#039;&amp;#039;&amp;#039; utiliza&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;uno.systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; cuando uses rutas de archivos o directorios en&lt;br /&gt;
funciones de AOO que las requieran como argumentos. Ya vimos que el primer&lt;br /&gt;
agumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, es la ruta del archivo a&lt;br /&gt;
abrir, el segundo argumento es una cadena con el nombre del macro (frame)&lt;br /&gt;
donde será mostrado el documento abierto, generalmente si existe este frame se&lt;br /&gt;
usa si no se crea uno nuevo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_cal&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_writer&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existen nombre especiales para este agumento, los más usuales son dos, primero&lt;br /&gt;
que ya hemos estado usando &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; que usa el frame actual y&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039; que siempre crea un nuevo frame.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La recomendación es que uses siempre &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; o &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, un&lt;br /&gt;
escenario puede ser que habrás con &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; una instancia, y después de&lt;br /&gt;
forma oculta uno nuevo con &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, más abajo vemos como abrir un&lt;br /&gt;
documento de forma oculta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si abres una plantilla, esta se comportará de forma normal, es decir, te abrirá una copia de dicha plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_plantilla.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero también podrías querer abrir la plantilla para editarla, en este caso,&lt;br /&gt;
le indicamos en las opciones de apertura esta opción, y aquí vemos como usar&lt;br /&gt;
el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como hemos importado una nueva estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como la instanciamos y asignamos sus valores.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Muy importante, el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
espera una tupla, por eso es que usamos la coma al final del nombre del&lt;br /&gt;
argumento &amp;#039;&amp;#039;&amp;#039;(opciones,)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt; esta conformada por&lt;br /&gt;
un par de valores, un nombre y un valor y es muy frecuentemente usada cuando se&lt;br /&gt;
programa en AOO, para este ejemplo solo hemos usado un par de agumentos,&lt;br /&gt;
siempre van en pares, pero muy bien puede tener más opciones como veremos más&lt;br /&gt;
adelante. En la macro anterior le estamos indicando la propiedad&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (que seria algo así como Es Plantilla), si el valor es&lt;br /&gt;
falso (False), le estamos indicando que queremos abrir la plantilla para&lt;br /&gt;
editarla, en caso contrario (True) abrirá una copia de la plantilla. Lo&lt;br /&gt;
interesante de esta propiedad es que perfectamente la puedes aplicar a archivos&lt;br /&gt;
existentes, es decir, archivos que &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; necesariamente sean plantillas, con&lt;br /&gt;
esta propiedad podemos forzarlos a comportarse como plantillas, por ejemplo, prueba el siguiente código con algún archivo existente que no sea plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como el archivo es un documento de texto normal (ODT), pero con la&lt;br /&gt;
propiedad &amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;, forzamos su apertura como una plantilla.&lt;br /&gt;
&lt;br /&gt;
Otras propiedades interesantes son &amp;#039;&amp;#039;&amp;#039;ReadOnly&amp;#039;&amp;#039;&amp;#039; (Solo Lectura) para abrir un&lt;br /&gt;
archivo como solo lectura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y &amp;#039;&amp;#039;&amp;#039;Password&amp;#039;&amp;#039;&amp;#039; (Contraseña) para abrir archivos con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto puedes combinar cualquier cantidad de opciones siempre y cuando no&lt;br /&gt;
entren en conflicto, es importante que al final, sea una tupla lo que le pasas&lt;br /&gt;
al método, si no, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # creamos una lista vacía&lt;br /&gt;
    opciones = []&lt;br /&gt;
    # creamos la primer propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opcion.Value = True&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
    # creamos la segunda propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opcion.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    # nota que la lista la convertimos en tupla&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, tuple(opciones))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si la contraseña es incorrecta, no obtendrás ningún mensaje, simplemente no&lt;br /&gt;
lo abrira y la variable &amp;#039;&amp;#039;&amp;#039;doc&amp;#039;&amp;#039;&amp;#039; será vacía, puedes validar esto:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if doc is None:&lt;br /&gt;
        print (&amp;#039;No se abrio el documento&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos otras formas de validar y depurar nuestras macros para&lt;br /&gt;
los dificiles casos en donde no obtengamos ningún mensaje de error, pero&lt;br /&gt;
simplemente nuestra macro se niega a hacer su trabajo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mientras un formato de archivo sea soportado por AOO, lo podrás abrir con el&lt;br /&gt;
método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, en el siguiente ejemplo, abrimos un archivo tipo Doc, un Html y un Xls.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_web.html&amp;#039;)&lt;br /&gt;
    doc_h = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_excel.xls&amp;#039;)&lt;br /&gt;
    doc_x = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Qué otras opciones tengo para abrir archivos?. La mayoría están descritas&lt;br /&gt;
en el servicio &amp;lt;idl&amp;gt;com.sun.star.document.MediaDescriptor&amp;lt;/idl&amp;gt;, aquí veremos&lt;br /&gt;
las más usadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cuando abres un archivo por código y este contiene macros, tu puedes&lt;br /&gt;
establecer si se abre con las macros activadas, de forma predeterminada lo abre&lt;br /&gt;
con las macros desactivadas, así que solo nos resta saber como abrirlo con las&lt;br /&gt;
macros activadas, las constanes que puedes usar puedes verlas aquí&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.document.MacroExecMode&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.document.MacroExecMode import ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;MacroExecutionMode&amp;#039;&lt;br /&gt;
    opciones.Value = ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Otra opción interesante, es la que nos permite abrir una presentación e iniciarla inmediatamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;StartPresentation&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_impress.odp&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes abrir un archivo como vista previa, útil para evitar que el usuario haga cambios en el, en este estado, los cambios que intente hacer el usuario no se guardaran.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Preview&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, la idea general de abrir un archivo es para obtener datos de el o para manipularlo, ya sea un documento nuevo o uno existente, veamos como guardar los cambios realizados y cerrar el archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    # aquí va todo el código que quieras para manipular el archivo&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto correctamente, presiona Aceptar para gaurdarlo y cerrarlo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # guardamos los cambios&lt;br /&gt;
    doc.store()&lt;br /&gt;
    # cerramos el archivo&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El código anterior funcionara con un archivo existente, pero con uno nuevo no,&lt;br /&gt;
te dará un error, por supuesto no me creas, compruébalo. Los documentos&lt;br /&gt;
tienen un método (&amp;#039;&amp;#039;&amp;#039;hasLocation&amp;#039;&amp;#039;&amp;#039;) que nos informa si un documento ya esta guardado o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
    &lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El primer mensaje debe mostrarte falso (False) porque es un documento nuevo y&lt;br /&gt;
el segundo verdadero (True) por ser un archivo abierto del disco.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También tenemos una propiedad que nos ayuda a saber si un documento ha sido modificado o no, ejecuta la siguiente macro, llamándola desde diferentes documentos, unos ábrelos y modifícalos antes de ejecutarla, otros, solo ábrelos y ejecútala para que notes la diferencia.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def esta_modificado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
 &lt;br /&gt;
    msgbox(doc.isModified())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y otra más que nos informa si el documento es de solo lectura (&amp;#039;&amp;#039;&amp;#039;isReadonly&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que valides antes de intentar guardar un archivo, si este ha sido&lt;br /&gt;
modificado o es de solo lectura. Ahora veamos como guardar un archivo nuevo con el método &amp;#039;&amp;#039;&amp;#039;storeAsUrl&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como requiere dos parámetros, la ruta del archivo y una matriz de&lt;br /&gt;
propiedades, algunas de las cuales veremos a continuación. Toma nota de que si&lt;br /&gt;
el archivo ya existe lo reemplazara sin avisarte por lo que es buena practica&lt;br /&gt;
de programación validar esto, observa como volvemos a usar la librería&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; para saber si un archivo existe ya.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    documentos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def documentos():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;&lt;br /&gt;
    if os.path.exists(ruta):&lt;br /&gt;
        msgbox(u&amp;#039;El archivo existe, no se guardará el nuevo&amp;#039;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
De la macro anterior, &amp;#039;&amp;#039;&amp;#039;es muy importante&amp;#039;&amp;#039;&amp;#039; que tomes nota que para todos&lt;br /&gt;
los métodos de Python que usen rutas de archivos o directorios, se les tienen&lt;br /&gt;
que pasar en las rutas nativas del sistema operativo donde estes trabajando,&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;solo&amp;#039;&amp;#039;&amp;#039; a los métodos de AOO, es a los que se les pasa en notación URL.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Veamos algunas propiedades interesantes para guardar archivos, por ejemplo, guardar con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo pero con contraseña&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_protegido.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como sabes, AOO, soporta la importación/exportación de múltiples formatos de archivos, veamos como guardar, por ejemplo, en formato DOC.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo en formato DOC&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;MS Word 97&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que cuando exportes, uses un formato compatible, es decir, no&lt;br /&gt;
puedes guardar una hoja de calculo como documento de texto. En el [[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices|Apéndice]]&lt;br /&gt;
mostramos una macro para obtener todos los filtros que soporta AOO.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El método storeAsURL también lo puedes usar para abrir un archivo existente y guardarlo con otro nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos con otro nombre&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc_nuevo.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para terminar esta sección, vamos a hacer un poco más interactiva la apertura&lt;br /&gt;
y guardado de archivos, permitamos que el usuario escoja la ruta y el archivo&lt;br /&gt;
desde un cuadro de dialogo, para ello, usaremos el servicio&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt;, que nos permite hacer esto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    # podemos establecer el título&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        # el primer elemento es la ruta seleccionada&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si estableces la propiedad &amp;#039;&amp;#039;&amp;#039;MultiSelectionMode&amp;#039;&amp;#039;&amp;#039; en verdadero, le&lt;br /&gt;
permitiras al usuario seleccionar más de un archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    dlg.setMultiSelectionMode(True)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        archivos = dlg.getFiles()&lt;br /&gt;
        if len(archivos) == 1:&lt;br /&gt;
            # si selecciona uno, devuelve la ruta completa&lt;br /&gt;
            desktop.loadComponentFromURL(archivos[0], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
        else:&lt;br /&gt;
            # si selecciona varios, el primer elemento es la carpeta&lt;br /&gt;
            folder = archivos[0]&lt;br /&gt;
            # los demás elementos son los archivos seleccionados&lt;br /&gt;
            for f in range(1, len(archivos)):&lt;br /&gt;
                desktop.loadComponentFromURL(folder + archivos[f], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si lo notaste, con la macro anterior el usuario puede seleccionar cualquier&lt;br /&gt;
archivo, para limitar las opciones, agrega un filtro con el método&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;appendFilter&amp;#039;&amp;#039;&amp;#039; con solo los tipos de&lt;br /&gt;
archivos que necesites, usa una línea por cada filtro, este método requiere&lt;br /&gt;
dos argumentos, el primero es el título, lo que verá el usuario y el segundo&lt;br /&gt;
es el filtro en si.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, mostramos el cuadro de dialogo Guardar Como, para permitir al usuario&lt;br /&gt;
seleccionar carpeta y nombre de archivo donde guardar su archivo, se usa el&lt;br /&gt;
mismo servicio &amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt; solo cambiando&lt;br /&gt;
algunas de sus propiedades.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_AUTOEXTENSION_PASSWORD&lt;br /&gt;
    &lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Guardar archivo&amp;#039;)&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
    # con esta opción le indicamos que use guardar como con otras opciones&lt;br /&gt;
    dlg.initialize((FILESAVE_AUTOEXTENSION_PASSWORD,))&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        msgbox(ruta)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota que el argumento del método &amp;#039;&amp;#039;&amp;#039;initialize&amp;#039;&amp;#039;&amp;#039; es una tupla.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, para terminar, te mostramos como abrir un archivo de forma oculta.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo cerraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.store()&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es &amp;#039;&amp;#039;&amp;#039;muy importante&amp;#039;&amp;#039;&amp;#039;, que cuando abras un archivo oculto siempre uses el argumento &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, a menos claro esta, que sepas lo que haces, y que, mantengas una referencia a el, para poder cerrarlo en cuanto no lo necesites.&lt;br /&gt;
&lt;br /&gt;
== Algunas tareas comunes en documentos ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exportando a PDF ===&lt;br /&gt;
&lt;br /&gt;
Para exportar a PDF solo hay que establecer el filtro correcto, nota como construimos el nombre del filtro de acuerdo al tipo de documento y como construimos la ruta de acuerdo a la ruta actual donde este guardado el documento solo reemplazando la extensión para que quede en PDF. Estamos haciendo uso de la macro &amp;#039;&amp;#039;&amp;#039;obtener_tipo&amp;#039;&amp;#039;&amp;#039; con unos ligeros cambios para este propósito.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    export_pdf()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def export_pdf():&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    tipo = obtener_tipo(doc)&lt;br /&gt;
    soportados = &amp;#039;calc,writer,draw,impress,math&amp;#039;&lt;br /&gt;
    if tipo in soportados:&lt;br /&gt;
        # establecemos el filtro como PDF&lt;br /&gt;
        opciones = PropertyValue()&lt;br /&gt;
        opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
        opciones.Value = &amp;#039;%s_pdf_Export&amp;#039; % tipo&lt;br /&gt;
        # obtenemos la ruta y reemplazados la extensión por PDF&lt;br /&gt;
        ruta, archivo = os.path.split(doc.getURL())&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
        ruta = os.path.join(ruta, nombre + &amp;#039;.pdf&amp;#039;)&lt;br /&gt;
        # guardamos&lt;br /&gt;
        doc.storeToURL(ruta, (opciones,))&lt;br /&gt;
        msgbox(u&amp;#039;Documento exportado correctamente a PDF&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;Aplicación no soportada&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;basic&amp;#039;}&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            return tipo[t]&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La forma de descomponer la ruta en sus diferentes partes, ya la vimos anteriormente, en este caso, observa como la extensión actual del documento ya no la usaremos por lo que la omitimos con un guión bajo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ocultando y mostrando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para ocultar una ventana, hay que acceder a la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # y la ocultamos&lt;br /&gt;
        ventana.setVisible(False)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Se han ocultado todas las ventanas, presiona Aceptar para mostrarlas&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # tienes que crear de nuevo la enumeración&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # ahora las mostramos&lt;br /&gt;
        ventana.setVisible(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta técnica la puedes usar también para mostrar un archivo que abriste de forma oculta previamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo mostraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    ventana.setVisible(True)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo visible, ahora lo cerramos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Activando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para usamos el método &amp;#039;&amp;#039;&amp;#039;setFocus&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # esperamos 3 segundos y mostramos la ventana&lt;br /&gt;
        time.sleep(3)&lt;br /&gt;
        ventana.setFocus()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Controlando la barra de estado ===&lt;br /&gt;
&lt;br /&gt;
La barra de estado, generalmente en la parte inferior de las aplicaciones, es útil para dar información al usuario, generalmente de un proceso en progreso.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def barra_estado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    barra = doc.getCurrentController().getStatusIndicator()&lt;br /&gt;
    barra.start(u&amp;#039;Se procesaran líneas en tres segundos&amp;#039;, 10)&lt;br /&gt;
    # esta pausa es solo para que veas el mensaje anterior en la barra de estado&lt;br /&gt;
    time.sleep(3)&lt;br /&gt;
    for i in range(1, 11):&lt;br /&gt;
        barra.setValue(i)&lt;br /&gt;
        barra.setText(u&amp;#039;Procesando línea: %s&amp;#039; % i)&lt;br /&gt;
        # pausa de un segundo&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
    # importante para regresar el control a la aplicación&lt;br /&gt;
    barra.end()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218396</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218396"/>
		<updated>2013-04-28T19:34:12Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Controlando la barra de estado */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con Apache OpenOffice}}&lt;br /&gt;
&lt;br /&gt;
== Conceptos iniciales==&lt;br /&gt;
&lt;br /&gt;
Este es el tema más importante para crear macros, de forma sencilla, pero se ven las bases para trabajar con todo AOO, por eso es importante no avanzar en estas notas, sin antes haber comprendido a cabalidad los temas presentes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;UNO&amp;#039;&amp;#039;&amp;#039; (Universal Network Objects), es la especificación que da acceso a todos los objetos de Apache OpenOffice. Todo lo que quieras saber de esta especificación, lo puedes encontrar en la [[http://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide Guía del desarrollador]] (en ingles).&lt;br /&gt;
&lt;br /&gt;
El &amp;#039;&amp;#039;&amp;#039;API&amp;#039;&amp;#039;&amp;#039; (Application Programer Interface) de Apache OpenOffice proporciona el acceso a toda la funcionalidad de AOO, independientemente del lenguaje. Todo el API de AOO esta en &amp;lt;idl&amp;gt;com.sun.star.module-ix&amp;lt;/idl&amp;gt; (solo ingles).&lt;br /&gt;
&lt;br /&gt;
La comunicación entre objetos UNO se basa en &amp;#039;&amp;#039;&amp;#039;interfaces&amp;#039;&amp;#039;&amp;#039; de objeto.  Las interfaces pueden ser vistos desde el exterior o el interior de un objeto y proporcionan formas de ver o manipular el objeto.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;servicios&amp;#039;&amp;#039;&amp;#039; son agrupaciones lógicas de interfaces, son la forma en que un mismo objeto pueda ofrecer la funcionalidad de varias interfaces.&lt;br /&gt;
&lt;br /&gt;
Los servicios se pueden implementar en librerías compartidas llamadas &amp;#039;&amp;#039;&amp;#039;componentes UNO&amp;#039;&amp;#039;&amp;#039;, con Python podemos crear componentes nuevos y generalmente el usuario final las recibe como una extensión OXT.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;modulos&amp;#039;&amp;#039;&amp;#039; pueden agrupar submodulos, servicios, excepciones, constantes, enumeraciones, etc, se utilizan para especificar bloques coherentes en la API, esto permite tener un API bien estructurada.&lt;br /&gt;
&lt;br /&gt;
== Creando servicios ==&lt;br /&gt;
Para crear un servicio, usamos la &amp;#039;&amp;#039;&amp;#039;fabrica de servicios&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;), una interfaz especial para crear nuevos servicios, pero para llegar a ella, tenemos que hacerlo a traves de la interfaz &amp;#039;&amp;#039;&amp;#039;ComponentContext&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;), como puedes verlo en la siguiente imagen. &lt;br /&gt;
[[Image:UseServices1.png|none|thumb|400px|ComponentContext y ServiceManager]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En pyUNO tenemos dos formas de acceder a esta interfaz, las dos son equivalentes por lo que puedes usar la que prefieras. En la introducción a Python se mencionó que la mayoría de sus herramientas están disponibles en librerias, estás librerias tienen que importarse &amp;#039;&amp;#039;&amp;#039;antes&amp;#039;&amp;#039;&amp;#039; de poder usarse, en nuestro caso importaremos la librería &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; que nos da acceso (entre otras cosas) al contexto de ejecución de AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx1 = XSCRIPTCONTEXT.getComponentContext()&lt;br /&gt;
    ctx2 = uno.getComponentContext()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si te gusta investigar, busca el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; en la carpeta de instalación de AOO, ahí puedes ver de donde sale XSCRIPTCONTEXT}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, podemos acceder a la fábrica de servicios con el &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿como sabemos que este &amp;#039;&amp;#039;&amp;#039;objeto (ComponentContext)&amp;#039;&amp;#039;&amp;#039; tiene este &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;? porque lo estamos demostrando, si, también por eso, pero también porque puedes ver su documentación (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;) en el API de AOO, pero más importante aún, porque podemos hacer que el mismo objeto te diga todo lo que sabe hacer. Para ello haremos uso de una magnifica extensión que te tiene que acompañar el resto de tus días como programador de macros Python, nos referimos a [http://extensions.services.openoffice.org/project/MRI MRI]. Instala (tal vez tengas que reiniciar AOO para poder usarla) y la probamos de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    # llamamos a la extensión MRI y le pasamos el objeto a inspeccionar&lt;br /&gt;
    mri(ctx)&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def mri(target):&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()    &lt;br /&gt;
    mri = sm.createInstanceWithContext(&amp;#039;mytools.Mri&amp;#039;, ctx)&lt;br /&gt;
    mri.inspect(target)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa en la imágen siguiente, como hemos seleccionado los métodos del objeto y nos lista todos los que tenga, hemos remarcado el que por ahora nos interesa &amp;#039;&amp;#039;&amp;#039;getServiceManager()&amp;#039;&amp;#039;&amp;#039;, observa al final de la línea que efectivamente este método nos devuelve una &amp;#039;&amp;#039;&amp;#039;instancia&amp;#039;&amp;#039;&amp;#039; de la interfaz &amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;. &lt;br /&gt;
[[Image:Py_img_0006.png|none|thumb|500px|Usando la extensión MRI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gran ventaja de usar esta extensión (que por cierto esta hecha en Python), es que siempre te devolverá la información directamente del objeto, a esto se le llama &amp;#039;&amp;#039;&amp;#039;instrospección&amp;#039;&amp;#039;&amp;#039;. Acostumbrate a usarla.&lt;br /&gt;
&lt;br /&gt;
Ahora si, ya podemos crear una instancia de cualquier servicio o interfaz disponible en AOO, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existe una forma alternativa de crear este servicio, usando &amp;#039;&amp;#039;&amp;#039;XSCRIPTCONTEXT&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    XSCRIPTCONTEXT.getDesktop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si vuelves a mirar el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; notaras que usa el mismo método para instanciar este servicio}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y para que sirve este servicio? Entre otras cosas para crear nuevos documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
nuevo = desktop.loadComponentFromURL(&amp;#039;private:factory/scalc&amp;#039;, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos a detalle este método y otros relacionados con los documentos de AOO. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; es la instancia de la administración central para todas las aplicaciones AOO.  Todas las ventanas de la aplicación AOO se organizan en una jerarquía de marcos que contienen componentes visibles.  &lt;br /&gt;
&lt;br /&gt;
[[Image:DesktopOverview.png|none|thumb|400px|Desktop administra los componentes y marcos.]]&lt;br /&gt;
&lt;br /&gt;
Para los fines de crear macros es suficiente que recuerdes que, Desktop es el marco raíz de toda la jerarquía de documentos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para crear la instancia del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; usamos un contexto y usamos el método &amp;#039;&amp;#039;&amp;#039;createInstanceWithContext&amp;#039;&amp;#039;&amp;#039;. Otros servicios no requieren de contexto para ser instanciados y usados, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.util.PathSettings&amp;lt;/idl&amp;gt; que nos sirve para obtener las rutas de trabajo actuales en AOO, para estos casos usamos el método &amp;#039;&amp;#039;&amp;#039;createInstance&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    rutas = sm.createInstance(&amp;#039;com.sun.star.util.PathSettings&amp;#039;)&lt;br /&gt;
    # mostramos la ruta de trabajo del usuario&lt;br /&gt;
    print (rutas.Work)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora que ya sabemos instanciar servicios, veamos de nuevo nuestra macro para mostrar un mensaje en pantalla y analicemosla línea a línea para que veas que sencillo es, además, nos servirá para ver otros detalles al programar con Python en AOO. La macro tiene ahora unos ligeros cambios para que trabaje mejor y para explicar algunas cosas, veamos cuales.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la primer línea &amp;#039;&amp;#039;&amp;#039;declaramos&amp;#039;&amp;#039;&amp;#039; nuestra macro, su nombre y los argumentos que necesita, en este caso solo uno &amp;#039;&amp;#039;&amp;#039;message&amp;#039;&amp;#039;&amp;#039; que será el mensaje a mostrar.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la segunda línea, estamos importando (&amp;#039;&amp;#039;&amp;#039;import&amp;#039;&amp;#039;&amp;#039;) la estructura &amp;#039;&amp;#039;&amp;#039;Rectangle&amp;#039;&amp;#039;&amp;#039; desde (&amp;#039;&amp;#039;&amp;#039;from&amp;#039;&amp;#039;&amp;#039;) el modulo &amp;lt;idl&amp;gt;com.sun.star.awt.module-ix&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Las estructuras son un conjunto de valores relacionados, valores que pueden ser de tipos diferentes, pero que son mostrados como una unidad lógica, por ejemplo, la estructura &amp;lt;idl&amp;gt;com.sun.star.awt.Rectangle&amp;lt;/idl&amp;gt; hace referencia a un área rectangular estableciendo su posición y tamaño, en este caso, solo sirve para cumplir los argumentos del método para mostrar nuestro mensaje.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la tercer línea, hacemos otra importación, pero esta vez la hacemos de una constante, específicamente la constante para mostrar el botón &amp;#039;&amp;#039;&amp;#039;Aceptar&amp;#039;&amp;#039;&amp;#039; (OK), estas constantes las puedes ver aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.MessageBoxButtons&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La cuarta línea esta vacía solo para separar la parte de importacion con el resto del código. En la siguiente línea hacemos una validación del argumento pasado a nuestra macro, si el argumento &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; es una instancia de la clase &amp;#039;&amp;#039;&amp;#039;unicode&amp;#039;&amp;#039;&amp;#039; o de la clase &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, entonces la convertimos a &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, esto nos permite pasar a nuestra macro, listas, tuplas, diccionarios y practicamente cualquier objeto, del cual, podremos ver su representación en texto, muchas veces, con información bastante útil.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea ya la hemos estudiado, creamos una instancia del contexto donde se ejecuta AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea también ya la hemos estudiado, creamos una instancia de la fabrica de servicios, una de las instancias más importantes y que usaras constantemente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la siguiente línea creamos una instancia con contexto de un nuevo servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt;, este servicio sirve, entre otras muchas cosas para crear ventanas y mensaje de texto, como el de nuestra macro.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la penultima línea, usamos el método &amp;#039;&amp;#039;&amp;#039;createMessageBox&amp;#039;&amp;#039;&amp;#039; del servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt; para crear nuestro cuadro de mensaje, todos los argumentos de este método puedes verlo aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.XMessageBoxFactory&amp;lt;/idl&amp;gt;, pero aquí los explicamos uno a uno.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Aunque veas muchas líneas, el interpete la considera una sola, esto se logra al estar todos los argumentos entre paréntesis.&lt;br /&gt;
* El primer argumento es la ventana padre (&amp;#039;&amp;#039;&amp;#039;parent&amp;#039;&amp;#039;&amp;#039;) donde será mostrado el cuadro de mensaje, observa como usamos de nuevo el servicio &amp;#039;&amp;#039;&amp;#039;toolkit&amp;#039;&amp;#039;&amp;#039; para recuperar (&amp;#039;&amp;#039;&amp;#039;getDesktopWindow&amp;#039;&amp;#039;&amp;#039;) la ventana padre de AOO.&lt;br /&gt;
* El segundo argumento es el área rectangular del cuadro de mensaje, observa los dos paréntesis al final del nombre de la estructura, son necesarios para inicializarla.&lt;br /&gt;
* El tercer argumento es el tipo de mensaje, dependiendo de este argumento se muestra el icono correspondiente, los valores permitidos son: &amp;#039;&amp;#039;&amp;#039;infobox, warningbox, errorbox, querybox y messbox&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;infobox&amp;#039;&amp;#039;&amp;#039;, el siguiente argumento es ignorado.&lt;br /&gt;
* El cuarto argumento sirve para mostrar botones de comando diferentes, como: &amp;#039;&amp;#039;&amp;#039;Si, No, Cancelar&amp;#039;&amp;#039;&amp;#039;, etc, que están establecidos en las constantes vistas más arriba.&lt;br /&gt;
* El quinto argumento es el título del cuadro de mensaje.&lt;br /&gt;
* Y por ultimo, el mensaje a mostrar, el cual ya validamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la ultima línea al mismo tiempo que mostramos (&amp;#039;&amp;#039;&amp;#039;ejecute&amp;#039;&amp;#039;&amp;#039;) estamos retornando el cuadro de mensaje, esto nos da la posibilidad de capturar el botón al que le haya dado click el usuario, lo cual, veremos más adelante. Todas las macros retornan un valor, aun y cuando este sea un valor vacío (None).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, los servicio los instanciamos y las estructuras y constantes las importamos, y el punto más importante; &amp;#039;&amp;#039;&amp;#039;acostúmbrate a usar, manejar y dominar, la extensión MRI&amp;#039;&amp;#039;&amp;#039;, ella te dice todo lo necesario para trabajar con los objetos UNO de AOO, los demás, es sencillo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== El documento activo ==&lt;br /&gt;
&lt;br /&gt;
Tenemos dos formas de acceder al documento activo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc1 = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
    doc2 = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc1.getIdentifier())&lt;br /&gt;
    print (doc2.getIdentifier())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note| Mira en el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; la forma en que trabaja el método &amp;#039;&amp;#039;&amp;#039;getDocument&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si seguiste nuestra recomendación de asignar la macro de pruebas a una combinación de teclas disponible en todo AOO, prueba a abrir cada uno de los tipos de documentos que puedes ver en el menú &amp;#039;&amp;#039;&amp;#039;Archivo-&amp;gt;Nuevo-&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
[[Image:Py_img_0007.png|none|thumb|500px|Tipos de documentos en AOO]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y a ejecutar la siguiente macro, teniendo como documento activo cada uno de ellos, es decir, activas uno y ejecutas la macro, activas otro y vuelves a llamar a la macro y así sucesivamente con todos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getIdentifier())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los mensajes devueltos en cada documento, son bastante ilustrativos de que &amp;#039;&amp;#039;&amp;#039;tipo de documento&amp;#039;&amp;#039;&amp;#039; se trata. Pero si probaste con todos, habrás notado que con la base de datos nos devuelve un error, si no lo has probado hazlo ahora. Para resolver este caso tenemos varias posibilidades, la primera es controlar la excepción como ya aprendimos en la introducción a Python.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿estamos realmente seguros que ese es el error?, es mejor especificarlo y asegurarnos de que este es el error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tenemos otra alternativa donde no usamos controlador de excepciónes, si no una función que nos dice si un cierto atributo lo posee o no un objeto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    if hasattr(doc, &amp;#039;getIdentifier&amp;#039;):&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Sin atributo getIdentifier&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es mucho mejor esta segunda opción. Aun así, no podemos estar 100% seguros de que cuando no la tenga, el documento sea una base de datos, simplemente estamos excluyendo la posibilidad pero no lo estamos asegurando, probemos con otra propiedad.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getImplementationName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mucho mejor, ahora ya no tenemos errores, pero si probaste de nuevo con todos los tipos de documentos, habrás notado que con &amp;#039;&amp;#039;&amp;#039;Impres&amp;#039;&amp;#039;&amp;#039; y con &amp;#039;&amp;#039;&amp;#039;Draw&amp;#039;&amp;#039;&amp;#039; obtenemos el mismo resultado, por lo que no tenemos la certeza de que tipo de documento es, por lo que descartamos esta propiedad para nuestra finalidad que es identificar fehacientemente cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
Ya vimos que cada objeto UNO soporta diferentes servicios e interfaces, asì que cada documento de AOO (&amp;#039;&amp;#039;&amp;#039;que son objetos&amp;#039;&amp;#039;&amp;#039;) soportan diferentes servicios, algunos son iguales, es decir, comúnes a todos, pero algunos pueden ser únicos para cada documento. Ya vimos como saber si un documento soporta una propiedad, pero para saber si soporta un servicio completo, cambiamos de método, ahora usamos &amp;#039;&amp;#039;&amp;#039;supportsService&amp;#039;&amp;#039;&amp;#039; que nos devuelve falso o verdadero según soporte o no el nombre del servicio pasado como argumento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    res = doc.supportsService(&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;)&lt;br /&gt;
    mensaje = u&amp;#039;No soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    if res:&lt;br /&gt;
        mensaje = u&amp;#039;Soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    print(mensaje)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y mejor aun, podemos saber todos los servicios que soporta un objeto con el método &amp;#039;&amp;#039;&amp;#039;getSupportedServiceNames&amp;#039;&amp;#039;&amp;#039; que nos devuelve una tupla con todos sus nombres.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    servicios = doc.getSupportedServiceNames()&lt;br /&gt;
    &lt;br /&gt;
    print(servicios)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Te queda de tarea probar esta macro en cada uno de los documentos abiertos, incluso puedes probar también el IDE para AOOBasic que incorpora AOO y determinar que servicio usar para diferenciar sin duda cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
== Los documentos abiertos ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todos los documentos abiertos en la sesión de AOO, usamos el método &amp;#039;&amp;#039;&amp;#039;getComponents&amp;#039;&amp;#039;&amp;#039; del objeto &amp;#039;&amp;#039;&amp;#039;Desktop&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;MRI&amp;#039;&amp;#039;&amp;#039;, notarás que este método nos devuelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta interfaz (&amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;) tiene un solo método llamado &amp;#039;&amp;#039;&amp;#039;createEnumeration&amp;#039;&amp;#039;&amp;#039; que nos duelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumeration&amp;lt;/idl&amp;gt; la cual a su vez tiene solo dos métodos, el primero para saber si tenemos más elementos en la enumeración: &amp;#039;&amp;#039;&amp;#039;hasMoreElements&amp;#039;&amp;#039;&amp;#039; y el segundo para acceder al siguiente elemento &amp;#039;&amp;#039;&amp;#039;nextElement&amp;#039;&amp;#039;&amp;#039;, veamoslo con un ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    # mientras tengamos elementos&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        # obtenemos el siguiente elemento&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # mostrámos el tipo de documento&lt;br /&gt;
        mensaje = obtener_tipo(doc)&lt;br /&gt;
        print(mensaje)&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;Calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;Writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;Impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;Draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;Base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;Math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;Basic&amp;#039;}&lt;br /&gt;
    # iteramos entre los tipos de documentos&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        # validamos si soporta el servicio&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            # devolvemos el tipo de documento&lt;br /&gt;
            return &amp;#039;Soy %s&amp;#039; % tipo[t]&lt;br /&gt;
    # si termina sin encontrar un tipo&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como usamos una macro de apoyo para saber que tipo de documento es. Una enumeración no es más que una lista de objetos y es una forma muy común y a veces la única de acceder a ciertos objetos en AOO, es importante que la recuerdes.&lt;br /&gt;
&lt;br /&gt;
== Rutas de archivos y directorios ==&lt;br /&gt;
&lt;br /&gt;
Apache OpenOffice, al ser multiplataforma, hace uso de las rutas de archivos y directorios, en el formato URL, por ejemplo.&lt;br /&gt;
&lt;br /&gt;
file:///home/usuario/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
file:///d:/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta que este formato hace uso de los caracteres 0-9, a-z y A-Z, y cualquier otro carácter será convertido y mostrado con su respectivo código, por ejemplo, los espacios los reemplazara con &amp;#039;&amp;#039;&amp;#039;%20&amp;#039;&amp;#039;&amp;#039;. Siempre que le pases una ruta de archivo a cualquier servicio de AOO, hazlo, casi como una regla, pasarle la ruta en formato Url, para ello, la libreria &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; cuenta con dos funciones muy útiles que hacen el trabajo &amp;#039;&amp;#039;&amp;#039;systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; y &amp;#039;&amp;#039;&amp;#039;fileUrlToSystemPath&amp;#039;&amp;#039;&amp;#039;, veamos como se usan.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def rutas():&lt;br /&gt;
    &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi archivo de Calc.ods&amp;quot;&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # La convertimos al formato URL&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # Regresamos al formato local&lt;br /&gt;
    ruta = uno.fileUrlToSystemPath(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Abre varios documentos existentes y ejecuta la siguiente macro desde cada uno:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def info_ruta():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
    &lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    # obtenemos la ruta en disco&lt;br /&gt;
    ruta =  doc.getURL()&lt;br /&gt;
    # obtenemos las diferentes partes de la ruta&lt;br /&gt;
    ruta, archivo = os.path.split(ruta)&lt;br /&gt;
    nombre, extension = os.path.splitext(archivo)&lt;br /&gt;
    &lt;br /&gt;
    print (ruta)&lt;br /&gt;
    print (uno.fileUrlToSystemPath(ruta))&lt;br /&gt;
    print (archivo)&lt;br /&gt;
    print (nombre)&lt;br /&gt;
    print (extension)&lt;br /&gt;
    &lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hemos importado una nueva librería de Python, &amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; que entre otras muchas cosas, nos permite obtener información de las rutas de archivos como en la macro anterior.&lt;br /&gt;
&lt;br /&gt;
En nuestros siguientes temas, veremos la importancia de usar las rutas de archivos y directorios en formato Url y recuerda que en S.O. Linux, se tiene en cuenta la diferencia entre mayúsculas y minúsculas.&lt;br /&gt;
&lt;br /&gt;
== Creando nuevos documentos ==&lt;br /&gt;
&lt;br /&gt;
El método que nos permite crear nuevos documentos se llama &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039; y es un método del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, por ejemplo, para crear una nueva hoja de calculo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo hay que hacer un pequeño cambio para crear un nuevo documento de texto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y los demás tipos de documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/simpress&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/sdraw&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/smath&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y una base de datos?, probemos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/sbase&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos da un error ¿verdad?&lt;br /&gt;
[[Image:Py_img_0008.png|none|thumb|500px|Error al crear base de datos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No esta soportado. Para saber por que nos da un error, intenta abrir una base de datos nueva, observa como primero, si queremos trabajar con ella, el asistente nos “obliga” primero a guardarla con un nombre y después ya podemos manipularla, esto, solo pasa con las bases de datos, de los demás documentos podemos crear tantos nuevos documentos como queramos sin tener que guardar nada, entonces ¿como creamos una nueva base de datos?, la respuesta es sencilla, del mismo modo que lo hacemos desde la interfaz de usuario, es decir, tenemos que guardar primero la base de datos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
 &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi_Base_Datos.odb&amp;quot;&lt;br /&gt;
    # Creamos el servicio que nos permite manipular bases de datos&lt;br /&gt;
    dbcon = sm.createInstance(&amp;#039;com.sun.star.sdb.DatabaseContext&amp;#039;)&lt;br /&gt;
    # creamos una instancia de una nueva base de datos&lt;br /&gt;
    base = dbcon.createInstance()&lt;br /&gt;
    # establecemos el tipo de base&lt;br /&gt;
    base.URL = &amp;quot;sdbc:embedded:hsqldb&amp;quot;&lt;br /&gt;
    # y la guardamos&lt;br /&gt;
    base.DatabaseDocument.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta dos cosas muy importantes en la macro anterior, el nombre que uses, si ya existe, simplemente lo reemplazara, no te preguntara nada, así que ten cuidado de no usar una ruta o nombre de una base importante que tengas y segundo, la base de datos así creada, no quedara “registrada” en AOO, con lo que no tendrás acceso desde otros programas de la aplicación, más adelante veremos como registrar una base de datos por código.&lt;br /&gt;
&lt;br /&gt;
== Abriendo, guardando y cerrando documentos ==&lt;br /&gt;
Abrir archivos existentes es sumamente sencillo, usamos el mismo método usado&lt;br /&gt;
para crear nuevos documentos &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, pero en el parámetro ruta, le especificamos la ubicación del archivo a abrir de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def documento1():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si tus archivos existen (esto se puede validar), el código anterior los abrirá, &amp;#039;&amp;#039;&amp;#039;siempre&amp;#039;&amp;#039;&amp;#039; utiliza&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;uno.systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; cuando uses rutas de archivos o directorios en&lt;br /&gt;
funciones de AOO que las requieran como argumentos. Ya vimos que el primer&lt;br /&gt;
agumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, es la ruta del archivo a&lt;br /&gt;
abrir, el segundo argumento es una cadena con el nombre del macro (frame)&lt;br /&gt;
donde será mostrado el documento abierto, generalmente si existe este frame se&lt;br /&gt;
usa si no se crea uno nuevo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_cal&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_writer&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existen nombre especiales para este agumento, los más usuales son dos, primero&lt;br /&gt;
que ya hemos estado usando &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; que usa el frame actual y&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039; que siempre crea un nuevo frame.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La recomendación es que uses siempre &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; o &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, un&lt;br /&gt;
escenario puede ser que habrás con &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; una instancia, y después de&lt;br /&gt;
forma oculta uno nuevo con &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, más abajo vemos como abrir un&lt;br /&gt;
documento de forma oculta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si abres una plantilla, esta se comportará de forma normal, es decir, te abrirá una copia de dicha plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_plantilla.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero también podrías querer abrir la plantilla para editarla, en este caso,&lt;br /&gt;
le indicamos en las opciones de apertura esta opción, y aquí vemos como usar&lt;br /&gt;
el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como hemos importado una nueva estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como la instanciamos y asignamos sus valores.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Muy importante, el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
espera una tupla, por eso es que usamos la coma al final del nombre del&lt;br /&gt;
argumento &amp;#039;&amp;#039;&amp;#039;(opciones,)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt; esta conformada por&lt;br /&gt;
un par de valores, un nombre y un valor y es muy frecuentemente usada cuando se&lt;br /&gt;
programa en AOO, para este ejemplo solo hemos usado un par de agumentos,&lt;br /&gt;
siempre van en pares, pero muy bien puede tener más opciones como veremos más&lt;br /&gt;
adelante. En la macro anterior le estamos indicando la propiedad&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (que seria algo así como Es Plantilla), si el valor es&lt;br /&gt;
falso (False), le estamos indicando que queremos abrir la plantilla para&lt;br /&gt;
editarla, en caso contrario (True) abrirá una copia de la plantilla. Lo&lt;br /&gt;
interesante de esta propiedad es que perfectamente la puedes aplicar a archivos&lt;br /&gt;
existentes, es decir, archivos que &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; necesariamente sean plantillas, con&lt;br /&gt;
esta propiedad podemos forzarlos a comportarse como plantillas, por ejemplo, prueba el siguiente código con algún archivo existente que no sea plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como el archivo es un documento de texto normal (ODT), pero con la&lt;br /&gt;
propiedad &amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;, forzamos su apertura como una plantilla.&lt;br /&gt;
&lt;br /&gt;
Otras propiedades interesantes son &amp;#039;&amp;#039;&amp;#039;ReadOnly&amp;#039;&amp;#039;&amp;#039; (Solo Lectura) para abrir un&lt;br /&gt;
archivo como solo lectura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y &amp;#039;&amp;#039;&amp;#039;Password&amp;#039;&amp;#039;&amp;#039; (Contraseña) para abrir archivos con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto puedes combinar cualquier cantidad de opciones siempre y cuando no&lt;br /&gt;
entren en conflicto, es importante que al final, sea una tupla lo que le pasas&lt;br /&gt;
al método, si no, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # creamos una lista vacía&lt;br /&gt;
    opciones = []&lt;br /&gt;
    # creamos la primer propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opcion.Value = True&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
    # creamos la segunda propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opcion.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    # nota que la lista la convertimos en tupla&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, tuple(opciones))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si la contraseña es incorrecta, no obtendrás ningún mensaje, simplemente no&lt;br /&gt;
lo abrira y la variable &amp;#039;&amp;#039;&amp;#039;doc&amp;#039;&amp;#039;&amp;#039; será vacía, puedes validar esto:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if doc is None:&lt;br /&gt;
        print (&amp;#039;No se abrio el documento&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos otras formas de validar y depurar nuestras macros para&lt;br /&gt;
los dificiles casos en donde no obtengamos ningún mensaje de error, pero&lt;br /&gt;
simplemente nuestra macro se niega a hacer su trabajo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mientras un formato de archivo sea soportado por AOO, lo podrás abrir con el&lt;br /&gt;
método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, en el siguiente ejemplo, abrimos un archivo tipo Doc, un Html y un Xls.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_web.html&amp;#039;)&lt;br /&gt;
    doc_h = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_excel.xls&amp;#039;)&lt;br /&gt;
    doc_x = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Qué otras opciones tengo para abrir archivos?. La mayoría están descritas&lt;br /&gt;
en el servicio &amp;lt;idl&amp;gt;com.sun.star.document.MediaDescriptor&amp;lt;/idl&amp;gt;, aquí veremos&lt;br /&gt;
las más usadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cuando abres un archivo por código y este contiene macros, tu puedes&lt;br /&gt;
establecer si se abre con las macros activadas, de forma predeterminada lo abre&lt;br /&gt;
con las macros desactivadas, así que solo nos resta saber como abrirlo con las&lt;br /&gt;
macros activadas, las constanes que puedes usar puedes verlas aquí&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.document.MacroExecMode&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.document.MacroExecMode import ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;MacroExecutionMode&amp;#039;&lt;br /&gt;
    opciones.Value = ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Otra opción interesante, es la que nos permite abrir una presentación e iniciarla inmediatamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;StartPresentation&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_impress.odp&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes abrir un archivo como vista previa, útil para evitar que el usuario haga cambios en el, en este estado, los cambios que intente hacer el usuario no se guardaran.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Preview&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, la idea general de abrir un archivo es para obtener datos de el o para manipularlo, ya sea un documento nuevo o uno existente, veamos como guardar los cambios realizados y cerrar el archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    # aquí va todo el código que quieras para manipular el archivo&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto correctamente, presiona Aceptar para gaurdarlo y cerrarlo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # guardamos los cambios&lt;br /&gt;
    doc.store()&lt;br /&gt;
    # cerramos el archivo&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El código anterior funcionara con un archivo existente, pero con uno nuevo no,&lt;br /&gt;
te dará un error, por supuesto no me creas, compruébalo. Los documentos&lt;br /&gt;
tienen un método (&amp;#039;&amp;#039;&amp;#039;hasLocation&amp;#039;&amp;#039;&amp;#039;) que nos informa si un documento ya esta guardado o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
    &lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El primer mensaje debe mostrarte falso (False) porque es un documento nuevo y&lt;br /&gt;
el segundo verdadero (True) por ser un archivo abierto del disco.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También tenemos una propiedad que nos ayuda a saber si un documento ha sido modificado o no, ejecuta la siguiente macro, llamándola desde diferentes documentos, unos ábrelos y modifícalos antes de ejecutarla, otros, solo ábrelos y ejecútala para que notes la diferencia.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def esta_modificado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
 &lt;br /&gt;
    msgbox(doc.isModified())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y otra más que nos informa si el documento es de solo lectura (&amp;#039;&amp;#039;&amp;#039;isReadonly&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que valides antes de intentar guardar un archivo, si este ha sido&lt;br /&gt;
modificado o es de solo lectura. Ahora veamos como guardar un archivo nuevo con el método &amp;#039;&amp;#039;&amp;#039;storeAsUrl&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como requiere dos parámetros, la ruta del archivo y una matriz de&lt;br /&gt;
propiedades, algunas de las cuales veremos a continuación. Toma nota de que si&lt;br /&gt;
el archivo ya existe lo reemplazara sin avisarte por lo que es buena practica&lt;br /&gt;
de programación validar esto, observa como volvemos a usar la librería&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; para saber si un archivo existe ya.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    documentos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def documentos():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;&lt;br /&gt;
    if os.path.exists(ruta):&lt;br /&gt;
        msgbox(u&amp;#039;El archivo existe, no se guardará el nuevo&amp;#039;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
De la macro anterior, &amp;#039;&amp;#039;&amp;#039;es muy importante&amp;#039;&amp;#039;&amp;#039; que tomes nota que para todos&lt;br /&gt;
los métodos de Python que usen rutas de archivos o directorios, se les tienen&lt;br /&gt;
que pasar en las rutas nativas del sistema operativo donde estes trabajando,&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;solo&amp;#039;&amp;#039;&amp;#039; a los métodos de AOO, es a los que se les pasa en notación URL.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Veamos algunas propiedades interesantes para guardar archivos, por ejemplo, guardar con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo pero con contraseña&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_protegido.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como sabes, AOO, soporta la importación/exportación de múltiples formatos de archivos, veamos como guardar, por ejemplo, en formato DOC.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo en formato DOC&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;MS Word 97&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que cuando exportes, uses un formato compatible, es decir, no&lt;br /&gt;
puedes guardar una hoja de calculo como documento de texto. En el [[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices|Apéndice]]&lt;br /&gt;
mostramos una macro para obtener todos los filtros que soporta AOO.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El método storeAsURL también lo puedes usar para abrir un archivo existente y guardarlo con otro nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos con otro nombre&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc_nuevo.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para terminar esta sección, vamos a hacer un poco más interactiva la apertura&lt;br /&gt;
y guardado de archivos, permitamos que el usuario escoja la ruta y el archivo&lt;br /&gt;
desde un cuadro de dialogo, para ello, usaremos el servicio&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt;, que nos permite hacer esto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    # podemos establecer el título&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        # el primer elemento es la ruta seleccionada&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si estableces la propiedad &amp;#039;&amp;#039;&amp;#039;MultiSelectionMode&amp;#039;&amp;#039;&amp;#039; en verdadero, le&lt;br /&gt;
permitiras al usuario seleccionar más de un archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    dlg.setMultiSelectionMode(True)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        archivos = dlg.getFiles()&lt;br /&gt;
        if len(archivos) == 1:&lt;br /&gt;
            # si selecciona uno, devuelve la ruta completa&lt;br /&gt;
            desktop.loadComponentFromURL(archivos[0], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
        else:&lt;br /&gt;
            # si selecciona varios, el primer elemento es la carpeta&lt;br /&gt;
            folder = archivos[0]&lt;br /&gt;
            # los demás elementos son los archivos seleccionados&lt;br /&gt;
            for f in range(1, len(archivos)):&lt;br /&gt;
                desktop.loadComponentFromURL(folder + archivos[f], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si lo notaste, con la macro anterior el usuario puede seleccionar cualquier&lt;br /&gt;
archivo, para limitar las opciones, agrega un filtro con el método&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;appendFilter&amp;#039;&amp;#039;&amp;#039; con solo los tipos de&lt;br /&gt;
archivos que necesites, usa una línea por cada filtro, este método requiere&lt;br /&gt;
dos argumentos, el primero es el título, lo que verá el usuario y el segundo&lt;br /&gt;
es el filtro en si.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, mostramos el cuadro de dialogo Guardar Como, para permitir al usuario&lt;br /&gt;
seleccionar carpeta y nombre de archivo donde guardar su archivo, se usa el&lt;br /&gt;
mismo servicio &amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt; solo cambiando&lt;br /&gt;
algunas de sus propiedades.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_AUTOEXTENSION_PASSWORD&lt;br /&gt;
    &lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Guardar archivo&amp;#039;)&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
    # con esta opción le indicamos que use guardar como con otras opciones&lt;br /&gt;
    dlg.initialize((FILESAVE_AUTOEXTENSION_PASSWORD,))&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        msgbox(ruta)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota que el argumento del método &amp;#039;&amp;#039;&amp;#039;initialize&amp;#039;&amp;#039;&amp;#039; es una tupla.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, para terminar, te mostramos como abrir un archivo de forma oculta.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo cerraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.store()&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es &amp;#039;&amp;#039;&amp;#039;muy importante&amp;#039;&amp;#039;&amp;#039;, que cuando abras un archivo oculto siempre uses el argumento &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, a menos claro esta, que sepas lo que haces, y que, mantengas una referencia a el, para poder cerrarlo en cuanto no lo necesites.&lt;br /&gt;
&lt;br /&gt;
== Algunas tareas comunes en documentos ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exportando a PDF ===&lt;br /&gt;
&lt;br /&gt;
Para exportar a PDF solo hay que establecer el filtro correcto, nota como construimos el nombre del filtro de acuerdo al tipo de documento y como construimos la ruta de acuerdo a la ruta actual donde este guardado el documento solo reemplazando la extensión para que quede en PDF. Estamos haciendo uso de la macro &amp;#039;&amp;#039;&amp;#039;obtener_tipo&amp;#039;&amp;#039;&amp;#039; con unos ligeros cambios para este propósito.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    export_pdf()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def export_pdf():&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    tipo = obtener_tipo(doc)&lt;br /&gt;
    soportados = &amp;#039;calc,writer,draw,impress,math&amp;#039;&lt;br /&gt;
    if tipo in soportados:&lt;br /&gt;
        # establecemos el filtro como PDF&lt;br /&gt;
        opciones = PropertyValue()&lt;br /&gt;
        opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
        opciones.Value = &amp;#039;%s_pdf_Export&amp;#039; % tipo&lt;br /&gt;
        # obtenemos la ruta y reemplazados la extensión por PDF&lt;br /&gt;
        ruta, archivo = os.path.split(doc.getURL())&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
        ruta = os.path.join(ruta, nombre + &amp;#039;.pdf&amp;#039;)&lt;br /&gt;
        # guardamos&lt;br /&gt;
        doc.storeToURL(ruta, (opciones,))&lt;br /&gt;
        msgbox(u&amp;#039;Documento exportado correctamente a PDF&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;Aplicación no soportada&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;basic&amp;#039;}&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            return tipo[t]&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La forma de descomponer la ruta en sus diferentes partes, ya la vimos anteriormente, en este caso, observa como la extensión actual del documento ya no la usaremos por lo que la omitimos con un guión bajo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ocultando y mostrando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para ocultar una ventana, hay que acceder a la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # y la ocultamos&lt;br /&gt;
        ventana.setVisible(False)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Se han ocultado todas las ventanas, presiona Aceptar para mostrarlas&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # tienes que crear de nuevo la enumeración&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # ahora las mostramos&lt;br /&gt;
        ventana.setVisible(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta técnica la puedes usar también para mostrar un archivo que abriste de forma oculta previamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo mostraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    ventana.setVisible(True)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo visible, ahora lo cerramos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Activando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para usamos el método &amp;#039;&amp;#039;&amp;#039;setFocus&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # esperamos 3 segundos y mostramos la ventana&lt;br /&gt;
        time.sleep(3)&lt;br /&gt;
        ventana.setFocus()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Controlando la barra de estado ===&lt;br /&gt;
&lt;br /&gt;
La barra de estado, generalmente en la parte inferior de las aplicaciones, es útil para dar información al usuario, generalmente de un proceso en progreso.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def barra_estado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    barra = doc.getCurrentController().getStatusIndicator()&lt;br /&gt;
    barra.start(u&amp;#039;Se procesaran líneas en tres segundos&amp;#039;, 10)&lt;br /&gt;
    # esta pausa es solo para que veas el mensaje anterior en la barra de estado&lt;br /&gt;
    time.sleep(3)&lt;br /&gt;
    for i in range(1, 11):&lt;br /&gt;
        barra.setValue(i)&lt;br /&gt;
        barra.setText(u&amp;#039;Procesando línea: %s&amp;#039; % i)&lt;br /&gt;
        # pausa de un segundo&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
    # importante para regresar el control a la aplicación&lt;br /&gt;
    barra.end()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218395</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218395"/>
		<updated>2013-04-28T19:33:23Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Controlando la barra de estado */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con Apache OpenOffice}}&lt;br /&gt;
&lt;br /&gt;
== Conceptos iniciales==&lt;br /&gt;
&lt;br /&gt;
Este es el tema más importante para crear macros, de forma sencilla, pero se ven las bases para trabajar con todo AOO, por eso es importante no avanzar en estas notas, sin antes haber comprendido a cabalidad los temas presentes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;UNO&amp;#039;&amp;#039;&amp;#039; (Universal Network Objects), es la especificación que da acceso a todos los objetos de Apache OpenOffice. Todo lo que quieras saber de esta especificación, lo puedes encontrar en la [[http://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide Guía del desarrollador]] (en ingles).&lt;br /&gt;
&lt;br /&gt;
El &amp;#039;&amp;#039;&amp;#039;API&amp;#039;&amp;#039;&amp;#039; (Application Programer Interface) de Apache OpenOffice proporciona el acceso a toda la funcionalidad de AOO, independientemente del lenguaje. Todo el API de AOO esta en &amp;lt;idl&amp;gt;com.sun.star.module-ix&amp;lt;/idl&amp;gt; (solo ingles).&lt;br /&gt;
&lt;br /&gt;
La comunicación entre objetos UNO se basa en &amp;#039;&amp;#039;&amp;#039;interfaces&amp;#039;&amp;#039;&amp;#039; de objeto.  Las interfaces pueden ser vistos desde el exterior o el interior de un objeto y proporcionan formas de ver o manipular el objeto.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;servicios&amp;#039;&amp;#039;&amp;#039; son agrupaciones lógicas de interfaces, son la forma en que un mismo objeto pueda ofrecer la funcionalidad de varias interfaces.&lt;br /&gt;
&lt;br /&gt;
Los servicios se pueden implementar en librerías compartidas llamadas &amp;#039;&amp;#039;&amp;#039;componentes UNO&amp;#039;&amp;#039;&amp;#039;, con Python podemos crear componentes nuevos y generalmente el usuario final las recibe como una extensión OXT.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;modulos&amp;#039;&amp;#039;&amp;#039; pueden agrupar submodulos, servicios, excepciones, constantes, enumeraciones, etc, se utilizan para especificar bloques coherentes en la API, esto permite tener un API bien estructurada.&lt;br /&gt;
&lt;br /&gt;
== Creando servicios ==&lt;br /&gt;
Para crear un servicio, usamos la &amp;#039;&amp;#039;&amp;#039;fabrica de servicios&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;), una interfaz especial para crear nuevos servicios, pero para llegar a ella, tenemos que hacerlo a traves de la interfaz &amp;#039;&amp;#039;&amp;#039;ComponentContext&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;), como puedes verlo en la siguiente imagen. &lt;br /&gt;
[[Image:UseServices1.png|none|thumb|400px|ComponentContext y ServiceManager]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En pyUNO tenemos dos formas de acceder a esta interfaz, las dos son equivalentes por lo que puedes usar la que prefieras. En la introducción a Python se mencionó que la mayoría de sus herramientas están disponibles en librerias, estás librerias tienen que importarse &amp;#039;&amp;#039;&amp;#039;antes&amp;#039;&amp;#039;&amp;#039; de poder usarse, en nuestro caso importaremos la librería &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; que nos da acceso (entre otras cosas) al contexto de ejecución de AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx1 = XSCRIPTCONTEXT.getComponentContext()&lt;br /&gt;
    ctx2 = uno.getComponentContext()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si te gusta investigar, busca el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; en la carpeta de instalación de AOO, ahí puedes ver de donde sale XSCRIPTCONTEXT}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, podemos acceder a la fábrica de servicios con el &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿como sabemos que este &amp;#039;&amp;#039;&amp;#039;objeto (ComponentContext)&amp;#039;&amp;#039;&amp;#039; tiene este &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;? porque lo estamos demostrando, si, también por eso, pero también porque puedes ver su documentación (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;) en el API de AOO, pero más importante aún, porque podemos hacer que el mismo objeto te diga todo lo que sabe hacer. Para ello haremos uso de una magnifica extensión que te tiene que acompañar el resto de tus días como programador de macros Python, nos referimos a [http://extensions.services.openoffice.org/project/MRI MRI]. Instala (tal vez tengas que reiniciar AOO para poder usarla) y la probamos de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    # llamamos a la extensión MRI y le pasamos el objeto a inspeccionar&lt;br /&gt;
    mri(ctx)&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def mri(target):&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()    &lt;br /&gt;
    mri = sm.createInstanceWithContext(&amp;#039;mytools.Mri&amp;#039;, ctx)&lt;br /&gt;
    mri.inspect(target)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa en la imágen siguiente, como hemos seleccionado los métodos del objeto y nos lista todos los que tenga, hemos remarcado el que por ahora nos interesa &amp;#039;&amp;#039;&amp;#039;getServiceManager()&amp;#039;&amp;#039;&amp;#039;, observa al final de la línea que efectivamente este método nos devuelve una &amp;#039;&amp;#039;&amp;#039;instancia&amp;#039;&amp;#039;&amp;#039; de la interfaz &amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;. &lt;br /&gt;
[[Image:Py_img_0006.png|none|thumb|500px|Usando la extensión MRI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gran ventaja de usar esta extensión (que por cierto esta hecha en Python), es que siempre te devolverá la información directamente del objeto, a esto se le llama &amp;#039;&amp;#039;&amp;#039;instrospección&amp;#039;&amp;#039;&amp;#039;. Acostumbrate a usarla.&lt;br /&gt;
&lt;br /&gt;
Ahora si, ya podemos crear una instancia de cualquier servicio o interfaz disponible en AOO, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existe una forma alternativa de crear este servicio, usando &amp;#039;&amp;#039;&amp;#039;XSCRIPTCONTEXT&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    XSCRIPTCONTEXT.getDesktop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si vuelves a mirar el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; notaras que usa el mismo método para instanciar este servicio}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y para que sirve este servicio? Entre otras cosas para crear nuevos documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
nuevo = desktop.loadComponentFromURL(&amp;#039;private:factory/scalc&amp;#039;, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos a detalle este método y otros relacionados con los documentos de AOO. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; es la instancia de la administración central para todas las aplicaciones AOO.  Todas las ventanas de la aplicación AOO se organizan en una jerarquía de marcos que contienen componentes visibles.  &lt;br /&gt;
&lt;br /&gt;
[[Image:DesktopOverview.png|none|thumb|400px|Desktop administra los componentes y marcos.]]&lt;br /&gt;
&lt;br /&gt;
Para los fines de crear macros es suficiente que recuerdes que, Desktop es el marco raíz de toda la jerarquía de documentos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para crear la instancia del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; usamos un contexto y usamos el método &amp;#039;&amp;#039;&amp;#039;createInstanceWithContext&amp;#039;&amp;#039;&amp;#039;. Otros servicios no requieren de contexto para ser instanciados y usados, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.util.PathSettings&amp;lt;/idl&amp;gt; que nos sirve para obtener las rutas de trabajo actuales en AOO, para estos casos usamos el método &amp;#039;&amp;#039;&amp;#039;createInstance&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    rutas = sm.createInstance(&amp;#039;com.sun.star.util.PathSettings&amp;#039;)&lt;br /&gt;
    # mostramos la ruta de trabajo del usuario&lt;br /&gt;
    print (rutas.Work)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora que ya sabemos instanciar servicios, veamos de nuevo nuestra macro para mostrar un mensaje en pantalla y analicemosla línea a línea para que veas que sencillo es, además, nos servirá para ver otros detalles al programar con Python en AOO. La macro tiene ahora unos ligeros cambios para que trabaje mejor y para explicar algunas cosas, veamos cuales.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la primer línea &amp;#039;&amp;#039;&amp;#039;declaramos&amp;#039;&amp;#039;&amp;#039; nuestra macro, su nombre y los argumentos que necesita, en este caso solo uno &amp;#039;&amp;#039;&amp;#039;message&amp;#039;&amp;#039;&amp;#039; que será el mensaje a mostrar.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la segunda línea, estamos importando (&amp;#039;&amp;#039;&amp;#039;import&amp;#039;&amp;#039;&amp;#039;) la estructura &amp;#039;&amp;#039;&amp;#039;Rectangle&amp;#039;&amp;#039;&amp;#039; desde (&amp;#039;&amp;#039;&amp;#039;from&amp;#039;&amp;#039;&amp;#039;) el modulo &amp;lt;idl&amp;gt;com.sun.star.awt.module-ix&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Las estructuras son un conjunto de valores relacionados, valores que pueden ser de tipos diferentes, pero que son mostrados como una unidad lógica, por ejemplo, la estructura &amp;lt;idl&amp;gt;com.sun.star.awt.Rectangle&amp;lt;/idl&amp;gt; hace referencia a un área rectangular estableciendo su posición y tamaño, en este caso, solo sirve para cumplir los argumentos del método para mostrar nuestro mensaje.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la tercer línea, hacemos otra importación, pero esta vez la hacemos de una constante, específicamente la constante para mostrar el botón &amp;#039;&amp;#039;&amp;#039;Aceptar&amp;#039;&amp;#039;&amp;#039; (OK), estas constantes las puedes ver aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.MessageBoxButtons&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La cuarta línea esta vacía solo para separar la parte de importacion con el resto del código. En la siguiente línea hacemos una validación del argumento pasado a nuestra macro, si el argumento &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; es una instancia de la clase &amp;#039;&amp;#039;&amp;#039;unicode&amp;#039;&amp;#039;&amp;#039; o de la clase &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, entonces la convertimos a &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, esto nos permite pasar a nuestra macro, listas, tuplas, diccionarios y practicamente cualquier objeto, del cual, podremos ver su representación en texto, muchas veces, con información bastante útil.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea ya la hemos estudiado, creamos una instancia del contexto donde se ejecuta AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea también ya la hemos estudiado, creamos una instancia de la fabrica de servicios, una de las instancias más importantes y que usaras constantemente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la siguiente línea creamos una instancia con contexto de un nuevo servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt;, este servicio sirve, entre otras muchas cosas para crear ventanas y mensaje de texto, como el de nuestra macro.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la penultima línea, usamos el método &amp;#039;&amp;#039;&amp;#039;createMessageBox&amp;#039;&amp;#039;&amp;#039; del servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt; para crear nuestro cuadro de mensaje, todos los argumentos de este método puedes verlo aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.XMessageBoxFactory&amp;lt;/idl&amp;gt;, pero aquí los explicamos uno a uno.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Aunque veas muchas líneas, el interpete la considera una sola, esto se logra al estar todos los argumentos entre paréntesis.&lt;br /&gt;
* El primer argumento es la ventana padre (&amp;#039;&amp;#039;&amp;#039;parent&amp;#039;&amp;#039;&amp;#039;) donde será mostrado el cuadro de mensaje, observa como usamos de nuevo el servicio &amp;#039;&amp;#039;&amp;#039;toolkit&amp;#039;&amp;#039;&amp;#039; para recuperar (&amp;#039;&amp;#039;&amp;#039;getDesktopWindow&amp;#039;&amp;#039;&amp;#039;) la ventana padre de AOO.&lt;br /&gt;
* El segundo argumento es el área rectangular del cuadro de mensaje, observa los dos paréntesis al final del nombre de la estructura, son necesarios para inicializarla.&lt;br /&gt;
* El tercer argumento es el tipo de mensaje, dependiendo de este argumento se muestra el icono correspondiente, los valores permitidos son: &amp;#039;&amp;#039;&amp;#039;infobox, warningbox, errorbox, querybox y messbox&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;infobox&amp;#039;&amp;#039;&amp;#039;, el siguiente argumento es ignorado.&lt;br /&gt;
* El cuarto argumento sirve para mostrar botones de comando diferentes, como: &amp;#039;&amp;#039;&amp;#039;Si, No, Cancelar&amp;#039;&amp;#039;&amp;#039;, etc, que están establecidos en las constantes vistas más arriba.&lt;br /&gt;
* El quinto argumento es el título del cuadro de mensaje.&lt;br /&gt;
* Y por ultimo, el mensaje a mostrar, el cual ya validamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la ultima línea al mismo tiempo que mostramos (&amp;#039;&amp;#039;&amp;#039;ejecute&amp;#039;&amp;#039;&amp;#039;) estamos retornando el cuadro de mensaje, esto nos da la posibilidad de capturar el botón al que le haya dado click el usuario, lo cual, veremos más adelante. Todas las macros retornan un valor, aun y cuando este sea un valor vacío (None).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, los servicio los instanciamos y las estructuras y constantes las importamos, y el punto más importante; &amp;#039;&amp;#039;&amp;#039;acostúmbrate a usar, manejar y dominar, la extensión MRI&amp;#039;&amp;#039;&amp;#039;, ella te dice todo lo necesario para trabajar con los objetos UNO de AOO, los demás, es sencillo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== El documento activo ==&lt;br /&gt;
&lt;br /&gt;
Tenemos dos formas de acceder al documento activo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc1 = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
    doc2 = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc1.getIdentifier())&lt;br /&gt;
    print (doc2.getIdentifier())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note| Mira en el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; la forma en que trabaja el método &amp;#039;&amp;#039;&amp;#039;getDocument&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si seguiste nuestra recomendación de asignar la macro de pruebas a una combinación de teclas disponible en todo AOO, prueba a abrir cada uno de los tipos de documentos que puedes ver en el menú &amp;#039;&amp;#039;&amp;#039;Archivo-&amp;gt;Nuevo-&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
[[Image:Py_img_0007.png|none|thumb|500px|Tipos de documentos en AOO]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y a ejecutar la siguiente macro, teniendo como documento activo cada uno de ellos, es decir, activas uno y ejecutas la macro, activas otro y vuelves a llamar a la macro y así sucesivamente con todos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getIdentifier())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los mensajes devueltos en cada documento, son bastante ilustrativos de que &amp;#039;&amp;#039;&amp;#039;tipo de documento&amp;#039;&amp;#039;&amp;#039; se trata. Pero si probaste con todos, habrás notado que con la base de datos nos devuelve un error, si no lo has probado hazlo ahora. Para resolver este caso tenemos varias posibilidades, la primera es controlar la excepción como ya aprendimos en la introducción a Python.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿estamos realmente seguros que ese es el error?, es mejor especificarlo y asegurarnos de que este es el error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tenemos otra alternativa donde no usamos controlador de excepciónes, si no una función que nos dice si un cierto atributo lo posee o no un objeto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    if hasattr(doc, &amp;#039;getIdentifier&amp;#039;):&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Sin atributo getIdentifier&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es mucho mejor esta segunda opción. Aun así, no podemos estar 100% seguros de que cuando no la tenga, el documento sea una base de datos, simplemente estamos excluyendo la posibilidad pero no lo estamos asegurando, probemos con otra propiedad.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getImplementationName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mucho mejor, ahora ya no tenemos errores, pero si probaste de nuevo con todos los tipos de documentos, habrás notado que con &amp;#039;&amp;#039;&amp;#039;Impres&amp;#039;&amp;#039;&amp;#039; y con &amp;#039;&amp;#039;&amp;#039;Draw&amp;#039;&amp;#039;&amp;#039; obtenemos el mismo resultado, por lo que no tenemos la certeza de que tipo de documento es, por lo que descartamos esta propiedad para nuestra finalidad que es identificar fehacientemente cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
Ya vimos que cada objeto UNO soporta diferentes servicios e interfaces, asì que cada documento de AOO (&amp;#039;&amp;#039;&amp;#039;que son objetos&amp;#039;&amp;#039;&amp;#039;) soportan diferentes servicios, algunos son iguales, es decir, comúnes a todos, pero algunos pueden ser únicos para cada documento. Ya vimos como saber si un documento soporta una propiedad, pero para saber si soporta un servicio completo, cambiamos de método, ahora usamos &amp;#039;&amp;#039;&amp;#039;supportsService&amp;#039;&amp;#039;&amp;#039; que nos devuelve falso o verdadero según soporte o no el nombre del servicio pasado como argumento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    res = doc.supportsService(&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;)&lt;br /&gt;
    mensaje = u&amp;#039;No soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    if res:&lt;br /&gt;
        mensaje = u&amp;#039;Soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    print(mensaje)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y mejor aun, podemos saber todos los servicios que soporta un objeto con el método &amp;#039;&amp;#039;&amp;#039;getSupportedServiceNames&amp;#039;&amp;#039;&amp;#039; que nos devuelve una tupla con todos sus nombres.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    servicios = doc.getSupportedServiceNames()&lt;br /&gt;
    &lt;br /&gt;
    print(servicios)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Te queda de tarea probar esta macro en cada uno de los documentos abiertos, incluso puedes probar también el IDE para AOOBasic que incorpora AOO y determinar que servicio usar para diferenciar sin duda cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
== Los documentos abiertos ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todos los documentos abiertos en la sesión de AOO, usamos el método &amp;#039;&amp;#039;&amp;#039;getComponents&amp;#039;&amp;#039;&amp;#039; del objeto &amp;#039;&amp;#039;&amp;#039;Desktop&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;MRI&amp;#039;&amp;#039;&amp;#039;, notarás que este método nos devuelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta interfaz (&amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;) tiene un solo método llamado &amp;#039;&amp;#039;&amp;#039;createEnumeration&amp;#039;&amp;#039;&amp;#039; que nos duelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumeration&amp;lt;/idl&amp;gt; la cual a su vez tiene solo dos métodos, el primero para saber si tenemos más elementos en la enumeración: &amp;#039;&amp;#039;&amp;#039;hasMoreElements&amp;#039;&amp;#039;&amp;#039; y el segundo para acceder al siguiente elemento &amp;#039;&amp;#039;&amp;#039;nextElement&amp;#039;&amp;#039;&amp;#039;, veamoslo con un ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    # mientras tengamos elementos&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        # obtenemos el siguiente elemento&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # mostrámos el tipo de documento&lt;br /&gt;
        mensaje = obtener_tipo(doc)&lt;br /&gt;
        print(mensaje)&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;Calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;Writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;Impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;Draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;Base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;Math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;Basic&amp;#039;}&lt;br /&gt;
    # iteramos entre los tipos de documentos&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        # validamos si soporta el servicio&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            # devolvemos el tipo de documento&lt;br /&gt;
            return &amp;#039;Soy %s&amp;#039; % tipo[t]&lt;br /&gt;
    # si termina sin encontrar un tipo&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como usamos una macro de apoyo para saber que tipo de documento es. Una enumeración no es más que una lista de objetos y es una forma muy común y a veces la única de acceder a ciertos objetos en AOO, es importante que la recuerdes.&lt;br /&gt;
&lt;br /&gt;
== Rutas de archivos y directorios ==&lt;br /&gt;
&lt;br /&gt;
Apache OpenOffice, al ser multiplataforma, hace uso de las rutas de archivos y directorios, en el formato URL, por ejemplo.&lt;br /&gt;
&lt;br /&gt;
file:///home/usuario/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
file:///d:/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta que este formato hace uso de los caracteres 0-9, a-z y A-Z, y cualquier otro carácter será convertido y mostrado con su respectivo código, por ejemplo, los espacios los reemplazara con &amp;#039;&amp;#039;&amp;#039;%20&amp;#039;&amp;#039;&amp;#039;. Siempre que le pases una ruta de archivo a cualquier servicio de AOO, hazlo, casi como una regla, pasarle la ruta en formato Url, para ello, la libreria &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; cuenta con dos funciones muy útiles que hacen el trabajo &amp;#039;&amp;#039;&amp;#039;systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; y &amp;#039;&amp;#039;&amp;#039;fileUrlToSystemPath&amp;#039;&amp;#039;&amp;#039;, veamos como se usan.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def rutas():&lt;br /&gt;
    &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi archivo de Calc.ods&amp;quot;&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # La convertimos al formato URL&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # Regresamos al formato local&lt;br /&gt;
    ruta = uno.fileUrlToSystemPath(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Abre varios documentos existentes y ejecuta la siguiente macro desde cada uno:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def info_ruta():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
    &lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    # obtenemos la ruta en disco&lt;br /&gt;
    ruta =  doc.getURL()&lt;br /&gt;
    # obtenemos las diferentes partes de la ruta&lt;br /&gt;
    ruta, archivo = os.path.split(ruta)&lt;br /&gt;
    nombre, extension = os.path.splitext(archivo)&lt;br /&gt;
    &lt;br /&gt;
    print (ruta)&lt;br /&gt;
    print (uno.fileUrlToSystemPath(ruta))&lt;br /&gt;
    print (archivo)&lt;br /&gt;
    print (nombre)&lt;br /&gt;
    print (extension)&lt;br /&gt;
    &lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hemos importado una nueva librería de Python, &amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; que entre otras muchas cosas, nos permite obtener información de las rutas de archivos como en la macro anterior.&lt;br /&gt;
&lt;br /&gt;
En nuestros siguientes temas, veremos la importancia de usar las rutas de archivos y directorios en formato Url y recuerda que en S.O. Linux, se tiene en cuenta la diferencia entre mayúsculas y minúsculas.&lt;br /&gt;
&lt;br /&gt;
== Creando nuevos documentos ==&lt;br /&gt;
&lt;br /&gt;
El método que nos permite crear nuevos documentos se llama &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039; y es un método del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, por ejemplo, para crear una nueva hoja de calculo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo hay que hacer un pequeño cambio para crear un nuevo documento de texto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y los demás tipos de documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/simpress&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/sdraw&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/smath&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y una base de datos?, probemos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/sbase&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos da un error ¿verdad?&lt;br /&gt;
[[Image:Py_img_0008.png|none|thumb|500px|Error al crear base de datos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No esta soportado. Para saber por que nos da un error, intenta abrir una base de datos nueva, observa como primero, si queremos trabajar con ella, el asistente nos “obliga” primero a guardarla con un nombre y después ya podemos manipularla, esto, solo pasa con las bases de datos, de los demás documentos podemos crear tantos nuevos documentos como queramos sin tener que guardar nada, entonces ¿como creamos una nueva base de datos?, la respuesta es sencilla, del mismo modo que lo hacemos desde la interfaz de usuario, es decir, tenemos que guardar primero la base de datos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
 &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi_Base_Datos.odb&amp;quot;&lt;br /&gt;
    # Creamos el servicio que nos permite manipular bases de datos&lt;br /&gt;
    dbcon = sm.createInstance(&amp;#039;com.sun.star.sdb.DatabaseContext&amp;#039;)&lt;br /&gt;
    # creamos una instancia de una nueva base de datos&lt;br /&gt;
    base = dbcon.createInstance()&lt;br /&gt;
    # establecemos el tipo de base&lt;br /&gt;
    base.URL = &amp;quot;sdbc:embedded:hsqldb&amp;quot;&lt;br /&gt;
    # y la guardamos&lt;br /&gt;
    base.DatabaseDocument.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta dos cosas muy importantes en la macro anterior, el nombre que uses, si ya existe, simplemente lo reemplazara, no te preguntara nada, así que ten cuidado de no usar una ruta o nombre de una base importante que tengas y segundo, la base de datos así creada, no quedara “registrada” en AOO, con lo que no tendrás acceso desde otros programas de la aplicación, más adelante veremos como registrar una base de datos por código.&lt;br /&gt;
&lt;br /&gt;
== Abriendo, guardando y cerrando documentos ==&lt;br /&gt;
Abrir archivos existentes es sumamente sencillo, usamos el mismo método usado&lt;br /&gt;
para crear nuevos documentos &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, pero en el parámetro ruta, le especificamos la ubicación del archivo a abrir de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def documento1():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si tus archivos existen (esto se puede validar), el código anterior los abrirá, &amp;#039;&amp;#039;&amp;#039;siempre&amp;#039;&amp;#039;&amp;#039; utiliza&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;uno.systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; cuando uses rutas de archivos o directorios en&lt;br /&gt;
funciones de AOO que las requieran como argumentos. Ya vimos que el primer&lt;br /&gt;
agumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, es la ruta del archivo a&lt;br /&gt;
abrir, el segundo argumento es una cadena con el nombre del macro (frame)&lt;br /&gt;
donde será mostrado el documento abierto, generalmente si existe este frame se&lt;br /&gt;
usa si no se crea uno nuevo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_cal&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_writer&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existen nombre especiales para este agumento, los más usuales son dos, primero&lt;br /&gt;
que ya hemos estado usando &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; que usa el frame actual y&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039; que siempre crea un nuevo frame.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La recomendación es que uses siempre &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; o &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, un&lt;br /&gt;
escenario puede ser que habrás con &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; una instancia, y después de&lt;br /&gt;
forma oculta uno nuevo con &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, más abajo vemos como abrir un&lt;br /&gt;
documento de forma oculta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si abres una plantilla, esta se comportará de forma normal, es decir, te abrirá una copia de dicha plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_plantilla.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero también podrías querer abrir la plantilla para editarla, en este caso,&lt;br /&gt;
le indicamos en las opciones de apertura esta opción, y aquí vemos como usar&lt;br /&gt;
el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como hemos importado una nueva estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como la instanciamos y asignamos sus valores.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Muy importante, el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
espera una tupla, por eso es que usamos la coma al final del nombre del&lt;br /&gt;
argumento &amp;#039;&amp;#039;&amp;#039;(opciones,)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt; esta conformada por&lt;br /&gt;
un par de valores, un nombre y un valor y es muy frecuentemente usada cuando se&lt;br /&gt;
programa en AOO, para este ejemplo solo hemos usado un par de agumentos,&lt;br /&gt;
siempre van en pares, pero muy bien puede tener más opciones como veremos más&lt;br /&gt;
adelante. En la macro anterior le estamos indicando la propiedad&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (que seria algo así como Es Plantilla), si el valor es&lt;br /&gt;
falso (False), le estamos indicando que queremos abrir la plantilla para&lt;br /&gt;
editarla, en caso contrario (True) abrirá una copia de la plantilla. Lo&lt;br /&gt;
interesante de esta propiedad es que perfectamente la puedes aplicar a archivos&lt;br /&gt;
existentes, es decir, archivos que &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; necesariamente sean plantillas, con&lt;br /&gt;
esta propiedad podemos forzarlos a comportarse como plantillas, por ejemplo, prueba el siguiente código con algún archivo existente que no sea plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como el archivo es un documento de texto normal (ODT), pero con la&lt;br /&gt;
propiedad &amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;, forzamos su apertura como una plantilla.&lt;br /&gt;
&lt;br /&gt;
Otras propiedades interesantes son &amp;#039;&amp;#039;&amp;#039;ReadOnly&amp;#039;&amp;#039;&amp;#039; (Solo Lectura) para abrir un&lt;br /&gt;
archivo como solo lectura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y &amp;#039;&amp;#039;&amp;#039;Password&amp;#039;&amp;#039;&amp;#039; (Contraseña) para abrir archivos con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto puedes combinar cualquier cantidad de opciones siempre y cuando no&lt;br /&gt;
entren en conflicto, es importante que al final, sea una tupla lo que le pasas&lt;br /&gt;
al método, si no, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # creamos una lista vacía&lt;br /&gt;
    opciones = []&lt;br /&gt;
    # creamos la primer propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opcion.Value = True&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
    # creamos la segunda propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opcion.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    # nota que la lista la convertimos en tupla&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, tuple(opciones))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si la contraseña es incorrecta, no obtendrás ningún mensaje, simplemente no&lt;br /&gt;
lo abrira y la variable &amp;#039;&amp;#039;&amp;#039;doc&amp;#039;&amp;#039;&amp;#039; será vacía, puedes validar esto:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if doc is None:&lt;br /&gt;
        print (&amp;#039;No se abrio el documento&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos otras formas de validar y depurar nuestras macros para&lt;br /&gt;
los dificiles casos en donde no obtengamos ningún mensaje de error, pero&lt;br /&gt;
simplemente nuestra macro se niega a hacer su trabajo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mientras un formato de archivo sea soportado por AOO, lo podrás abrir con el&lt;br /&gt;
método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, en el siguiente ejemplo, abrimos un archivo tipo Doc, un Html y un Xls.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_web.html&amp;#039;)&lt;br /&gt;
    doc_h = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_excel.xls&amp;#039;)&lt;br /&gt;
    doc_x = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Qué otras opciones tengo para abrir archivos?. La mayoría están descritas&lt;br /&gt;
en el servicio &amp;lt;idl&amp;gt;com.sun.star.document.MediaDescriptor&amp;lt;/idl&amp;gt;, aquí veremos&lt;br /&gt;
las más usadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cuando abres un archivo por código y este contiene macros, tu puedes&lt;br /&gt;
establecer si se abre con las macros activadas, de forma predeterminada lo abre&lt;br /&gt;
con las macros desactivadas, así que solo nos resta saber como abrirlo con las&lt;br /&gt;
macros activadas, las constanes que puedes usar puedes verlas aquí&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.document.MacroExecMode&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.document.MacroExecMode import ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;MacroExecutionMode&amp;#039;&lt;br /&gt;
    opciones.Value = ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Otra opción interesante, es la que nos permite abrir una presentación e iniciarla inmediatamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;StartPresentation&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_impress.odp&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes abrir un archivo como vista previa, útil para evitar que el usuario haga cambios en el, en este estado, los cambios que intente hacer el usuario no se guardaran.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Preview&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, la idea general de abrir un archivo es para obtener datos de el o para manipularlo, ya sea un documento nuevo o uno existente, veamos como guardar los cambios realizados y cerrar el archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    # aquí va todo el código que quieras para manipular el archivo&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto correctamente, presiona Aceptar para gaurdarlo y cerrarlo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # guardamos los cambios&lt;br /&gt;
    doc.store()&lt;br /&gt;
    # cerramos el archivo&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El código anterior funcionara con un archivo existente, pero con uno nuevo no,&lt;br /&gt;
te dará un error, por supuesto no me creas, compruébalo. Los documentos&lt;br /&gt;
tienen un método (&amp;#039;&amp;#039;&amp;#039;hasLocation&amp;#039;&amp;#039;&amp;#039;) que nos informa si un documento ya esta guardado o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
    &lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El primer mensaje debe mostrarte falso (False) porque es un documento nuevo y&lt;br /&gt;
el segundo verdadero (True) por ser un archivo abierto del disco.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También tenemos una propiedad que nos ayuda a saber si un documento ha sido modificado o no, ejecuta la siguiente macro, llamándola desde diferentes documentos, unos ábrelos y modifícalos antes de ejecutarla, otros, solo ábrelos y ejecútala para que notes la diferencia.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def esta_modificado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
 &lt;br /&gt;
    msgbox(doc.isModified())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y otra más que nos informa si el documento es de solo lectura (&amp;#039;&amp;#039;&amp;#039;isReadonly&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que valides antes de intentar guardar un archivo, si este ha sido&lt;br /&gt;
modificado o es de solo lectura. Ahora veamos como guardar un archivo nuevo con el método &amp;#039;&amp;#039;&amp;#039;storeAsUrl&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como requiere dos parámetros, la ruta del archivo y una matriz de&lt;br /&gt;
propiedades, algunas de las cuales veremos a continuación. Toma nota de que si&lt;br /&gt;
el archivo ya existe lo reemplazara sin avisarte por lo que es buena practica&lt;br /&gt;
de programación validar esto, observa como volvemos a usar la librería&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; para saber si un archivo existe ya.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    documentos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def documentos():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;&lt;br /&gt;
    if os.path.exists(ruta):&lt;br /&gt;
        msgbox(u&amp;#039;El archivo existe, no se guardará el nuevo&amp;#039;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
De la macro anterior, &amp;#039;&amp;#039;&amp;#039;es muy importante&amp;#039;&amp;#039;&amp;#039; que tomes nota que para todos&lt;br /&gt;
los métodos de Python que usen rutas de archivos o directorios, se les tienen&lt;br /&gt;
que pasar en las rutas nativas del sistema operativo donde estes trabajando,&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;solo&amp;#039;&amp;#039;&amp;#039; a los métodos de AOO, es a los que se les pasa en notación URL.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Veamos algunas propiedades interesantes para guardar archivos, por ejemplo, guardar con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo pero con contraseña&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_protegido.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como sabes, AOO, soporta la importación/exportación de múltiples formatos de archivos, veamos como guardar, por ejemplo, en formato DOC.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo en formato DOC&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;MS Word 97&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que cuando exportes, uses un formato compatible, es decir, no&lt;br /&gt;
puedes guardar una hoja de calculo como documento de texto. En el [[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices|Apéndice]]&lt;br /&gt;
mostramos una macro para obtener todos los filtros que soporta AOO.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El método storeAsURL también lo puedes usar para abrir un archivo existente y guardarlo con otro nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos con otro nombre&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc_nuevo.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para terminar esta sección, vamos a hacer un poco más interactiva la apertura&lt;br /&gt;
y guardado de archivos, permitamos que el usuario escoja la ruta y el archivo&lt;br /&gt;
desde un cuadro de dialogo, para ello, usaremos el servicio&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt;, que nos permite hacer esto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    # podemos establecer el título&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        # el primer elemento es la ruta seleccionada&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si estableces la propiedad &amp;#039;&amp;#039;&amp;#039;MultiSelectionMode&amp;#039;&amp;#039;&amp;#039; en verdadero, le&lt;br /&gt;
permitiras al usuario seleccionar más de un archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    dlg.setMultiSelectionMode(True)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        archivos = dlg.getFiles()&lt;br /&gt;
        if len(archivos) == 1:&lt;br /&gt;
            # si selecciona uno, devuelve la ruta completa&lt;br /&gt;
            desktop.loadComponentFromURL(archivos[0], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
        else:&lt;br /&gt;
            # si selecciona varios, el primer elemento es la carpeta&lt;br /&gt;
            folder = archivos[0]&lt;br /&gt;
            # los demás elementos son los archivos seleccionados&lt;br /&gt;
            for f in range(1, len(archivos)):&lt;br /&gt;
                desktop.loadComponentFromURL(folder + archivos[f], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si lo notaste, con la macro anterior el usuario puede seleccionar cualquier&lt;br /&gt;
archivo, para limitar las opciones, agrega un filtro con el método&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;appendFilter&amp;#039;&amp;#039;&amp;#039; con solo los tipos de&lt;br /&gt;
archivos que necesites, usa una línea por cada filtro, este método requiere&lt;br /&gt;
dos argumentos, el primero es el título, lo que verá el usuario y el segundo&lt;br /&gt;
es el filtro en si.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, mostramos el cuadro de dialogo Guardar Como, para permitir al usuario&lt;br /&gt;
seleccionar carpeta y nombre de archivo donde guardar su archivo, se usa el&lt;br /&gt;
mismo servicio &amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt; solo cambiando&lt;br /&gt;
algunas de sus propiedades.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_AUTOEXTENSION_PASSWORD&lt;br /&gt;
    &lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Guardar archivo&amp;#039;)&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
    # con esta opción le indicamos que use guardar como con otras opciones&lt;br /&gt;
    dlg.initialize((FILESAVE_AUTOEXTENSION_PASSWORD,))&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        msgbox(ruta)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota que el argumento del método &amp;#039;&amp;#039;&amp;#039;initialize&amp;#039;&amp;#039;&amp;#039; es una tupla.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, para terminar, te mostramos como abrir un archivo de forma oculta.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo cerraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.store()&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es &amp;#039;&amp;#039;&amp;#039;muy importante&amp;#039;&amp;#039;&amp;#039;, que cuando abras un archivo oculto siempre uses el argumento &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, a menos claro esta, que sepas lo que haces, y que, mantengas una referencia a el, para poder cerrarlo en cuanto no lo necesites.&lt;br /&gt;
&lt;br /&gt;
== Algunas tareas comunes en documentos ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exportando a PDF ===&lt;br /&gt;
&lt;br /&gt;
Para exportar a PDF solo hay que establecer el filtro correcto, nota como construimos el nombre del filtro de acuerdo al tipo de documento y como construimos la ruta de acuerdo a la ruta actual donde este guardado el documento solo reemplazando la extensión para que quede en PDF. Estamos haciendo uso de la macro &amp;#039;&amp;#039;&amp;#039;obtener_tipo&amp;#039;&amp;#039;&amp;#039; con unos ligeros cambios para este propósito.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    export_pdf()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def export_pdf():&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    tipo = obtener_tipo(doc)&lt;br /&gt;
    soportados = &amp;#039;calc,writer,draw,impress,math&amp;#039;&lt;br /&gt;
    if tipo in soportados:&lt;br /&gt;
        # establecemos el filtro como PDF&lt;br /&gt;
        opciones = PropertyValue()&lt;br /&gt;
        opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
        opciones.Value = &amp;#039;%s_pdf_Export&amp;#039; % tipo&lt;br /&gt;
        # obtenemos la ruta y reemplazados la extensión por PDF&lt;br /&gt;
        ruta, archivo = os.path.split(doc.getURL())&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
        ruta = os.path.join(ruta, nombre + &amp;#039;.pdf&amp;#039;)&lt;br /&gt;
        # guardamos&lt;br /&gt;
        doc.storeToURL(ruta, (opciones,))&lt;br /&gt;
        msgbox(u&amp;#039;Documento exportado correctamente a PDF&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;Aplicación no soportada&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;basic&amp;#039;}&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            return tipo[t]&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La forma de descomponer la ruta en sus diferentes partes, ya la vimos anteriormente, en este caso, observa como la extensión actual del documento ya no la usaremos por lo que la omitimos con un guión bajo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ocultando y mostrando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para ocultar una ventana, hay que acceder a la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # y la ocultamos&lt;br /&gt;
        ventana.setVisible(False)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Se han ocultado todas las ventanas, presiona Aceptar para mostrarlas&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # tienes que crear de nuevo la enumeración&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # ahora las mostramos&lt;br /&gt;
        ventana.setVisible(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta técnica la puedes usar también para mostrar un archivo que abriste de forma oculta previamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo mostraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    ventana.setVisible(True)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo visible, ahora lo cerramos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Activando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para usamos el método &amp;#039;&amp;#039;&amp;#039;setFocus&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # esperamos 3 segundos y mostramos la ventana&lt;br /&gt;
        time.sleep(3)&lt;br /&gt;
        ventana.setFocus()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Controlando la barra de estado ===&lt;br /&gt;
&lt;br /&gt;
La barra de estado, generalmente en la parte inferior de las aplicaciones, es útil para dar información al usuario, generalmente de un proceso en progreso.&lt;br /&gt;
&amp;lt;source lang=pyhton&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def barra_estado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    barra = doc.getCurrentController().getStatusIndicator()&lt;br /&gt;
    barra.start(u&amp;#039;Se procesaran líneas en tres segundos&amp;#039;, 10)&lt;br /&gt;
    # esta pausa es solo para que veas el mensaje anterior en la barra de estado&lt;br /&gt;
    time.sleep(3)&lt;br /&gt;
    for i in range(1, 11):&lt;br /&gt;
        barra.setValue(i)&lt;br /&gt;
        barra.setText(u&amp;#039;Procesando línea: %s&amp;#039; % i)&lt;br /&gt;
        # pausa de un segundo&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
    # importante para regresar el control a la aplicación&lt;br /&gt;
    barra.end()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218394</id>
		<title>ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonAOO&amp;diff=218394"/>
		<updated>2013-04-28T19:19:30Z</updated>

		<summary type="html">&lt;p&gt;Mauriciobaeza: /* Activando ventanas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Trabajando con Apache OpenOffice}}&lt;br /&gt;
&lt;br /&gt;
== Conceptos iniciales==&lt;br /&gt;
&lt;br /&gt;
Este es el tema más importante para crear macros, de forma sencilla, pero se ven las bases para trabajar con todo AOO, por eso es importante no avanzar en estas notas, sin antes haber comprendido a cabalidad los temas presentes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;UNO&amp;#039;&amp;#039;&amp;#039; (Universal Network Objects), es la especificación que da acceso a todos los objetos de Apache OpenOffice. Todo lo que quieras saber de esta especificación, lo puedes encontrar en la [[http://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide Guía del desarrollador]] (en ingles).&lt;br /&gt;
&lt;br /&gt;
El &amp;#039;&amp;#039;&amp;#039;API&amp;#039;&amp;#039;&amp;#039; (Application Programer Interface) de Apache OpenOffice proporciona el acceso a toda la funcionalidad de AOO, independientemente del lenguaje. Todo el API de AOO esta en &amp;lt;idl&amp;gt;com.sun.star.module-ix&amp;lt;/idl&amp;gt; (solo ingles).&lt;br /&gt;
&lt;br /&gt;
La comunicación entre objetos UNO se basa en &amp;#039;&amp;#039;&amp;#039;interfaces&amp;#039;&amp;#039;&amp;#039; de objeto.  Las interfaces pueden ser vistos desde el exterior o el interior de un objeto y proporcionan formas de ver o manipular el objeto.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;servicios&amp;#039;&amp;#039;&amp;#039; son agrupaciones lógicas de interfaces, son la forma en que un mismo objeto pueda ofrecer la funcionalidad de varias interfaces.&lt;br /&gt;
&lt;br /&gt;
Los servicios se pueden implementar en librerías compartidas llamadas &amp;#039;&amp;#039;&amp;#039;componentes UNO&amp;#039;&amp;#039;&amp;#039;, con Python podemos crear componentes nuevos y generalmente el usuario final las recibe como una extensión OXT.&lt;br /&gt;
&lt;br /&gt;
Los &amp;#039;&amp;#039;&amp;#039;modulos&amp;#039;&amp;#039;&amp;#039; pueden agrupar submodulos, servicios, excepciones, constantes, enumeraciones, etc, se utilizan para especificar bloques coherentes en la API, esto permite tener un API bien estructurada.&lt;br /&gt;
&lt;br /&gt;
== Creando servicios ==&lt;br /&gt;
Para crear un servicio, usamos la &amp;#039;&amp;#039;&amp;#039;fabrica de servicios&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;), una interfaz especial para crear nuevos servicios, pero para llegar a ella, tenemos que hacerlo a traves de la interfaz &amp;#039;&amp;#039;&amp;#039;ComponentContext&amp;#039;&amp;#039;&amp;#039; (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;), como puedes verlo en la siguiente imagen. &lt;br /&gt;
[[Image:UseServices1.png|none|thumb|400px|ComponentContext y ServiceManager]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En pyUNO tenemos dos formas de acceder a esta interfaz, las dos son equivalentes por lo que puedes usar la que prefieras. En la introducción a Python se mencionó que la mayoría de sus herramientas están disponibles en librerias, estás librerias tienen que importarse &amp;#039;&amp;#039;&amp;#039;antes&amp;#039;&amp;#039;&amp;#039; de poder usarse, en nuestro caso importaremos la librería &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; que nos da acceso (entre otras cosas) al contexto de ejecución de AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx1 = XSCRIPTCONTEXT.getComponentContext()&lt;br /&gt;
    ctx2 = uno.getComponentContext()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si te gusta investigar, busca el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; en la carpeta de instalación de AOO, ahí puedes ver de donde sale XSCRIPTCONTEXT}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, podemos acceder a la fábrica de servicios con el &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿como sabemos que este &amp;#039;&amp;#039;&amp;#039;objeto (ComponentContext)&amp;#039;&amp;#039;&amp;#039; tiene este &amp;#039;&amp;#039;&amp;#039;método getServiceManager()&amp;#039;&amp;#039;&amp;#039;? porque lo estamos demostrando, si, también por eso, pero también porque puedes ver su documentación (&amp;lt;idl&amp;gt;com.sun.star.uno.XComponentContext&amp;lt;/idl&amp;gt;) en el API de AOO, pero más importante aún, porque podemos hacer que el mismo objeto te diga todo lo que sabe hacer. Para ello haremos uso de una magnifica extensión que te tiene que acompañar el resto de tus días como programador de macros Python, nos referimos a [http://extensions.services.openoffice.org/project/MRI MRI]. Instala (tal vez tengas que reiniciar AOO para poder usarla) y la probamos de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    # llamamos a la extensión MRI y le pasamos el objeto a inspeccionar&lt;br /&gt;
    mri(ctx)&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def mri(target):&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()    &lt;br /&gt;
    mri = sm.createInstanceWithContext(&amp;#039;mytools.Mri&amp;#039;, ctx)&lt;br /&gt;
    mri.inspect(target)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa en la imágen siguiente, como hemos seleccionado los métodos del objeto y nos lista todos los que tenga, hemos remarcado el que por ahora nos interesa &amp;#039;&amp;#039;&amp;#039;getServiceManager()&amp;#039;&amp;#039;&amp;#039;, observa al final de la línea que efectivamente este método nos devuelve una &amp;#039;&amp;#039;&amp;#039;instancia&amp;#039;&amp;#039;&amp;#039; de la interfaz &amp;lt;idl&amp;gt;com.sun.star.lang.XMultiComponentFactory&amp;lt;/idl&amp;gt;. &lt;br /&gt;
[[Image:Py_img_0006.png|none|thumb|500px|Usando la extensión MRI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La gran ventaja de usar esta extensión (que por cierto esta hecha en Python), es que siempre te devolverá la información directamente del objeto, a esto se le llama &amp;#039;&amp;#039;&amp;#039;instrospección&amp;#039;&amp;#039;&amp;#039;. Acostumbrate a usarla.&lt;br /&gt;
&lt;br /&gt;
Ahora si, ya podemos crear una instancia de cualquier servicio o interfaz disponible en AOO, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existe una forma alternativa de crear este servicio, usando &amp;#039;&amp;#039;&amp;#039;XSCRIPTCONTEXT&amp;#039;&amp;#039;&amp;#039; de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    XSCRIPTCONTEXT.getDesktop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Documentation/Note| Si vuelves a mirar el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; notaras que usa el mismo método para instanciar este servicio}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y para que sirve este servicio? Entre otras cosas para crear nuevos documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
nuevo = desktop.loadComponentFromURL(&amp;#039;private:factory/scalc&amp;#039;, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos a detalle este método y otros relacionados con los documentos de AOO. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; es la instancia de la administración central para todas las aplicaciones AOO.  Todas las ventanas de la aplicación AOO se organizan en una jerarquía de marcos que contienen componentes visibles.  &lt;br /&gt;
&lt;br /&gt;
[[Image:DesktopOverview.png|none|thumb|400px|Desktop administra los componentes y marcos.]]&lt;br /&gt;
&lt;br /&gt;
Para los fines de crear macros es suficiente que recuerdes que, Desktop es el marco raíz de toda la jerarquía de documentos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para crear la instancia del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.Desktop&amp;lt;/idl&amp;gt; usamos un contexto y usamos el método &amp;#039;&amp;#039;&amp;#039;createInstanceWithContext&amp;#039;&amp;#039;&amp;#039;. Otros servicios no requieren de contexto para ser instanciados y usados, por ejemplo, el servicio &amp;lt;idl&amp;gt;com.sun.star.util.PathSettings&amp;lt;/idl&amp;gt; que nos sirve para obtener las rutas de trabajo actuales en AOO, para estos casos usamos el método &amp;#039;&amp;#039;&amp;#039;createInstance&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    rutas = sm.createInstance(&amp;#039;com.sun.star.util.PathSettings&amp;#039;)&lt;br /&gt;
    # mostramos la ruta de trabajo del usuario&lt;br /&gt;
    print (rutas.Work)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora que ya sabemos instanciar servicios, veamos de nuevo nuestra macro para mostrar un mensaje en pantalla y analicemosla línea a línea para que veas que sencillo es, además, nos servirá para ver otros detalles al programar con Python en AOO. La macro tiene ahora unos ligeros cambios para que trabaje mejor y para explicar algunas cosas, veamos cuales.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la primer línea &amp;#039;&amp;#039;&amp;#039;declaramos&amp;#039;&amp;#039;&amp;#039; nuestra macro, su nombre y los argumentos que necesita, en este caso solo uno &amp;#039;&amp;#039;&amp;#039;message&amp;#039;&amp;#039;&amp;#039; que será el mensaje a mostrar.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def msgbox(message):&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la segunda línea, estamos importando (&amp;#039;&amp;#039;&amp;#039;import&amp;#039;&amp;#039;&amp;#039;) la estructura &amp;#039;&amp;#039;&amp;#039;Rectangle&amp;#039;&amp;#039;&amp;#039; desde (&amp;#039;&amp;#039;&amp;#039;from&amp;#039;&amp;#039;&amp;#039;) el modulo &amp;lt;idl&amp;gt;com.sun.star.awt.module-ix&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt import Rectangle&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Las estructuras son un conjunto de valores relacionados, valores que pueden ser de tipos diferentes, pero que son mostrados como una unidad lógica, por ejemplo, la estructura &amp;lt;idl&amp;gt;com.sun.star.awt.Rectangle&amp;lt;/idl&amp;gt; hace referencia a un área rectangular estableciendo su posición y tamaño, en este caso, solo sirve para cumplir los argumentos del método para mostrar nuestro mensaje.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la tercer línea, hacemos otra importación, pero esta vez la hacemos de una constante, específicamente la constante para mostrar el botón &amp;#039;&amp;#039;&amp;#039;Aceptar&amp;#039;&amp;#039;&amp;#039; (OK), estas constantes las puedes ver aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.MessageBoxButtons&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La cuarta línea esta vacía solo para separar la parte de importacion con el resto del código. En la siguiente línea hacemos una validación del argumento pasado a nuestra macro, si el argumento &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; es una instancia de la clase &amp;#039;&amp;#039;&amp;#039;unicode&amp;#039;&amp;#039;&amp;#039; o de la clase &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, entonces la convertimos a &amp;#039;&amp;#039;&amp;#039;str&amp;#039;&amp;#039;&amp;#039;, esto nos permite pasar a nuestra macro, listas, tuplas, diccionarios y practicamente cualquier objeto, del cual, podremos ver su representación en texto, muchas veces, con información bastante útil.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if not isinstance(message, (unicode, str)):&lt;br /&gt;
        message = str(message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea ya la hemos estudiado, creamos una instancia del contexto donde se ejecuta AOO.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La siguiente línea también ya la hemos estudiado, creamos una instancia de la fabrica de servicios, una de las instancias más importantes y que usaras constantemente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la siguiente línea creamos una instancia con contexto de un nuevo servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt;, este servicio sirve, entre otras muchas cosas para crear ventanas y mensaje de texto, como el de nuestra macro.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    toolkit = sm.createInstanceWithContext(&amp;#039;com.sun.star.awt.Toolkit&amp;#039;, ctx)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la penultima línea, usamos el método &amp;#039;&amp;#039;&amp;#039;createMessageBox&amp;#039;&amp;#039;&amp;#039; del servicio &amp;lt;idl&amp;gt;com.sun.star.awt.Toolkit&amp;lt;/idl&amp;gt; para crear nuestro cuadro de mensaje, todos los argumentos de este método puedes verlo aquí: &amp;lt;idl&amp;gt;com.sun.star.awt.XMessageBoxFactory&amp;lt;/idl&amp;gt;, pero aquí los explicamos uno a uno.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    MsgBox = toolkit.createMessageBox(&lt;br /&gt;
                                    toolkit.getDesktopWindow(),&lt;br /&gt;
                                    Rectangle(),&lt;br /&gt;
                                    &amp;#039;infobox&amp;#039;,&lt;br /&gt;
                                    BUTTONS_OK,&lt;br /&gt;
                                    &amp;#039;pyUNO&amp;#039;,&lt;br /&gt;
                                    message)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Aunque veas muchas líneas, el interpete la considera una sola, esto se logra al estar todos los argumentos entre paréntesis.&lt;br /&gt;
* El primer argumento es la ventana padre (&amp;#039;&amp;#039;&amp;#039;parent&amp;#039;&amp;#039;&amp;#039;) donde será mostrado el cuadro de mensaje, observa como usamos de nuevo el servicio &amp;#039;&amp;#039;&amp;#039;toolkit&amp;#039;&amp;#039;&amp;#039; para recuperar (&amp;#039;&amp;#039;&amp;#039;getDesktopWindow&amp;#039;&amp;#039;&amp;#039;) la ventana padre de AOO.&lt;br /&gt;
* El segundo argumento es el área rectangular del cuadro de mensaje, observa los dos paréntesis al final del nombre de la estructura, son necesarios para inicializarla.&lt;br /&gt;
* El tercer argumento es el tipo de mensaje, dependiendo de este argumento se muestra el icono correspondiente, los valores permitidos son: &amp;#039;&amp;#039;&amp;#039;infobox, warningbox, errorbox, querybox y messbox&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;infobox&amp;#039;&amp;#039;&amp;#039;, el siguiente argumento es ignorado.&lt;br /&gt;
* El cuarto argumento sirve para mostrar botones de comando diferentes, como: &amp;#039;&amp;#039;&amp;#039;Si, No, Cancelar&amp;#039;&amp;#039;&amp;#039;, etc, que están establecidos en las constantes vistas más arriba.&lt;br /&gt;
* El quinto argumento es el título del cuadro de mensaje.&lt;br /&gt;
* Y por ultimo, el mensaje a mostrar, el cual ya validamos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En la ultima línea al mismo tiempo que mostramos (&amp;#039;&amp;#039;&amp;#039;ejecute&amp;#039;&amp;#039;&amp;#039;) estamos retornando el cuadro de mensaje, esto nos da la posibilidad de capturar el botón al que le haya dado click el usuario, lo cual, veremos más adelante. Todas las macros retornan un valor, aun y cuando este sea un valor vacío (None).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    return MsgBox.execute()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resumiendo, los servicio los instanciamos y las estructuras y constantes las importamos, y el punto más importante; &amp;#039;&amp;#039;&amp;#039;acostúmbrate a usar, manejar y dominar, la extensión MRI&amp;#039;&amp;#039;&amp;#039;, ella te dice todo lo necesario para trabajar con los objetos UNO de AOO, los demás, es sencillo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== El documento activo ==&lt;br /&gt;
&lt;br /&gt;
Tenemos dos formas de acceder al documento activo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc1 = XSCRIPTCONTEXT.getDocument()&lt;br /&gt;
    doc2 = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc1.getIdentifier())&lt;br /&gt;
    print (doc2.getIdentifier())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Documentation/Note| Mira en el archivo &amp;#039;&amp;#039;&amp;#039;pythonscript.py&amp;#039;&amp;#039;&amp;#039; la forma en que trabaja el método &amp;#039;&amp;#039;&amp;#039;getDocument&amp;#039;&amp;#039;&amp;#039;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si seguiste nuestra recomendación de asignar la macro de pruebas a una combinación de teclas disponible en todo AOO, prueba a abrir cada uno de los tipos de documentos que puedes ver en el menú &amp;#039;&amp;#039;&amp;#039;Archivo-&amp;gt;Nuevo-&amp;gt;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
[[Image:Py_img_0007.png|none|thumb|500px|Tipos de documentos en AOO]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y a ejecutar la siguiente macro, teniendo como documento activo cada uno de ellos, es decir, activas uno y ejecutas la macro, activas otro y vuelves a llamar a la macro y así sucesivamente con todos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getIdentifier())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los mensajes devueltos en cada documento, son bastante ilustrativos de que &amp;#039;&amp;#039;&amp;#039;tipo de documento&amp;#039;&amp;#039;&amp;#039; se trata. Pero si probaste con todos, habrás notado que con la base de datos nos devuelve un error, si no lo has probado hazlo ahora. Para resolver este caso tenemos varias posibilidades, la primera es controlar la excepción como ya aprendimos en la introducción a Python.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero... ¿estamos realmente seguros que ese es el error?, es mejor especificarlo y asegurarnos de que este es el error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    try:&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    except AttributeError:&lt;br /&gt;
        print (&amp;#039;Error al obtener el tipo de documento&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tenemos otra alternativa donde no usamos controlador de excepciónes, si no una función que nos dice si un cierto atributo lo posee o no un objeto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    if hasattr(doc, &amp;#039;getIdentifier&amp;#039;):&lt;br /&gt;
        print (doc.getIdentifier())&lt;br /&gt;
    else:&lt;br /&gt;
        print (&amp;#039;Sin atributo getIdentifier&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es mucho mejor esta segunda opción. Aun así, no podemos estar 100% seguros de que cuando no la tenga, el documento sea una base de datos, simplemente estamos excluyendo la posibilidad pero no lo estamos asegurando, probemos con otra propiedad.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    print (doc.getImplementationName())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mucho mejor, ahora ya no tenemos errores, pero si probaste de nuevo con todos los tipos de documentos, habrás notado que con &amp;#039;&amp;#039;&amp;#039;Impres&amp;#039;&amp;#039;&amp;#039; y con &amp;#039;&amp;#039;&amp;#039;Draw&amp;#039;&amp;#039;&amp;#039; obtenemos el mismo resultado, por lo que no tenemos la certeza de que tipo de documento es, por lo que descartamos esta propiedad para nuestra finalidad que es identificar fehacientemente cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
Ya vimos que cada objeto UNO soporta diferentes servicios e interfaces, asì que cada documento de AOO (&amp;#039;&amp;#039;&amp;#039;que son objetos&amp;#039;&amp;#039;&amp;#039;) soportan diferentes servicios, algunos son iguales, es decir, comúnes a todos, pero algunos pueden ser únicos para cada documento. Ya vimos como saber si un documento soporta una propiedad, pero para saber si soporta un servicio completo, cambiamos de método, ahora usamos &amp;#039;&amp;#039;&amp;#039;supportsService&amp;#039;&amp;#039;&amp;#039; que nos devuelve falso o verdadero según soporte o no el nombre del servicio pasado como argumento.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    res = doc.supportsService(&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;)&lt;br /&gt;
    mensaje = u&amp;#039;No soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    if res:&lt;br /&gt;
        mensaje = u&amp;#039;Soy una hoja de cálculo&amp;#039;&lt;br /&gt;
    print(mensaje)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y mejor aun, podemos saber todos los servicios que soporta un objeto con el método &amp;#039;&amp;#039;&amp;#039;getSupportedServiceNames&amp;#039;&amp;#039;&amp;#039; que nos devuelve una tupla con todos sus nombres.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    servicios = doc.getSupportedServiceNames()&lt;br /&gt;
    &lt;br /&gt;
    print(servicios)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Te queda de tarea probar esta macro en cada uno de los documentos abiertos, incluso puedes probar también el IDE para AOOBasic que incorpora AOO y determinar que servicio usar para diferenciar sin duda cada tipo de documento.&lt;br /&gt;
&lt;br /&gt;
== Los documentos abiertos ==&lt;br /&gt;
&lt;br /&gt;
Para acceder a todos los documentos abiertos en la sesión de AOO, usamos el método &amp;#039;&amp;#039;&amp;#039;getComponents&amp;#039;&amp;#039;&amp;#039; del objeto &amp;#039;&amp;#039;&amp;#039;Desktop&amp;#039;&amp;#039;&amp;#039;, si usas &amp;#039;&amp;#039;&amp;#039;MRI&amp;#039;&amp;#039;&amp;#039;, notarás que este método nos devuelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta interfaz (&amp;lt;idl&amp;gt;com.sun.star.container.XEnumerationAccess&amp;lt;/idl&amp;gt;) tiene un solo método llamado &amp;#039;&amp;#039;&amp;#039;createEnumeration&amp;#039;&amp;#039;&amp;#039; que nos duelve una instancia de la interfaz &amp;lt;idl&amp;gt;com.sun.star.container.XEnumeration&amp;lt;/idl&amp;gt; la cual a su vez tiene solo dos métodos, el primero para saber si tenemos más elementos en la enumeración: &amp;#039;&amp;#039;&amp;#039;hasMoreElements&amp;#039;&amp;#039;&amp;#039; y el segundo para acceder al siguiente elemento &amp;#039;&amp;#039;&amp;#039;nextElement&amp;#039;&amp;#039;&amp;#039;, veamoslo con un ejemplo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    &lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    # mientras tengamos elementos&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        # obtenemos el siguiente elemento&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # mostrámos el tipo de documento&lt;br /&gt;
        mensaje = obtener_tipo(doc)&lt;br /&gt;
        print(mensaje)&lt;br /&gt;
    return &lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;Calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;Writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;Impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;Draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;Base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;Math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;Basic&amp;#039;}&lt;br /&gt;
    # iteramos entre los tipos de documentos&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        # validamos si soporta el servicio&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            # devolvemos el tipo de documento&lt;br /&gt;
            return &amp;#039;Soy %s&amp;#039; % tipo[t]&lt;br /&gt;
    # si termina sin encontrar un tipo&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como usamos una macro de apoyo para saber que tipo de documento es. Una enumeración no es más que una lista de objetos y es una forma muy común y a veces la única de acceder a ciertos objetos en AOO, es importante que la recuerdes.&lt;br /&gt;
&lt;br /&gt;
== Rutas de archivos y directorios ==&lt;br /&gt;
&lt;br /&gt;
Apache OpenOffice, al ser multiplataforma, hace uso de las rutas de archivos y directorios, en el formato URL, por ejemplo.&lt;br /&gt;
&lt;br /&gt;
file:///home/usuario/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
file:///d:/datos/miarchivo.ods&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta que este formato hace uso de los caracteres 0-9, a-z y A-Z, y cualquier otro carácter será convertido y mostrado con su respectivo código, por ejemplo, los espacios los reemplazara con &amp;#039;&amp;#039;&amp;#039;%20&amp;#039;&amp;#039;&amp;#039;. Siempre que le pases una ruta de archivo a cualquier servicio de AOO, hazlo, casi como una regla, pasarle la ruta en formato Url, para ello, la libreria &amp;#039;&amp;#039;&amp;#039;uno&amp;#039;&amp;#039;&amp;#039; cuenta con dos funciones muy útiles que hacen el trabajo &amp;#039;&amp;#039;&amp;#039;systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; y &amp;#039;&amp;#039;&amp;#039;fileUrlToSystemPath&amp;#039;&amp;#039;&amp;#039;, veamos como se usan.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
&lt;br /&gt;
def rutas():&lt;br /&gt;
    &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi archivo de Calc.ods&amp;quot;&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # La convertimos al formato URL&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
 &lt;br /&gt;
    # Regresamos al formato local&lt;br /&gt;
    ruta = uno.fileUrlToSystemPath(ruta)&lt;br /&gt;
    print (ruta)&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Abre varios documentos existentes y ejecuta la siguiente macro desde cada uno:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def info_ruta():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
    &lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    # obtenemos la ruta en disco&lt;br /&gt;
    ruta =  doc.getURL()&lt;br /&gt;
    # obtenemos las diferentes partes de la ruta&lt;br /&gt;
    ruta, archivo = os.path.split(ruta)&lt;br /&gt;
    nombre, extension = os.path.splitext(archivo)&lt;br /&gt;
    &lt;br /&gt;
    print (ruta)&lt;br /&gt;
    print (uno.fileUrlToSystemPath(ruta))&lt;br /&gt;
    print (archivo)&lt;br /&gt;
    print (nombre)&lt;br /&gt;
    print (extension)&lt;br /&gt;
    &lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hemos importado una nueva librería de Python, &amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; que entre otras muchas cosas, nos permite obtener información de las rutas de archivos como en la macro anterior.&lt;br /&gt;
&lt;br /&gt;
En nuestros siguientes temas, veremos la importancia de usar las rutas de archivos y directorios en formato Url y recuerda que en S.O. Linux, se tiene en cuenta la diferencia entre mayúsculas y minúsculas.&lt;br /&gt;
&lt;br /&gt;
== Creando nuevos documentos ==&lt;br /&gt;
&lt;br /&gt;
El método que nos permite crear nuevos documentos se llama &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039; y es un método del servicio &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, por ejemplo, para crear una nueva hoja de calculo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Solo hay que hacer un pequeño cambio para crear un nuevo documento de texto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y los demás tipos de documentos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/simpress&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/sdraw&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/smath&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Y una base de datos?, probemos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/sbase&amp;#039;&lt;br /&gt;
    nuevo_doc = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nos da un error ¿verdad?&lt;br /&gt;
[[Image:Py_img_0008.png|none|thumb|500px|Error al crear base de datos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No esta soportado. Para saber por que nos da un error, intenta abrir una base de datos nueva, observa como primero, si queremos trabajar con ella, el asistente nos “obliga” primero a guardarla con un nombre y después ya podemos manipularla, esto, solo pasa con las bases de datos, de los demás documentos podemos crear tantos nuevos documentos como queramos sin tener que guardar nada, entonces ¿como creamos una nueva base de datos?, la respuesta es sencilla, del mismo modo que lo hacemos desde la interfaz de usuario, es decir, tenemos que guardar primero la base de datos.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)    &lt;br /&gt;
 &lt;br /&gt;
    ruta = &amp;quot;/home/mau/Mi_Base_Datos.odb&amp;quot;&lt;br /&gt;
    # Creamos el servicio que nos permite manipular bases de datos&lt;br /&gt;
    dbcon = sm.createInstance(&amp;#039;com.sun.star.sdb.DatabaseContext&amp;#039;)&lt;br /&gt;
    # creamos una instancia de una nueva base de datos&lt;br /&gt;
    base = dbcon.createInstance()&lt;br /&gt;
    # establecemos el tipo de base&lt;br /&gt;
    base.URL = &amp;quot;sdbc:embedded:hsqldb&amp;quot;&lt;br /&gt;
    # y la guardamos&lt;br /&gt;
    base.DatabaseDocument.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toma en cuenta dos cosas muy importantes en la macro anterior, el nombre que uses, si ya existe, simplemente lo reemplazara, no te preguntara nada, así que ten cuidado de no usar una ruta o nombre de una base importante que tengas y segundo, la base de datos así creada, no quedara “registrada” en AOO, con lo que no tendrás acceso desde otros programas de la aplicación, más adelante veremos como registrar una base de datos por código.&lt;br /&gt;
&lt;br /&gt;
== Abriendo, guardando y cerrando documentos ==&lt;br /&gt;
Abrir archivos existentes es sumamente sencillo, usamos el mismo método usado&lt;br /&gt;
para crear nuevos documentos &amp;lt;idl&amp;gt;com.sun.star.frame.XComponentLoader&amp;lt;/idl&amp;gt;, pero en el parámetro ruta, le especificamos la ubicación del archivo a abrir de la siguiente manera.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def documento1():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_default&amp;#039;, 0, ())&lt;br /&gt;
    &lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si tus archivos existen (esto se puede validar), el código anterior los abrirá, &amp;#039;&amp;#039;&amp;#039;siempre&amp;#039;&amp;#039;&amp;#039; utiliza&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;uno.systemPathToFileUrl&amp;#039;&amp;#039;&amp;#039; cuando uses rutas de archivos o directorios en&lt;br /&gt;
funciones de AOO que las requieran como argumentos. Ya vimos que el primer&lt;br /&gt;
agumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, es la ruta del archivo a&lt;br /&gt;
abrir, el segundo argumento es una cadena con el nombre del macro (frame)&lt;br /&gt;
donde será mostrado el documento abierto, generalmente si existe este frame se&lt;br /&gt;
usa si no se crea uno nuevo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_cal&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;nuevo_writer&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Existen nombre especiales para este agumento, los más usuales son dos, primero&lt;br /&gt;
que ya hemos estado usando &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; que usa el frame actual y&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039; que siempre crea un nuevo frame.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Calc.ods&amp;#039;)&lt;br /&gt;
    doc_c = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La recomendación es que uses siempre &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; o &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, un&lt;br /&gt;
escenario puede ser que habrás con &amp;#039;&amp;#039;&amp;#039;_default&amp;#039;&amp;#039;&amp;#039; una instancia, y después de&lt;br /&gt;
forma oculta uno nuevo con &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, más abajo vemos como abrir un&lt;br /&gt;
documento de forma oculta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si abres una plantilla, esta se comportará de forma normal, es decir, te abrirá una copia de dicha plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_plantilla.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ()) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pero también podrías querer abrir la plantilla para editarla, en este caso,&lt;br /&gt;
le indicamos en las opciones de apertura esta opción, y aquí vemos como usar&lt;br /&gt;
el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo.ots&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como hemos importado una nueva estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como la instanciamos y asignamos sus valores.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = False&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Muy importante, el cuarto argumento del método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
espera una tupla, por eso es que usamos la coma al final del nombre del&lt;br /&gt;
argumento &amp;#039;&amp;#039;&amp;#039;(opciones,)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La estructura &amp;lt;idl&amp;gt;com.sun.star.beans.PropertyValue&amp;lt;/idl&amp;gt; esta conformada por&lt;br /&gt;
un par de valores, un nombre y un valor y es muy frecuentemente usada cuando se&lt;br /&gt;
programa en AOO, para este ejemplo solo hemos usado un par de agumentos,&lt;br /&gt;
siempre van en pares, pero muy bien puede tener más opciones como veremos más&lt;br /&gt;
adelante. En la macro anterior le estamos indicando la propiedad&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (que seria algo así como Es Plantilla), si el valor es&lt;br /&gt;
falso (False), le estamos indicando que queremos abrir la plantilla para&lt;br /&gt;
editarla, en caso contrario (True) abrirá una copia de la plantilla. Lo&lt;br /&gt;
interesante de esta propiedad es que perfectamente la puedes aplicar a archivos&lt;br /&gt;
existentes, es decir, archivos que &amp;#039;&amp;#039;&amp;#039;no&amp;#039;&amp;#039;&amp;#039; necesariamente sean plantillas, con&lt;br /&gt;
esta propiedad podemos forzarlos a comportarse como plantillas, por ejemplo, prueba el siguiente código con algún archivo existente que no sea plantilla.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;AsTemplate&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como el archivo es un documento de texto normal (ODT), pero con la&lt;br /&gt;
propiedad &amp;#039;&amp;#039;&amp;#039;AsTemplate&amp;#039;&amp;#039;&amp;#039;, forzamos su apertura como una plantilla.&lt;br /&gt;
&lt;br /&gt;
Otras propiedades interesantes son &amp;#039;&amp;#039;&amp;#039;ReadOnly&amp;#039;&amp;#039;&amp;#039; (Solo Lectura) para abrir un&lt;br /&gt;
archivo como solo lectura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Mi_archivo_de_Writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y &amp;#039;&amp;#039;&amp;#039;Password&amp;#039;&amp;#039;&amp;#039; (Contraseña) para abrir archivos con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto puedes combinar cualquier cantidad de opciones siempre y cuando no&lt;br /&gt;
entren en conflicto, es importante que al final, sea una tupla lo que le pasas&lt;br /&gt;
al método, si no, te dará un error.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    # creamos una lista vacía&lt;br /&gt;
    opciones = []&lt;br /&gt;
    # creamos la primer propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opcion.Value = True&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
    # creamos la segunda propiedad&lt;br /&gt;
    opcion = PropertyValue()&lt;br /&gt;
    opcion.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opcion.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
    # y la agregamos a la lista&lt;br /&gt;
    opciones.append(opcion)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/Archivo_con_contrasena.odt&amp;#039;)&lt;br /&gt;
    # nota que la lista la convertimos en tupla&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, tuple(opciones))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si la contraseña es incorrecta, no obtendrás ningún mensaje, simplemente no&lt;br /&gt;
lo abrira y la variable &amp;#039;&amp;#039;&amp;#039;doc&amp;#039;&amp;#039;&amp;#039; será vacía, puedes validar esto:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    if doc is None:&lt;br /&gt;
        print (&amp;#039;No se abrio el documento&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Más adelante veremos otras formas de validar y depurar nuestras macros para&lt;br /&gt;
los dificiles casos en donde no obtengamos ningún mensaje de error, pero&lt;br /&gt;
simplemente nuestra macro se niega a hacer su trabajo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mientras un formato de archivo sea soportado por AOO, lo podrás abrir con el&lt;br /&gt;
método &amp;#039;&amp;#039;&amp;#039;loadComponentFromURL&amp;#039;&amp;#039;&amp;#039;, en el siguiente ejemplo, abrimos un archivo tipo Doc, un Html y un Xls.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc_w = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_web.html&amp;#039;)&lt;br /&gt;
    doc_h = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_excel.xls&amp;#039;)&lt;br /&gt;
    doc_x = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
¿Qué otras opciones tengo para abrir archivos?. La mayoría están descritas&lt;br /&gt;
en el servicio &amp;lt;idl&amp;gt;com.sun.star.document.MediaDescriptor&amp;lt;/idl&amp;gt;, aquí veremos&lt;br /&gt;
las más usadas.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cuando abres un archivo por código y este contiene macros, tu puedes&lt;br /&gt;
establecer si se abre con las macros activadas, de forma predeterminada lo abre&lt;br /&gt;
con las macros desactivadas, así que solo nos resta saber como abrirlo con las&lt;br /&gt;
macros activadas, las constanes que puedes usar puedes verlas aquí&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.document.MacroExecMode&amp;lt;/idl&amp;gt;&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.document.MacroExecMode import ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;MacroExecutionMode&amp;#039;&lt;br /&gt;
    opciones.Value = ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Otra opción interesante, es la que nos permite abrir una presentación e iniciarla inmediatamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;StartPresentation&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_impress.odp&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Puedes abrir un archivo como vista previa, útil para evitar que el usuario haga cambios en el, en este estado, los cambios que intente hacer el usuario no se guardaran.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Preview&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_writer.odt&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por supuesto, la idea general de abrir un archivo es para obtener datos de el o para manipularlo, ya sea un documento nuevo o uno existente, veamos como guardar los cambios realizados y cerrar el archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    # aquí va todo el código que quieras para manipular el archivo&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto correctamente, presiona Aceptar para gaurdarlo y cerrarlo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # guardamos los cambios&lt;br /&gt;
    doc.store()&lt;br /&gt;
    # cerramos el archivo&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El código anterior funcionara con un archivo existente, pero con uno nuevo no,&lt;br /&gt;
te dará un error, por supuesto no me creas, compruébalo. Los documentos&lt;br /&gt;
tienen un método (&amp;#039;&amp;#039;&amp;#039;hasLocation&amp;#039;&amp;#039;&amp;#039;) que nos informa si un documento ya esta guardado o no.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
    &lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.hasLocation())&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El primer mensaje debe mostrarte falso (False) porque es un documento nuevo y&lt;br /&gt;
el segundo verdadero (True) por ser un archivo abierto del disco.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
También tenemos una propiedad que nos ayuda a saber si un documento ha sido modificado o no, ejecuta la siguiente macro, llamándola desde diferentes documentos, unos ábrelos y modifícalos antes de ejecutarla, otros, solo ábrelos y ejecútala para que notes la diferencia.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def esta_modificado():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
 &lt;br /&gt;
    msgbox(doc.isModified())&lt;br /&gt;
    return &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Y otra más que nos informa si el documento es de solo lectura (&amp;#039;&amp;#039;&amp;#039;isReadonly&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;ReadOnly&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
    msgbox(doc.isReadonly())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que valides antes de intentar guardar un archivo, si este ha sido&lt;br /&gt;
modificado o es de solo lectura. Ahora veamos como guardar un archivo nuevo con el método &amp;#039;&amp;#039;&amp;#039;storeAsUrl&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Observa como requiere dos parámetros, la ruta del archivo y una matriz de&lt;br /&gt;
propiedades, algunas de las cuales veremos a continuación. Toma nota de que si&lt;br /&gt;
el archivo ya existe lo reemplazara sin avisarte por lo que es buena practica&lt;br /&gt;
de programación validar esto, observa como volvemos a usar la librería&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;os&amp;#039;&amp;#039;&amp;#039; para saber si un archivo existe ya.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    documentos()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def documentos():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Ahora guardaremos el archivo&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;/home/mau/archivo_nuevo_calc.ods&amp;#039;&lt;br /&gt;
    if os.path.exists(ruta):&lt;br /&gt;
        msgbox(u&amp;#039;El archivo existe, no se guardará el nuevo&amp;#039;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(ruta)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
De la macro anterior, &amp;#039;&amp;#039;&amp;#039;es muy importante&amp;#039;&amp;#039;&amp;#039; que tomes nota que para todos&lt;br /&gt;
los métodos de Python que usen rutas de archivos o directorios, se les tienen&lt;br /&gt;
que pasar en las rutas nativas del sistema operativo donde estes trabajando,&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;solo&amp;#039;&amp;#039;&amp;#039; a los métodos de AOO, es a los que se les pasa en notación URL.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Veamos algunas propiedades interesantes para guardar archivos, por ejemplo, guardar con contraseña.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/scalc&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo pero con contraseña&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Password&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;letmein&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_protegido.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como sabes, AOO, soporta la importación/exportación de múltiples formatos de archivos, veamos como guardar, por ejemplo, en formato DOC.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    ruta = &amp;#039;private:factory/swriter&amp;#039;&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos el archivo en formato DOC&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
    opciones.Value = &amp;#039;MS Word 97&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_word.doc&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, (opciones,))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es importante que cuando exportes, uses un formato compatible, es decir, no&lt;br /&gt;
puedes guardar una hoja de calculo como documento de texto. En el [[ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/Apendices|Apéndice]]&lt;br /&gt;
mostramos una macro para obtener todos los filtros que soporta AOO.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El método storeAsURL también lo puedes usar para abrir un archivo existente y guardarlo con otro nombre.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
&lt;br /&gt;
    msgbox(u&amp;#039;Ahora guardaremos con otro nombre&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc_nuevo.ods&amp;#039;)&lt;br /&gt;
    doc.storeAsURL(ruta, ())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Para terminar esta sección, vamos a hacer un poco más interactiva la apertura&lt;br /&gt;
y guardado de archivos, permitamos que el usuario escoja la ruta y el archivo&lt;br /&gt;
desde un cuadro de dialogo, para ello, usaremos el servicio&lt;br /&gt;
&amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt;, que nos permite hacer esto.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    # podemos establecer el título&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        # el primer elemento es la ruta seleccionada&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si estableces la propiedad &amp;#039;&amp;#039;&amp;#039;MultiSelectionMode&amp;#039;&amp;#039;&amp;#039; en verdadero, le&lt;br /&gt;
permitiras al usuario seleccionar más de un archivo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Selecciona un archivo&amp;#039;)&lt;br /&gt;
    dlg.setMultiSelectionMode(True)&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        archivos = dlg.getFiles()&lt;br /&gt;
        if len(archivos) == 1:&lt;br /&gt;
            # si selecciona uno, devuelve la ruta completa&lt;br /&gt;
            desktop.loadComponentFromURL(archivos[0], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
        else:&lt;br /&gt;
            # si selecciona varios, el primer elemento es la carpeta&lt;br /&gt;
            folder = archivos[0]&lt;br /&gt;
            # los demás elementos son los archivos seleccionados&lt;br /&gt;
            for f in range(1, len(archivos)):&lt;br /&gt;
                desktop.loadComponentFromURL(folder + archivos[f], &amp;#039;_blank&amp;#039;, 0, ())&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(&amp;#039;Proceso cancelado&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Si lo notaste, con la macro anterior el usuario puede seleccionar cualquier&lt;br /&gt;
archivo, para limitar las opciones, agrega un filtro con el método&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;appendFilter&amp;#039;&amp;#039;&amp;#039; con solo los tipos de&lt;br /&gt;
archivos que necesites, usa una línea por cada filtro, este método requiere&lt;br /&gt;
dos argumentos, el primero es el título, lo que verá el usuario y el segundo&lt;br /&gt;
es el filtro en si.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora, mostramos el cuadro de dialogo Guardar Como, para permitir al usuario&lt;br /&gt;
seleccionar carpeta y nombre de archivo donde guardar su archivo, se usa el&lt;br /&gt;
mismo servicio &amp;lt;idl&amp;gt;com.sun.star.ui.dialogs.FilePicker&amp;lt;/idl&amp;gt; solo cambiando&lt;br /&gt;
algunas de sus propiedades.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_AUTOEXTENSION_PASSWORD&lt;br /&gt;
    &lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    dlg = sm.createInstance(&amp;#039;com.sun.star.ui.dialogs.FilePicker&amp;#039;)&lt;br /&gt;
    dlg.setTitle(&amp;#039;Guardar archivo&amp;#039;)&lt;br /&gt;
    dlg.appendFilter(&amp;#039;Hoja de calculo ODF (.ods)&amp;#039;, &amp;#039;*.ods&amp;#039;)&lt;br /&gt;
    # con esta opción le indicamos que use guardar como con otras opciones&lt;br /&gt;
    dlg.initialize((FILESAVE_AUTOEXTENSION_PASSWORD,))&lt;br /&gt;
    if dlg.execute():&lt;br /&gt;
        ruta = dlg.getFiles()[0]&lt;br /&gt;
        msgbox(ruta)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nota que el argumento del método &amp;#039;&amp;#039;&amp;#039;initialize&amp;#039;&amp;#039;&amp;#039; es una tupla.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora si, para terminar, te mostramos como abrir un archivo de forma oculta.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo cerraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.store()&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es &amp;#039;&amp;#039;&amp;#039;muy importante&amp;#039;&amp;#039;&amp;#039;, que cuando abras un archivo oculto siempre uses el argumento &amp;#039;&amp;#039;&amp;#039;_blank&amp;#039;&amp;#039;&amp;#039;, a menos claro esta, que sepas lo que haces, y que, mantengas una referencia a el, para poder cerrarlo en cuanto no lo necesites.&lt;br /&gt;
&lt;br /&gt;
== Algunas tareas comunes en documentos ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exportando a PDF ===&lt;br /&gt;
&lt;br /&gt;
Para exportar a PDF solo hay que establecer el filtro correcto, nota como construimos el nombre del filtro de acuerdo al tipo de documento y como construimos la ruta de acuerdo a la ruta actual donde este guardado el documento solo reemplazando la extensión para que quede en PDF. Estamos haciendo uso de la macro &amp;#039;&amp;#039;&amp;#039;obtener_tipo&amp;#039;&amp;#039;&amp;#039; con unos ligeros cambios para este propósito.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    export_pdf()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def export_pdf():&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    doc = desktop.getCurrentComponent()&lt;br /&gt;
    tipo = obtener_tipo(doc)&lt;br /&gt;
    soportados = &amp;#039;calc,writer,draw,impress,math&amp;#039;&lt;br /&gt;
    if tipo in soportados:&lt;br /&gt;
        # establecemos el filtro como PDF&lt;br /&gt;
        opciones = PropertyValue()&lt;br /&gt;
        opciones.Name = &amp;#039;FilterName&amp;#039;&lt;br /&gt;
        opciones.Value = &amp;#039;%s_pdf_Export&amp;#039; % tipo&lt;br /&gt;
        # obtenemos la ruta y reemplazados la extensión por PDF&lt;br /&gt;
        ruta, archivo = os.path.split(doc.getURL())&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
        ruta = os.path.join(ruta, nombre + &amp;#039;.pdf&amp;#039;)&lt;br /&gt;
        # guardamos&lt;br /&gt;
        doc.storeToURL(ruta, (opciones,))&lt;br /&gt;
        msgbox(u&amp;#039;Documento exportado correctamente a PDF&amp;#039;)&lt;br /&gt;
    else:&lt;br /&gt;
        msgbox(u&amp;#039;Aplicación no soportada&amp;#039;)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def obtener_tipo(doc):&lt;br /&gt;
    tipo = {&amp;#039;com.sun.star.sheet.SpreadsheetDocument&amp;#039;: &amp;#039;calc&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.text.TextDocument&amp;#039;: &amp;#039;writer&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.presentation.PresentationDocument&amp;#039;: &amp;#039;impress&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.drawing.DrawingDocument&amp;#039;: &amp;#039;draw&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.sdb.OfficeDatabaseDocument&amp;#039;: &amp;#039;base&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.formula.FormulaProperties&amp;#039;: &amp;#039;math&amp;#039;,&lt;br /&gt;
            &amp;#039;com.sun.star.script.BasicIDE&amp;#039;: &amp;#039;basic&amp;#039;}&lt;br /&gt;
    for t in tipo:&lt;br /&gt;
        if doc.supportsService(t):&lt;br /&gt;
            return tipo[t]&lt;br /&gt;
    return &amp;#039;No se que tipo soy&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La forma de descomponer la ruta en sus diferentes partes, ya la vimos anteriormente, en este caso, observa como la extensión actual del documento ya no la usaremos por lo que la omitimos con un guión bajo.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
        nombre, _ = os.path.splitext(archivo)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ocultando y mostrando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para ocultar una ventana, hay que acceder a la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # y la ocultamos&lt;br /&gt;
        ventana.setVisible(False)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Se han ocultado todas las ventanas, presiona Aceptar para mostrarlas&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # tienes que crear de nuevo la enumeración&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # ahora las mostramos&lt;br /&gt;
        ventana.setVisible(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta técnica la puedes usar también para mostrar un archivo que abriste de forma oculta previamente.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
    from com.sun.star.beans import PropertyValue&lt;br /&gt;
&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
&lt;br /&gt;
    opciones = PropertyValue()&lt;br /&gt;
    opciones.Name = &amp;#039;Hidden&amp;#039;&lt;br /&gt;
    opciones.Value = True&lt;br /&gt;
&lt;br /&gt;
    ruta = uno.systemPathToFileUrl(&amp;#039;/home/mau/archivo_calc.ods&amp;#039;)&lt;br /&gt;
    doc = desktop.loadComponentFromURL(ruta, &amp;#039;_blank&amp;#039;, 0, (opciones,))&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo abierto de forma oculta, ahora lo mostraremos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
    ventana.setVisible(True)&lt;br /&gt;
&lt;br /&gt;
    msgbox(&amp;#039;Archivo visible, ahora lo cerramos&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    doc.close(True)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Activando ventanas ===&lt;br /&gt;
&lt;br /&gt;
Para usamos el método &amp;#039;&amp;#039;&amp;#039;setFocus&amp;#039;&amp;#039;&amp;#039; de la ventana contenedora.&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import uno&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def pruebas():&lt;br /&gt;
    ctx = uno.getComponentContext()&lt;br /&gt;
    sm = ctx.getServiceManager()&lt;br /&gt;
&lt;br /&gt;
    desktop = sm.createInstanceWithContext(&amp;#039;com.sun.star.frame.Desktop&amp;#039;, ctx)&lt;br /&gt;
    documentos = desktop.getComponents()&lt;br /&gt;
    enum = documentos.createEnumeration()&lt;br /&gt;
    while enum.hasMoreElements():&lt;br /&gt;
        doc = enum.nextElement()&lt;br /&gt;
        # obtenemos una referencia a la ventana contenedora&lt;br /&gt;
        ventana = doc.getCurrentController().getFrame().getContainerWindow()&lt;br /&gt;
        # esperamos 3 segundos y mostramos la ventana&lt;br /&gt;
        time.sleep(3)&lt;br /&gt;
        ventana.setFocus()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Controlando la barra de estado ===&lt;/div&gt;</summary>
		<author><name>Mauriciobaeza</name></author>
	</entry>
</feed>