Difference between revisions of "ES/Manuales/GuiaAOO/TemasAvanzados/Macros/Python/PythonCalc/TrabajandoConHojas"

From Apache OpenOffice Wiki
< ES‎ | Manuales‎ | GuiaAOO‎ | TemasAvanzados‎ | Macros‎ | Python‎ | PythonCalc
Jump to: navigation, search
(Insertando hojas)
 
(12 intermediate revisions by one other user not shown)
Line 105: Line 105:
 
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.
 
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.
 
<source lang=python>
 
<source lang=python>
     nombre = 'Nueva hoja'   hojas = doc.getSheets()   if not hojas.hasByName(nombre):       hojas.insertNewByName(nombre, 0)   nueva_hoja = doc.getSheets().getByName(nombre)   doc.getCurrentController().setActiveSheet(nueva_hoja)   
+
     nombre = 'Nueva hoja'
 +
    hojas = doc.getSheets()
 +
    if not hojas.hasByName(nombre):
 +
        hojas.insertNewByName(nombre, 0)
 +
    nueva_hoja = doc.getSheets().getByName(nombre)
 +
    doc.getCurrentController().setActiveSheet(nueva_hoja)   
 
</source>
 
</source>
  
  
 
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.  
 
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.  
{{Documentation/Note| Es sumamente frecuente en programadores noveles, querer '''activar''' toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}
+
{{Note| Es sumamente frecuente en programadores noveles, querer '''activar''' toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres}}
  
  
 
También podemos agregar la hoja al final de todas las demás.
 
También podemos agregar la hoja al final de todas las demás.
 +
<source lang=python>
 +
    nombre = 'Otra hoja'
 +
    hojas = doc.getSheets()
 +
    if not hojas.hasByName(nombre):
 +
        hojas.insertNewByName(nombre, hojas.getCount())
 +
    nueva_hoja = doc.getSheets().getByName(nombre)
 +
    doc.getCurrentController().setActiveSheet(nueva_hoja)   
 +
</source>
  
  
<source lang="oobas">
+
Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por '''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.
Sub InsertarNuevaHoja3()
+
<source lang=python>
Dim oHojas As Object
+
    activa = doc.getCurrentController().getActiveSheet()
Dim oHoja As Object
+
    indice = activa.getRangeAddress().Sheet
Dim sNombre As String
+
    msgbox(u'El índice de la hoja activa es: %s' % indice)
 +
</source>
  
    sNombre <nowiki>=</nowiki> Trim(InputBox("Nombre de la nueva hoja"))
 
    If sNombre <nowiki><></nowiki> "" Then
 
        oHojas <nowiki>=</nowiki> ThisComponent.getSheets()
 
        If Not oHojas.hasByName(sNombre) Then
 
            'Si no existe la insertamos al final
 
            oHojas.insertNewByName( sNombre, oHojas.getCount() )
 
        End If
 
        oHoja <nowiki>=</nowiki> ThisComponent.getSheets.getByName(sNombre)
 
        ThisComponent.getCurrentController.setActiveSheet(oHoja)
 
    End If
 
  
End Sub
+
Que podemos convertir en una submacro. Nota como estamos estableciendo un '''valor por default''' para el ultimo argumento que será la posición deseada para la nueva hoja.
 +
<source lang=python>
 +
def nueva_hoja(doc, nombre, pos=0):
 +
    hojas = doc.getSheets()
 +
    if not hojas.hasByName(nombre):
 +
        activa = doc.getCurrentController().getActiveSheet()
 +
        indice = activa.getRangeAddress().Sheet
 +
        if pos == 1:
 +
            pos = indice
 +
        elif pos == 2:
 +
            pos = indice + 1
 +
        elif pos > 2:
 +
            pos = hojas.getCount()
 +
        hojas.insertNewByName(nombre, pos)
 +
        return hojas.getByName(nombre)
 
</source>
 
</source>
  
  
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.
+
Ahora ya podemos insertar una nueva hoja en la posición que sea.
 +
<source lang=python>
 +
    doc = desktop.getCurrentComponent()
 +
   
 +
    nombre = 'Al inicio'
 +
    nueva = nueva_hoja(doc, nombre)
  
 +
    nombre = 'Antes de la activa'
 +
    nueva = nueva_hoja(doc, nombre, 1)
  
<source lang="oobas">
+
    nombre = 'Despues de la activa'
Sub IndiceHojaActiva()
+
    nueva = nueva_hoja(doc, nombre, 2)
Dim co1 As Integer
+
   
Dim oHojaActiva As Object
+
    nombre = 'Al final'
dim oHoja As Object
+
    nueva = nueva_hoja(doc, nombre, 3) 
 +
</source>
  
    oHojaActiva <nowiki>=</nowiki> ThisComponent.getCurrentController.getActiveSheet()
+
== Borrando hojas ==
 +
Para borrar hojas, usamos el método '''removeByName(Nombre)''', donde '''''Nombre''''' 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.
 +
<source lang=python>
 +
    hojas = doc.getSheets()
 +
    hojas.removeByName('Hoja3')
 +
</source>
  
    For co1 <nowiki>=</nowiki> 0 To ThisComponent.getSheets.getCount() - 1
 
        oHoja <nowiki>=</nowiki> ThisComponent.getSheets.getByIndex(co1)
 
        If oHoja.getName() <nowiki>=</nowiki> oHojaActiva.getName() then
 
            MsgBox "El indice de la hoja activa es: " & co1
 
            Exit For
 
        End If
 
    Next
 
  
End Sub
+
Por supuesto no puedes borrar una hoja que no exista, así que verifícalo.
 +
<source lang=python>
 +
    nombre = 'Hoja2'
 +
    hojas = doc.getSheets()
 +
    if hojas.hasByName(nombre):
 +
        hojas.removeByName(nombre)
 +
    else:
 +
        msgbox('No existe la hoja: %s' % nombre)
 
</source>
 
</source>
  
  
Que podemos convertir a una función.
+
Puedes borrar la hoja activa.
 +
<source lang=python>
 +
    activa = doc.getCurrentController().getActiveSheet()
 +
    hojas = doc.getSheets()
 +
    hojas.removeByName(activa.getName())
 +
</source>
  
  
<source lang="oobas">
+
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.
Function BuscarIndiceHoja(ByVal NombreHoja As String) As Integer
+
<source lang=python>
Dim co1 As Integer
+
    nombre = 'borrame'
dim oHoja As Object
+
    hojas = doc.getSheets()
 +
    if hojas.hasByName(nombre) and hojas.getCount() > 1:
 +
        hojas.removeByName(nombre)
 +
    else:
 +
        msgbox('La hoja no existe o solo queda una')
 +
</source>
  
    For co1 <nowiki>=</nowiki> 0 To ThisComponent.getSheets.getCount() - 1
+
== Moviendo hojas ==
        oHoja <nowiki>=</nowiki> ThisComponent.getSheets.getByIndex(co1)
+
Para mover hojas usamos el método '''moveByName(NombreHoja, PosicionNueva)''', donde '''''NombreHoja''''' tiene que ser el nombre de una hoja existente. En el siguiente ejemplo movemos la hoja al inicio.
        If oHoja.getName() <nowiki>=</nowiki> NombreHoja then
+
<source lang=python>
            BuscarIndiceHoja <nowiki>=</nowiki> co1
+
    hojas = doc.getSheets()
            Exit Function
+
    hojas.moveByName('Hoja3', 0)
        End If
+
    Next
+
    BuscarIndiceHoja <nowiki>=</nowiki> -1
+
 
+
End Function
+
 
</source>
 
</source>
  
  
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.
+
Ahora, la movemos al final.
 +
<source lang=python>
 +
    hojas = doc.getSheets()
 +
    hojas.moveByName('Hoja3', hojas.getCount())
 +
</source>
  
  
<source lang="oobas">
+
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.
Sub InsertarNuevaHoja4()
+
<source lang=python>
Dim oHojas As Object
+
    hojas = doc.getSheets()
Dim oHoja As Object
+
    nombres = sorted(hojas.getElementNames())
Dim oHojaActiva As Object
+
    for i,v in enumerate(nombres):
Dim sNombre As String
+
        hojas.moveByName(v, i)
Dim pos As Integer
+
</source>
  
    sNombre <nowiki>=</nowiki> Trim(InputBox("Nombre de la nueva hoja"))
+
== Copiando hojas ==
    If sNombre <nowiki><></nowiki> "" Then
+
Para copiar hojas usamos el método '''copyByName(NombreHoja, NombreNuevo, Posicion)''' de la siguiente manera.
        oHojas <nowiki>=</nowiki> ThisComponent.getSheets()
+
<source lang=python>
        oHojaActiva <nowiki>=</nowiki> ThisComponent.getCurrentController.getActiveSheet()
+
    hojas = doc.getSheets()
        If Not oHojas.hasByName(sNombre) Then
+
    hojas.copyByName('Hoja2', 'Nueva hoja2', 0)
            'Buscamos el índice de la hoja activa
+
</source>
            pos <nowiki>=</nowiki> BuscarIndiceHoja(oHojaActiva.getName())
+
            oHojas.insertNewByName( sNombre, pos )
+
        End If
+
        oHoja <nowiki>=</nowiki> ThisComponent.getSheets.getByName(sNombre)
+
        ThisComponent.getCurrentController.setActiveSheet(oHoja)
+
    End If
+
  
End Sub
+
 
 +
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.
 +
<source lang=python>
 +
    nombre = 'Datos'
 +
    nombre_nuevo = 'Datos nuevos'
 +
    hojas = doc.getSheets()
 +
    if hojas.hasByName(nombre) and not hojas.hasByName(nombre_nuevo):
 +
        hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())
 +
    else:
 +
        msgbox('No se copio la hoja')
 
</source>
 
</source>
  
  
Para insertar después de la hoja activa, solo sumas uno al valor devuelto por la función {{TextColor|Blue|BuscarIndiceHoja}}.
+
Podemos intentar copiar una hoja y asegurarnos de que el nombre no exista, tomando como base el nombre actual de la hoja, por ejemplo.
 +
<source lang=python>
 +
    hojas = doc.getSheets()
 +
    nombre = doc.getCurrentController().getActiveSheet().getName()
 +
    co1 = 1
 +
    nombre_nuevo = '%s_%s' % (nombre, co1)
 +
    while hojas.hasByName(nombre_nuevo):
 +
        co1 += 1
 +
        nombre_nuevo = '%s_%s' % (nombre, co1)
 +
    hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())
 +
    hoja = hojas.getByName(nombre_nuevo)
 +
    doc.getCurrentController().setActiveSheet(hoja)
 +
</source>
  
 +
== Renombrando hojas ==
  
<source lang="oobas">
+
Para renombrar hojas usamos el método '''setName(NuevoNombre)''', de la siguiente manera.
pos <nowiki>=</nowiki> BuscarIndiceHoja(oHojaActiva.getName()) + 1
+
<source lang=python>
 +
    hojas = doc.getSheets()
 +
    hojas.getByName('Hola').setName('Prueba')
 
</source>
 
</source>
  
  
Podemos aventurar una primera versión de una función genérica para insertar una nueva hoja de calculo donde quieras.
+
También puedes usar el índice para referirte a la hoja.
 +
<source lang=python>
 +
    hojas = doc.getSheets()
 +
    hojas.getByIndex(0).setName('Prueba')
 +
</source>
  
  
<source lang="oobas">
+
Es recomendable validar que la hoja a renombrar exista y que el nuevo nombre no.
'Como función regresamos la nueva hoja insertada o la existente en su caso
+
<source lang=python>
'Posición:    1 = Inicio
+
    hojas = doc.getSheets()
'            2 = Final
+
    actual = 'Resumen'
'           3 = Antes de la hoja activa
+
    nuevo = 'Terminado'
'            4 = Después de la hoja activa
+
    # Validamos que la hoja exista y el nuevo nombre no
Function getNuevaHoja(NombreHoja As String, Posicion As Integer) As Object
+
    if hojas.hasByName(actual) and not hojas.hasByName(nuevo):
Dim oHojas As Object
+
        hojas.getByName(actual).setName(nuevo)
Dim oHojaActiva As Object
+
    else:
Dim iPos As Integer
+
        msgbox('No es posible renombrar la hoja')
 +
</source>
  
    If NombreHoja <nowiki><></nowiki> "" Then
 
        oHojas <nowiki>=</nowiki> ThisComponent.getSheets()
 
        oHojaActiva <nowiki>=</nowiki> ThisComponent.getCurrentController.getActiveSheet()
 
        Select Case Posicion
 
            Case 1 : iPos <nowiki>=</nowiki> 0
 
            Case 2 : iPos <nowiki>=</nowiki> oHojas.getCount()
 
            Case 3 : iPos <nowiki>=</nowiki> oHojaActiva.getRangeAddress.Sheet
 
            Case 4 : iPos <nowiki>=</nowiki> oHojaActiva.getRangeAddress.Sheet + 1
 
            Case Else : iPos <nowiki>=</nowiki> 0
 
        End Select
 
        If Not oHojas.hasByName(NombreHoja) Then
 
            oHojas.insertNewByName(NombreHoja, iPos)
 
        End If
 
        getNuevaHoja <nowiki>=</nowiki> ThisComponent.getSheets.getByName(NombreHoja)
 
    End If
 
  
End Function
+
Solo para divertirnos, cambiamos los nombres de las hojas por números.
 +
<source lang=python>
 +
    hojas = doc.getSheets()
 +
    for i in range(hojas.getCount()):
 +
        hojas.getByIndex(i).setName(i+1)
 
</source>
 
</source>
  
  
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.
+
Ahora por letras, el código siguiente podría fallar en algunas circunstancias, tu tarea es decirnos ¿porqué? y corregirlo.
 +
<source lang=python>
 +
    hojas = doc.getSheets()
 +
    for i in range(hojas.getCount()):
 +
        hojas.getByIndex(i).setName(chr(i+65))
 +
</source>
  
== Borrando hojas ==
 
  
== Moviendo hojas ==
+
O los meses del año:
 +
<source lang=python>
 +
import uno
 +
import datetime
 +
import locale
 +
locale.setlocale(locale.LC_ALL, '')
  
== Copiando hojas ==
+
def pruebas():
 +
    ctx = uno.getComponentContext()
 +
    sm = ctx.getServiceManager()
 +
   
 +
    desktop = sm.createInstanceWithContext('com.sun.star.frame.Desktop', ctx)
 +
    doc = desktop.getCurrentComponent()
 +
   
 +
    hojas = doc.getSheets()
 +
    for i in range(hojas.getCount()):
 +
        hojas.getByIndex(i).setName(datetime.date(2013, i+1, 1).strftime('%B'))
 +
    return
 +
</source>
  
== Renombrando hojas ==
+
 
 +
Observa que hacemos uso de dos nuevas librerias de Python, '''datetime''' que tiene muchas utiles funciones para trabajar con fechas y tiempo, y '''locale''' para que los meses nos salgan en español.
  
 
== Ocultando y mostrando hojas ==
 
== Ocultando y mostrando hojas ==
 +
 +
Mostrar y ocultar hojas es muy sencillo, solo hay que establecer su propiedad '''IsVisible''' en verdadero (True) o falso (False) según se requiera de la siguiente manera.
 +
<source lang=python>
 +
    activa = doc.getCurrentController().getActiveSheet()
 +
    activa.IsVisible = False
 +
</source>
 +
 +
 +
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.
 +
<source lang=python>
 +
    hoja = doc.getSheets().getByIndex(1)
 +
    hoja.IsVisible = not hoja.IsVisible
 +
    doc.getCurrentController().setActiveSheet(hoja)
 +
</source>
 +
 +
 +
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.
 +
 +
<source lang="oobas">
 +
    hojas = doc.getSheets()
 +
   
 +
    activa = doc.getCurrentController().getActiveSheet().getRangeAddress().Sheet
 +
    for i in range(hojas.getCount()):
 +
        if i != activa:
 +
            hojas.getByIndex(i).IsVisible = False
 +
</source>
 +
 +
 +
Tu tarea es hacer la función inversa, muestra todas las hojas ocultas.
  
 
== Protección y desprotección de hojas ==
 
== Protección y desprotección de hojas ==
  
[[Category:ES/Python]]
+
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 '''protect(contraseña)''', 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.
 +
<source lang=python>
 +
    activa = doc.getCurrentController().getActiveSheet()
 +
    activa.protect('letmein')
 +
</source>
 +
 
 +
 
 +
Y para desproteger, usamos el método '''unprotect(contraseña)''', 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 '''isProtected''', si es verdadera (True) la hoja sigue protegida, si es falsa (False), la hoja esta desprotegida.
 +
<source lang=python>
 +
    activa = doc.getCurrentController().getActiveSheet()
 +
    if activa.isProtected():
 +
        msgbox('Hoja protegida, se va a desproteger')
 +
        activa.unprotect('letmein')
 +
        if activa.isProtected():
 +
            msgbox('Contraseña incorrecta')
 +
        else:
 +
            msgbox('Hoja desprotegida correctamente')
 +
    else:
 +
        msgbox('La hoja no esta protegida')
 +
</source>
 +
 
 +
 
 +
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.
 +
 
 +
 
 +
{{ES/Foro|macros}}
 +
 
 +
 
 +
[[Category:ES]][[Category:Manuales]][[Category:ES/Python]]

Latest revision as of 14:37, 7 July 2018


Acceso a las hojas de un archivo Calc

Para acceder a todas las hojas de un archivo usamos el método getSheets.

    doc = desktop.getCurrentComponent()
    hojas = doc.getSheets()


Podemos devolver todos los nombres de las mismas.

    doc = desktop.getCurrentComponent()
    hojas = doc.getSheets()
    nombres = hojas.getElementNames()
    msgbox('\n'.join(nombres))


O acceder por nombre a la que nos interesa (getByName), tienes que validar (hasByName) primero que existe esta hoja.

    doc = desktop.getCurrentComponent()
    hojas = doc.getSheets()
    nombre = 'Hoja1'
    if hojas.hasByName(nombre):
        hoja = hojas.getByName(nombre)
    else:
        msgbox('No existe la hoja: %s' % nombre)


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.

    doc = desktop.getCurrentComponent()
    hojas = doc.getSheets()
    indice = 1
    hoja = hojas.getByIndex(indice)
    msgbox (hoja.getName())


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.

    doc = desktop.getCurrentComponent()
    hojas = doc.getSheets()
    indice = 1
    if indice < hojas.getCount():
        hoja = hojas.getByIndex(indice)
        msgbox (hoja.getName())
    else:
        msgbox(u'No existe este índice: %s' % indice)


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.

    doc = desktop.getCurrentComponent()
    hojas = doc.getSheets()
    for i in range(hojas.getCount()):
        msgbox(hojas.getByIndex(i).getName())


También es posible devolver la hoja activa.

    doc = desktop.getCurrentComponent()
    hoja = doc.getCurrentController().getActiveSheet()
    msgbox(hoja.getName())


Creamos una función genérica para devolver una hoja.

def devuelve_hoja(doc, nombre):
    if doc.getSheets().hasByName(nombre):
        return doc.getSheets().getByName(nombre)


Para usarse de forma sencilla.

    doc = desktop.getCurrentComponent()
    nombre = 'Hoja2'
    hoja = devuelve_hoja(doc, nombre)
    if hoja:
        msgbox(hoja.getName())
    else:
        msgbox('No se encontró la hoja: %s' % nombre)re)


Insertando hojas

Para insertar nuevas hojas, usamos el método: insertNewByName(Nombre, Posición), 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.

    hojas = doc.getSheets()
    hojas.insertNewByName('Nuevos datos', 0)


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.

    nombre = 'Nueva hoja'
    hojas = doc.getSheets()
    if not hojas.hasByName(nombre):
        hojas.insertNewByName(nombre, 0)
    nueva_hoja = doc.getSheets().getByName(nombre)
    doc.getCurrentController().setActiveSheet(nueva_hoja)


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.

Documentation note.png Es sumamente frecuente en programadores noveles, querer activar toda hoja que se quiera manipular, esto no es necesario, solo activala, si estas seguro que esto es lo que quieres


También podemos agregar la hoja al final de todas las demás.

    nombre = 'Otra hoja'
    hojas = doc.getSheets()
    if not hojas.hasByName(nombre):
        hojas.insertNewByName(nombre, hojas.getCount())
    nueva_hoja = doc.getSheets().getByName(nombre)
    doc.getCurrentController().setActiveSheet(nueva_hoja)


Observa entonces que el argumento posición puede tomar valores desde 0 y hasta el total de hojas devuelto por 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.

    activa = doc.getCurrentController().getActiveSheet()
    indice = activa.getRangeAddress().Sheet 
    msgbox(u'El índice de la hoja activa es: %s' % indice)


Que podemos convertir en una submacro. Nota como estamos estableciendo un valor por default para el ultimo argumento que será la posición deseada para la nueva hoja.

def nueva_hoja(doc, nombre, pos=0):
    hojas = doc.getSheets() 
    if not hojas.hasByName(nombre):
        activa = doc.getCurrentController().getActiveSheet()
        indice = activa.getRangeAddress().Sheet
        if pos == 1:
            pos = indice
        elif pos == 2:
            pos = indice + 1
        elif pos > 2:
            pos = hojas.getCount()
        hojas.insertNewByName(nombre, pos)
        return hojas.getByName(nombre)


Ahora ya podemos insertar una nueva hoja en la posición que sea.

    doc = desktop.getCurrentComponent()
 
    nombre = 'Al inicio'
    nueva = nueva_hoja(doc, nombre)
 
    nombre = 'Antes de la activa'
    nueva = nueva_hoja(doc, nombre, 1)
 
    nombre = 'Despues de la activa'
    nueva = nueva_hoja(doc, nombre, 2)
 
    nombre = 'Al final'
    nueva = nueva_hoja(doc, nombre, 3)

Borrando hojas

Para borrar hojas, usamos el método removeByName(Nombre), donde Nombre 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.

    hojas = doc.getSheets()
    hojas.removeByName('Hoja3')


Por supuesto no puedes borrar una hoja que no exista, así que verifícalo.

    nombre = 'Hoja2'
    hojas = doc.getSheets()
    if hojas.hasByName(nombre):
        hojas.removeByName(nombre)
    else:
        msgbox('No existe la hoja: %s' % nombre)


Puedes borrar la hoja activa.

    activa = doc.getCurrentController().getActiveSheet()
    hojas = doc.getSheets()
    hojas.removeByName(activa.getName())


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.

    nombre = 'borrame'
    hojas = doc.getSheets()
    if hojas.hasByName(nombre) and hojas.getCount() > 1:
        hojas.removeByName(nombre)
    else:
        msgbox('La hoja no existe o solo queda una')

Moviendo hojas

Para mover hojas usamos el método moveByName(NombreHoja, PosicionNueva), donde NombreHoja tiene que ser el nombre de una hoja existente. En el siguiente ejemplo movemos la hoja al inicio.

    hojas = doc.getSheets()
    hojas.moveByName('Hoja3', 0)


Ahora, la movemos al final.

    hojas = doc.getSheets()
    hojas.moveByName('Hoja3', hojas.getCount())


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.

    hojas = doc.getSheets()
    nombres = sorted(hojas.getElementNames())
    for i,v in enumerate(nombres):
        hojas.moveByName(v, i)

Copiando hojas

Para copiar hojas usamos el método copyByName(NombreHoja, NombreNuevo, Posicion) de la siguiente manera.

    hojas = doc.getSheets()
    hojas.copyByName('Hoja2', 'Nueva hoja2', 0)


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.

    nombre = 'Datos'
    nombre_nuevo = 'Datos nuevos'
    hojas = doc.getSheets()
    if hojas.hasByName(nombre) and not hojas.hasByName(nombre_nuevo):
        hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())
    else:
        msgbox('No se copio la hoja')


Podemos intentar copiar una hoja y asegurarnos de que el nombre no exista, tomando como base el nombre actual de la hoja, por ejemplo.

    hojas = doc.getSheets()
    nombre = doc.getCurrentController().getActiveSheet().getName()
    co1 = 1
    nombre_nuevo = '%s_%s' % (nombre, co1)
    while hojas.hasByName(nombre_nuevo):
        co1 += 1
        nombre_nuevo = '%s_%s' % (nombre, co1)
    hojas.copyByName(nombre, nombre_nuevo, hojas.getCount())
    hoja = hojas.getByName(nombre_nuevo)
    doc.getCurrentController().setActiveSheet(hoja)

Renombrando hojas

Para renombrar hojas usamos el método setName(NuevoNombre), de la siguiente manera.

    hojas = doc.getSheets()
    hojas.getByName('Hola').setName('Prueba')


También puedes usar el índice para referirte a la hoja.

    hojas = doc.getSheets()
    hojas.getByIndex(0).setName('Prueba')


Es recomendable validar que la hoja a renombrar exista y que el nuevo nombre no.

    hojas = doc.getSheets()
    actual = 'Resumen'
    nuevo = 'Terminado'
    # Validamos que la hoja exista y el nuevo nombre no
    if hojas.hasByName(actual) and not hojas.hasByName(nuevo):
        hojas.getByName(actual).setName(nuevo)
    else:
        msgbox('No es posible renombrar la hoja')


Solo para divertirnos, cambiamos los nombres de las hojas por números.

    hojas = doc.getSheets()
    for i in range(hojas.getCount()):
        hojas.getByIndex(i).setName(i+1)


Ahora por letras, el código siguiente podría fallar en algunas circunstancias, tu tarea es decirnos ¿porqué? y corregirlo.

    hojas = doc.getSheets()
    for i in range(hojas.getCount()):
        hojas.getByIndex(i).setName(chr(i+65))


O los meses del año:

import uno
import datetime
import locale
locale.setlocale(locale.LC_ALL, '')
 
def pruebas():
    ctx = uno.getComponentContext()
    sm = ctx.getServiceManager()
 
    desktop = sm.createInstanceWithContext('com.sun.star.frame.Desktop', ctx)
    doc = desktop.getCurrentComponent()
 
    hojas = doc.getSheets()
    for i in range(hojas.getCount()):
        hojas.getByIndex(i).setName(datetime.date(2013, i+1, 1).strftime('%B'))
    return


Observa que hacemos uso de dos nuevas librerias de Python, datetime que tiene muchas utiles funciones para trabajar con fechas y tiempo, y locale para que los meses nos salgan en español.

Ocultando y mostrando hojas

Mostrar y ocultar hojas es muy sencillo, solo hay que establecer su propiedad IsVisible en verdadero (True) o falso (False) según se requiera de la siguiente manera.

    activa = doc.getCurrentController().getActiveSheet()
    activa.IsVisible = False


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.

    hoja = doc.getSheets().getByIndex(1)
    hoja.IsVisible = not hoja.IsVisible
    doc.getCurrentController().setActiveSheet(hoja)


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.

    hojas = doc.getSheets()
 
    activa = doc.getCurrentController().getActiveSheet().getRangeAddress().Sheet
    for i in range(hojas.getCount()):
        if i != activa:
            hojas.getByIndex(i).IsVisible = False


Tu tarea es hacer la función inversa, muestra todas las hojas ocultas.

Protección y desprotección de hojas

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 protect(contraseña), 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.

    activa = doc.getCurrentController().getActiveSheet()
    activa.protect('letmein')


Y para desproteger, usamos el método unprotect(contraseña), 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 isProtected, si es verdadera (True) la hoja sigue protegida, si es falsa (False), la hoja esta desprotegida.

    activa = doc.getCurrentController().getActiveSheet()
    if activa.isProtected():
        msgbox('Hoja protegida, se va a desproteger')
        activa.unprotect('letmein')
        if activa.isProtected():
            msgbox('Contraseña incorrecta')
        else:
            msgbox('Hoja desprotegida correctamente')
    else:
        msgbox('La hoja no esta protegida')


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.



ES.Plantillas.Logo foro es.png
Si tienes dudas acerca de lo aquí explicado, tienes algún problema con AOO,
o quieres ampliar la información, no dudes en dirigirte al

Foro Oficial en español de Apache OpenOffice para Macros y API UNO

Personal tools