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

From Apache OpenOffice Wiki
< ES‎ | Manuales‎ | GuiaAOO‎ | TemasAvanzados‎ | Macros‎ | Python‎ | PythonCalc
Jump to: navigation, search
Line 125: Line 125:
 
Esta estructura ('''getRangeAddress''') 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.
 
Esta estructura ('''getRangeAddress''') 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.
  
 +
 +
== Referencia a varios rangos de celdas ==
 +
 +
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 '''contenedor''' de estos rangos, veamos como.
 +
<source lang=python>
 +
    desktop = sm.createInstanceWithContext('com.sun.star.frame.Desktop', ctx)
 +
    doc = desktop.getCurrentComponent()
 +
   
 +
    activa = doc.getCurrentController().getActiveSheet()   
 +
    #~ Creamos el contender para los rangos
 +
    rangos = doc.createInstance('com.sun.star.sheet.SheetCellRanges')
 +
    #~ Creamos la estructura CellRangeAddress necesaria
 +
    dir_rango = activa.getCellRangeByName('A1:B2').getRangeAddress()
 +
    #~ Y lo agregamos al contenedor de rangos
 +
    rangos.addRangeAddress(dir_rango, False)
 +
    #~ Aquí solo hacemos referencia al rango
 +
    rango = activa.getCellRangeByName('E1:G2')
 +
    #~ Y lo agregamos al contenedor de rangos, nota como tenemos que usar
 +
    #~ el método getRangeAddress para pasarle el argumento correcto
 +
    rangos.addRangeAddress(rango.getRangeAddress(), False)
 +
    #~ Aquí agregamos un rango directamente al contenedor
 +
    #~ toma en cuenta que se van acumulando
 +
    rangos.addRangeAddress(activa.getCellRangeByName('D4:E5').getRangeAddress() , False)
 +
 +
    #~ Comprobamos que están correctos seleccionándolos
 +
    doc.getCurrentController().select(rangos)
 +
</source>
 +
 +
No te confundas, las tres líneas donde se agrega el rango con el método '''addRangeAddress()''' 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.
 +
 +
Por supuesto, también de estos rangos podemos obtener información, por ejemplo, los nombres de los rangos que contiene,
 +
<source lang=python>
 +
    activa = doc.getCurrentController().getActiveSheet()   
 +
    #~ Creamos el contender para los rangos
 +
    rangos = doc.createInstance('com.sun.star.sheet.SheetCellRanges')
 +
 +
    #~ Agregamos los rangos que queramos
 +
    rangos.addRangeAddress(activa.getCellRangeByName('A1:A2').getRangeAddress(), False)
 +
    rangos.addRangeAddress(activa.getCellRangeByName('B4:B5').getRangeAddress(), False)
 +
    rangos.addRangeAddress(activa.getCellRangeByName('C7:C8').getRangeAddress(), False)
 +
    rangos.addRangeAddress(activa.getCellRangeByName('D10:D11').getRangeAddress(), False)
 +
    rangos.addRangeAddress(activa.getCellRangeByName('E13:E14').getRangeAddress(), False)
 +
 +
    #~ Mostramos las direcciones de los rangos
 +
    msgbox(rangos.getRangeAddressesAsString())
 +
</source>
 +
 +
Nota como los rangos es una cadena larga de las direcciones de los rangos separados por un ''';''', si lo quieres mejor presentable, reemplaza los puntos y comas por un salto de línea con el siguiente código.
 +
<source lang=python>
 +
    #~ Mostramos las direcciones de los rangos
 +
    message = rangos.getRangeAddressesAsString().replace(';', '\n')
 +
    msgbox(message)
 +
</source>
  
 
[[Category:ES]]
 
[[Category:ES]]
 
[[Category:Manuales]]
 
[[Category:Manuales]]
 
[[Category:ES/Python]]
 
[[Category:ES/Python]]

Revision as of 03:56, 22 May 2013


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.


Referencia a celdas individuales

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.

    activa = doc.getCurrentController().getActiveSheet()
    # Referencia a la celda E5
    celda = activa.getCellRangeByName('E5')
    # Mostramos el contenido de la celda
    msgbox (celda.getString())
    # Mostramos direccion de esta celda
    ca = celda.getCellAddress()
    message = u'Columna: %s\nFila: %s\nHoja: %s' % (ca.Column, ca.Row, ca.Sheet)
    msgbox (message)


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 com.sun.star.table.CellAddress, 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 integer que también empieza en 0) donde esta la celda referenciada, la columna (long) y la fila (long) de esta celda.

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.

    activa = doc.getCurrentController().getActiveSheet()
 
    col = 9
    fil = 14
    if col < activa.getColumns().getCount() and fil < activa.getRows().getCount():
        celda = activa.getCellByPosition(col, fil)
        msgbox (celda.getString())
    else:
        msgbox('Valores incorrectos')


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.

import uno
import datetime
 
def pruebas():
    ctx = uno.getComponentContext()
    sm = ctx.getServiceManager()
 
    desktop = sm.createInstanceWithContext('com.sun.star.frame.Desktop', ctx)
    doc = desktop.getCurrentComponent()
 
    activa = doc.getCurrentController().getActiveSheet()
    activa.getCellRangeByName('A1').setString(datetime.date.today().year)
    for i in range(1,13):
        activa.getCellByPosition(0, i).setString(datetime.date(2013, i, 1).strftime('%B'))
 
    return


Observa que hemos estado usando el método getString() para obtener el contenido de una celda y setString(cadena) 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.


Referencia a un rango de celdas

Podemos acceder a un rango de celdas por su nombre, usando el mismo método usado para acceder a una celda.

    activa = doc.getCurrentController().getActiveSheet()
    rango = activa.getCellRangeByName('A1:E5')
    doc.getCurrentController().select(rango)


Para acceder a un rango de celdas por su posición, hay que usar un método diferente: getCellRangeByPosition, que requiere de cuatro argumentos.

    activa = doc.getCurrentController().getActiveSheet()    
    # Seleccionamos el rango B1:C10
    rango = activa.getCellRangeByPosition(1, 0, 2, 9)
    doc.getCurrentController().select(rango)


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.

Otra posibilidad, es usar nombres definidos de rangos, es decir, aquellos que establecemos desde el Cuadro de nombre 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ú 'Insertar | Nombres | Definir...' cuya teclas de acceso rápido son  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.

    activa = doc.getCurrentController().getActiveSheet()    
    rango = activa.getCellRangeByName('Datos')
    doc.getCurrentController().select(rango)


Este método no es sensible a mayúsculas o minúsculas. Observa como primero obtenemos una referencia a la interfaz com.sun.star.sheet.XNamedRanges y dado que esta hereda la interfaz com.sun.star.container.XNameAccess podemos usar el método getElementNames 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.

    nr = doc.NamedRanges
    nombre = 'Datos'
    nombres_rangos = nr.getElementNames()
 
    if nombre in nombres_rangos:
        rango = nr.getByName(nombre).getReferredCells()
        doc.getCurrentController().select(rango)
    else:
        msgbox(u'No existe el rango: %S' % nombre)


No confundas estos nombres de rangos, con los que puedes establecer en el menú Datos | Definir rango..., 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.

De los rangos de celdas, también es posible obtener información, para ello se hace uso de la estructura com.sun.star.table.CellRangeAddress a través del método getRangeAddress 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.

    activa = doc.getCurrentController().getActiveSheet()    
    rango = activa.getCellRangeByName('Datos')
    ra = rango.getRangeAddress()
 
    message = """
    El rango esta en la hoja: %s
    Columna inicio: %s
    Fila Inicio: %s
    Columna final: %s
    Fila final: %s
    """ % (ra.Sheet, ra.StartColumn, ra.StartRow, ra.EndColumn, ra.EndRow)
 
    msgbox(message)


Esta estructura (getRangeAddress) 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.


Referencia a varios rangos de celdas

Cuando en la interfaz del usuario, hacemos la selección de un rango y mantenemos presionada la tecla  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 contenedor de estos rangos, veamos como.

    desktop = sm.createInstanceWithContext('com.sun.star.frame.Desktop', ctx)
    doc = desktop.getCurrentComponent()
 
    activa = doc.getCurrentController().getActiveSheet()    
    #~ Creamos el contender para los rangos
    rangos = doc.createInstance('com.sun.star.sheet.SheetCellRanges')
    #~ Creamos la estructura CellRangeAddress necesaria
    dir_rango = activa.getCellRangeByName('A1:B2').getRangeAddress()
    #~ Y lo agregamos al contenedor de rangos
    rangos.addRangeAddress(dir_rango, False)
    #~ Aquí solo hacemos referencia al rango
    rango = activa.getCellRangeByName('E1:G2')
    #~ Y lo agregamos al contenedor de rangos, nota como tenemos que usar
    #~ el método getRangeAddress para pasarle el argumento correcto
    rangos.addRangeAddress(rango.getRangeAddress(), False)
    #~ Aquí agregamos un rango directamente al contenedor
    #~ toma en cuenta que se van acumulando 
    rangos.addRangeAddress(activa.getCellRangeByName('D4:E5').getRangeAddress() , False)
 
    #~ Comprobamos que están correctos seleccionándolos
    doc.getCurrentController().select(rangos)

No te confundas, las tres líneas donde se agrega el rango con el método addRangeAddress() 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.

Por supuesto, también de estos rangos podemos obtener información, por ejemplo, los nombres de los rangos que contiene,

    activa = doc.getCurrentController().getActiveSheet()    
    #~ Creamos el contender para los rangos
    rangos = doc.createInstance('com.sun.star.sheet.SheetCellRanges')
 
    #~ Agregamos los rangos que queramos
    rangos.addRangeAddress(activa.getCellRangeByName('A1:A2').getRangeAddress(), False)
    rangos.addRangeAddress(activa.getCellRangeByName('B4:B5').getRangeAddress(), False)
    rangos.addRangeAddress(activa.getCellRangeByName('C7:C8').getRangeAddress(), False)
    rangos.addRangeAddress(activa.getCellRangeByName('D10:D11').getRangeAddress(), False)
    rangos.addRangeAddress(activa.getCellRangeByName('E13:E14').getRangeAddress(), False)
 
    #~ Mostramos las direcciones de los rangos
    msgbox(rangos.getRangeAddressesAsString())

Nota como los rangos es una cadena larga de las direcciones de los rangos separados por un ;, si lo quieres mejor presentable, reemplaza los puntos y comas por un salto de línea con el siguiente código.

    #~ Mostramos las direcciones de los rangos
    message = rangos.getRangeAddressesAsString().replace(';', '\n')
    msgbox(message)
Personal tools