From 70e193353701d03d3183012098b063aa1200d54c Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 24 Apr 2023 00:15:16 -0600 Subject: [PATCH] Add shape --- doc/docs/calc/cells.md | 601 +++++++++++++++++++++++++++++++ doc/docs/calc/index.md | 394 ++++++++++++++++++++ doc/docs/calc/ranges.md | 175 +++++++++ doc/docs/calc/sheets.md | 354 ++++++++++++++++++ doc/docs/dp/drawpage.md | 109 ++++++ doc/docs/dp/shapes.md | 7 + doc/mkdocs.yml | 8 + source/easymacro/__init__.py | 1 + source/easymacro/easycalc.py | 59 ++- source/easymacro/easydrawpage.py | 5 +- source/easymacro/easyevents.py | 5 +- source/easymacro/easyshape.py | 18 + 12 files changed, 1718 insertions(+), 18 deletions(-) create mode 100644 doc/docs/calc/cells.md create mode 100644 doc/docs/calc/index.md create mode 100644 doc/docs/calc/ranges.md create mode 100644 doc/docs/calc/sheets.md create mode 100644 doc/docs/dp/drawpage.md create mode 100644 doc/docs/dp/shapes.md diff --git a/doc/docs/calc/cells.md b/doc/docs/calc/cells.md new file mode 100644 index 0000000..9e405c0 --- /dev/null +++ b/doc/docs/calc/cells.md @@ -0,0 +1,601 @@ + +## Trabajar con celdas y rangos + +--- + +### **address** + +Referencia por dirección. + +```py + hoja = app.active.active + celda = hoja['A1'] + rango = hoja['C10:D15'] + + app.debug(celda) + app.debug(rango) +``` + +
+ +### **doc** + +Devuelve el documento padre. + +```py + hoja = app.active.active + rango = hoja['A1:C5'] + + doc = rango.doc + app.debug(doc) +``` + +
+ +### **in** + +Verificar si un rango esta dentro de otro. + +```py + hoja = app.active.active + + celda = hoja['C5'] + rango = hoja['A1:E10'] + + resultado = celda in rango + app.debug(resultado) + + celda = hoja['C50'] + resultado = celda in rango + app.debug(resultado) +``` + +
+ +### **iter** + +Iterar cada celda de un rango. + +```py + hoja = app.active.active + rango = hoja['B10:C15'] + + for celda in rango: + app.debug(celda) +``` + +
+ +### **position** + +Referencia por posición. + +Para celdas: `HOJA[fila,columna]` + +Para rangos: `HOJA[fila_inicial:fila_final, columna_inicial:columna_final]` + +```py + hoja = app.active.active + + # ~ Cell A10 + celda = hoja[9,0] + + # ~ Range A1:C10 + rango = hoja[0:10,0:3] +``` + +!!! tip "Atención" + + Recuerde que las filas y columnas empiezan en cero, por lo que `fila_final` y la `columna_final` deben de ser la fila y columna deseada más 1. + +
+ +### **selection** + +Referencia por selección actual. + +```py + seleccion = app.active.selection + app.debug(seleccion) +``` + +!!! tip "Atención" + + Recuerde que la selección actual pueden ser varias cosas diferentes. + +
+ +## Propiedades + +--- + +### **address** + +Devuelve la dirección de la celda como una estructura: `com.sun.star.table.CellAddress` + +```py + hoja = app.active.active + + celda = hoja['A1'] + if celda.is_cell: + app.debug(celda.address) +``` + +
+ +### **back_color** + +Devuelve o aplica el color de fondo del rango. + +```py + hoja = app.active.active + + rango = hoja['A1:E10'] + rango.back_color = 'red' +``` + +
+ +### **current_region** + +Devuelve la región actual. + +```py + hoja = app.active.active + + celda = hoja['A1'] + rango = celda.current_region + app.debug(rango) +``` + +
+ +### **data** + +Alias de `data_array` al obtener los datos. Al establecer los datos, si es un rango se comporta como `data_array`, pero si es una celda, se autoajusta al tamaño de los datos. + +```py + hoja = app.active.active + celda = hoja['A1'] + datos = ( + (1, 'Uno'), + (2, 'Dos'), + (3, 'Tres'), + ) + + celda.data = datos + app.debug(celda.current_region.data) +``` + +!!! warning "Cuidado" + + Siempre valide que haya suficientes celdas libres para los datos para evitar sobreescribirlos. + +
+ +### **data_array** + +Devuelve o establece los datos de un rango. Es un alias de `DataArray`. + +```py + rango = app.active.selection + + datos = rango.data_array + app.debug(datos) + rango.data_array = datos +``` + +!!! warning "Cuidado" + + El tamaño de los datos, debe ser **exactamente** del tamaño del rango destino. De lo contrario obtendrá un error. + +
+ +### **date** + +Devuelve o establece el contenido de la celda como fecha. + +```py + hoja = app.active.active + celda = hoja['A1'] + celda.date = app.dates.date(1974, 1, 15) + app.debug(type(celda.date), celda.date) +``` + +``` +20/08/2022 18:38:53 - DEBUG - 1974-01-15 +``` + +
+ +### **datetime** + +Devuelve o establece el contenido de la celda como fecha y tiempo. + +```python + hoja = app.active.active + celda = hoja['A1'] + celda.datetime = app.dates.datetime(1974, 1, 15, 10, 11, 12) + app.debug(type(celda.datetime), celda.datetime) +``` + +
+ +### **dict** + +Devuelve o establece los datos como diccionarios. Automáticamente ajusta el rango al tamaño de los datos. + +```py + hoja = app.active.active + celda = hoja['A1'] + + datos = ( + {'No': 1, 'Nombre': 'Ingrid'}, + {'No': 2, 'Nombre': 'Sophia'}, + {'No': 3, 'Nombre': 'Scarlette'}, + ) + + celda.dict = datos + app.debug(celda.current_region.dict) +``` + +!!! warning "Consejo" + + Siempre valide que haya suficientes celdas libres para los datos para evitar sobreescribirlos, a menos que eso sea lo que realmente quiera. + +
+ +### **error** + +Si la celda tiene una formula con error, devuelve el número de error. + +```py + hoja = app.active.active + celda = hoja['A1'] + celda.value = '=RAND()/0' + app.debug(celda.error) +``` + +
+ +### **float** + +Devuelve o establece el contenido de la celda como valor. + +```py + hoja = app.active.active + celda = hoja['A1'] + celda.float = 12345 + app.debug(celda.type, celda.float) +``` + +
+ +### **formula** + +Devuelve o establece la formula de la celda. + +```py + hoja = app.active.active + celda = hoja['A1'] + celda.formula = '=RAND()' + app.debug(celda.type, celda.formula) +``` + +
+ +### **formula_array** + +Devuelve o establece los datos de un rango. Es un alias de `FormulaArray`. + +```py + rango = app.active.selection + + datos = rango.data_array + app.debug(datos) + datos = rango.formula_array + app.debug(datos) + rango.formula_array = datos +``` + +!!! tip "Consejo" + + **data_array** devolverá los resultados de las celdas con formulas. **formula_array** devolverá las formulas en dichas celdas. + +
+ +### **is_cell** + +Verdadero (True) si el objeto es de una celda. + +```py + hoja = app.active.active + + celda = hoja['A1'] + app.debug(celda.is_cell) + + rango = hoja['A1:C5'] + app.debug(rango.is_cell) +``` + +
+ +### **is_range** + +Verdadero (True) si el objeto es de un rango. + +```py + hoja = app.active.active + + celda = hoja['A1'] + app.debug(celda.is_range) + + rango = hoja['A1:C5'] + app.debug(rango.is_range) +``` + +
+ +### **len** + +Devolver el tamaño del rango en filas y columnas. + +```py + hoja = app.active.active + + rango = hoja['A1:E100'] + filas = len(rango) + columnas = rango.len_columns + app.debug(filas, columnas) +``` + +
+ +### **name** + +Devuelve la dirección de la celda o rango como texto. + +```py + hoja = app.active.active + + celda = hoja['A1'] + app.debug(celda.name) + + rango = hoja['A1:C5'] + app.debug(rango.name) +``` + +
+ +### **next_free** + +Devuelve la siguiente celda libre después de la región actual. + +```py + hoja = app.active.active + celda = hoja['A1'] + + celda_libre = celda.next_free + app.debug(celda_libre) +``` + +
+ +### **range_address** + +Devuelve la dirección del rango como una estructura: `com.sun.star.table.CellRangeAddress` + +```py + hoja = app.active.active + + rango = hoja['A1:C5'] + if rango.is_range: + app.debug(rango.range_address) +``` + +
+ +### **range_data** + +Devuelve la región actual del rango excepto la primer fila. + +```py + hoja = app.active.active + + celda = hoja['A1'] + rango = celda.range_data + app.debug(rango) +``` + +
+ +### **sheet** + +Devuelve la hoja padre. + +```py + hoja = app.active.active + rango = hoja['A1:C5'] + + hoja = rango.sheet + app.debug(hoja) +``` + +
+ +### **string** + +Devuelve o establece el contenido de la celda como texto. + +```py + hoja = app.active.active + + celda = hoja['A1'] + celda.string = 'Maldito Mundo' + app.debug(celda.type, celda.string) + + celda = hoja['A2'] + celda.string = 12345 + app.debug(celda.type, celda.string) +``` + +
+ +### **style** + +Devuelve o aplica el estilo de celda. + +```py + hoja = app.active.active + rango = hoja['A1:C5'] + rango.style = 'Good' +``` + +
+ +### **time** + +Devuelve o establece el contenido de la celda como tiempo. + +```py + hoja = app.active.active + celda = hoja['A1'] + celda.time = app.dates.time(10, 11, 12) + app.debug(type(celda.time), celda.time) +``` + +
+ +### **type** + +Devuelve el tipo de contenido de la celda: texto, número o formula. + +```py + hoja = app.active.active + celda = hoja['A1'] + app.debug(celda.type) +``` + +!!! tip "Consejo" + + Asegurese de que la selección siempre sea una sola celda. + +
+ +### **value** + +Devuelve o establece el valor de la celda, estableciendo el tipo de dato automáticamente. + +```py + hoja = app.active.active + + celda = hoja['A1'] + celda.value = 'Soy Texto' + app.debug(celda.type, celda.value) + + celda = hoja['A2'] + celda.value = 12345 + app.debug(celda.type, celda.value) + + celda = hoja['A3'] + celda.value = '=RAND()' + app.debug(celda.type, celda.value) + + celda = hoja['A4'] + celda.value = app.dates.date(1974, 1, 15) + app.debug(celda.type, celda.value) +``` + +```sh +23/04/2023 19:49:05 - DEBUG - Soy Texto +23/04/2023 19:49:05 - DEBUG - 12345.0 +23/04/2023 19:49:05 - DEBUG - =RAND() +23/04/2023 19:49:05 - DEBUG - 27044.0 +``` + +
+ +## Métodos + +--- + +### **clear** + +Limpia el rango. Por default solo borra datos. Mire [API CellFlags][1] para más información. + +```python + rango.clear() +``` + +Para borrar todo. +```python + rango.clear(app.ALL) +``` + +
+ +### **len** + +Devuelve el tamaño en filas y columnas del rango. + +```py + hoja = app.active.active + + rango = hoja['A1:C100'] + filas, columnas = rango.len() + app.debug(filas, columnas) +``` + +
+ +### **offset** + +Devuelve la celda inmediata a la derecha en la misma fila. + +```py + cell = app.active.active['A1'] + app.debug(cell) + cell = cell.offset() + app.debug(cell) +``` + +``` +23/04/2023 21:22:15 - DEBUG - Cell: $Sheet1.$A$1 +23/04/2023 21:22:15 - DEBUG - Cell: $Sheet1.$B$1 +``` + +Se puede establecer la distancia a la celda a devolver en filas y columnas. + +```py + cell = app.active.active['A1'] + app.debug(cell) + cell = cell.offset(4,2) + app.debug(cell) +``` + +``` +23/04/2023 21:24:59 - DEBUG - Cell: $Sheet1.$A$1 +23/04/2023 21:24:59 - DEBUG - Cell: $Sheet1.$C$5 +``` + +
+ +### **to_size** + +Espande el tamaño del rango actual tantas filas y columnas se pasen como argumentos. + +```py + cell = app.active.active['A1'] + app.debug(cell) + cell = cell.to_size(10,5) + app.debug(cell) +``` + +``` +23/04/2023 21:30:56 - DEBUG - Cell: $Sheet1.$A$1 +23/04/2023 21:30:56 - DEBUG - Range: $Sheet1.$A$1:$E$10 +``` + +
+ +[1]: https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1sheet_1_1CellFlags.html \ No newline at end of file diff --git a/doc/docs/calc/index.md b/doc/docs/calc/index.md new file mode 100644 index 0000000..5c56c8f --- /dev/null +++ b/doc/docs/calc/index.md @@ -0,0 +1,394 @@ +--- +title: Documento +--- + +Devolver el documento activo. + +### **active** + +```py + doc = app.active +``` + +
+ +## Propiedades + +--- + +### **active** + +Devuelve la hoja activa. + +```py + doc = app.active + hoja = doc.active + app.debug(hoja) +``` + +
+ +### **headers** + +Mostrar u ocultar encabezados de filas y columnas. + +```py + doc = app.active + app.msgbox(doc.headers) + doc.headers = not doc.headers + app.msgbox(doc.headers) + doc.headers = not doc.headers +``` + +
+ +### **names** + +Devolver una tupla con los nombres de todas las hojas. + +```py + doc = app.active + nombres = doc.names + app.debug(nombres) +``` + +
+ +### **selection** + +Devolver la selección activa. + +!!! warning inline end "Cuidado" + + La selección actual pueden ser muchas cosas diferentes. + +```py + doc = app.active + seleccion = doc.selection + app.debug(seleccion) +``` + +
+ +### **tabs** + +Mostrar u ocultar las pestañas de las hojas. + +```py + doc = app.active + app.msgbox(doc.tabs) + doc.tabs = not doc.tabs + app.msgbox(doc.tabs) + doc.tabs = not doc.tabs +``` + +
+ +## Métodos + +--- + +### **activate** + +Activar hoja, argumento como objeto. + +```py + doc = app.active + hoja = doc[-1] + doc.activate(hoja) +``` + +Activar hoja por nombre. + +```py + doc = app.active + doc.activate('Hoja3') +``` + +
+ +### **copy** + +Copiar hoja dentro del mismo documento. + +```py + doc = app.active + hoja = doc[0] + + doc.copy_sheet(hoja, 'Otra hoja') +``` + +Por nombre. + +```py + doc.copy_sheet('Hoja1', 'Nueva Hoja') +``` + +Si no se establece el nuevo nombre, se generá de forma automática: `nombre + índice`. + +```py + doc.copy_sheet(hoja) +``` + +
+ +### **copy_from** + +Copiar hojas de otro documento. Copiar con el mismo nombre. + +```py + doc = app.active + documento_origen = app.docs['Contactos.ods'] + nombre_origen = 'Nombres' + + doc.copy_from(documento_origen, nombre_origen) +``` + +Copiar con un nuevo nombre. + +```py + doc.copy_from(documento_origen, nombre_origen, 'NuevoNombre') +``` + +Si solo se establece el documento origen, se copian todas las hojas. + + +```py + doc.copy_from(documento_origen) +``` + +!!! info "Información" + + Si algún nombre de hoja en el origen existe en el destino, se copiará con un nuevo índice concatenado el nombre origen. + +
+ +### **insert** + +Inserta una nueva hoja, se devuelve la hoja insertada. + +```py + doc = app.active + hoja = doc.insert('HojaInsertada') +``` + +Insertar varias hojas. Devolverá la última insertada. + +```py + nombres = ('Enero', 'Febrero', 'Marzo') + hoja = doc.insert(nombres) + app.debug(hoja) +``` + +Creando una nueva instancia y asignandola. + +```py + doc = app.active + doc['NuevaHoja'] = doc.new_sheet() +``` + +!!! warning "Cuidado" + + Si la hoja existe, obtendrá un error, verifique siempre que no exista primero. + +
+ +### **move** + +Mover hojas. + +Pasar la hoja como objeto, de forma predetermianda se mueve a la última posición. + +```py + doc = app.active + hoja = doc[0] + doc.move(hoja) +``` + +!!! info "Información" + + Al mover una hoja, cambian sus índices. + +Pasar la hoja por nombre. + +```py + doc = app.active + doc.move('Hoja1') +``` + +Especificar la posición destino. + +```py + doc = app.active + hoja = doc[0] + doc.move(hoja, 2) +``` + +
+ +### **remove** + +!!! warning "Cuidado" + + Siempre debe haber al menos una hoja en un documento. + +Eliminar hoja por índice. + +```py + doc = app.active + sheet = doc[0] + + doc.remove(sheet) +``` + +Eliminar por nombre. + +```py + doc.remove('Hoja2') +``` + +
+ +### **start_range_selection** + +Permitir al usuario seleccionar un rango. Es necesario pasarle una clase con el nombre que prefiera (`Eventos` es recomendable) con dos métodos para procesar la captura como en el siguiente ejemplo: + +```py +class Eventos(): + + def __init__(self, doc): + self.doc = doc + + def range_selection_done(self, range_selection): + if range_selection: + app.debug(range_selection) + self.doc.remove_range_selection_listener() + return + + def range_selection_aborted(self): + self.doc.remove_range_selection_listener() + return + + +def main(): + doc = app.active + doc.start_range_selection(Eventos) + return +``` + +
+ +### **select** + +Seleccionar una celda o rango. + +```py + doc = app.active + cell = doc[0]['A1'] + doc.select(cell) +``` + +!!! tip "Consejo" + + **No es necesario** seleccionar celdas o rangos para manipularlos. + +
+ +### **sort** + +Ordenar hojas en orden alfabetico. + +```py + doc = app.active + doc.sort() +``` + +Ordenar de forma inversa. + +```py + doc = app.active + doc.sort(True) +``` + +
+ +## Eventos + +--- + +Obtener una tupla con los eventos soportados por el documento. + +```py + doc = app.active + nombres = doc.events.names + for nombre in nombres: + app.debug(nombre) +``` + +```sh +23/04/2023 13:54:10 - DEBUG - OnStartApp +23/04/2023 13:54:10 - DEBUG - OnCloseApp +23/04/2023 13:54:10 - DEBUG - OnCreate +23/04/2023 13:54:10 - DEBUG - OnNew +23/04/2023 13:54:10 - DEBUG - OnLoadFinished +23/04/2023 13:54:10 - DEBUG - OnLoad +23/04/2023 13:54:10 - DEBUG - OnPrepareUnload +23/04/2023 13:54:10 - DEBUG - OnUnload +23/04/2023 13:54:10 - DEBUG - OnSave +23/04/2023 13:54:10 - DEBUG - OnSaveDone +23/04/2023 13:54:10 - DEBUG - OnSaveFailed +23/04/2023 13:54:10 - DEBUG - OnSaveAs +23/04/2023 13:54:10 - DEBUG - OnSaveAsDone +23/04/2023 13:54:10 - DEBUG - OnSaveAsFailed +23/04/2023 13:54:10 - DEBUG - OnCopyTo +23/04/2023 13:54:10 - DEBUG - OnCopyToDone +23/04/2023 13:54:10 - DEBUG - OnCopyToFailed +23/04/2023 13:54:10 - DEBUG - OnFocus +23/04/2023 13:54:10 - DEBUG - OnUnfocus +23/04/2023 13:54:10 - DEBUG - OnPrint +23/04/2023 13:54:10 - DEBUG - OnViewCreated +23/04/2023 13:54:10 - DEBUG - OnPrepareViewClosing +23/04/2023 13:54:10 - DEBUG - OnViewClosed +23/04/2023 13:54:10 - DEBUG - OnModifyChanged +23/04/2023 13:54:10 - DEBUG - OnTitleChanged +23/04/2023 13:54:10 - DEBUG - OnVisAreaChanged +23/04/2023 13:54:10 - DEBUG - OnModeChanged +23/04/2023 13:54:10 - DEBUG - OnStorageChanged +``` + +
+ +### Asignar una macro a un evento. + +```py +def doc_on_focus(event): + app.debug('Documento activado...') + return + + +def main(): + doc = app.active + events = doc.events + if 'OnFocus' in events: + macro = {'library': 'test', 'name': 'doc_on_focus'} + events['OnFocus'] = macro + return +``` + +
+ +### Eliminar la asignación del evento. + +```py + doc = app.active + doc.events['OnFocus'] = {} +``` + +O + +```python + doc = app.active + doc.events.remove('OnFocus') +``` + +
\ No newline at end of file diff --git a/doc/docs/calc/ranges.md b/doc/docs/calc/ranges.md new file mode 100644 index 0000000..6584231 --- /dev/null +++ b/doc/docs/calc/ranges.md @@ -0,0 +1,175 @@ +## Trabajar con conjuntos de rangos + +--- + +### **address** + +Referencia a un rango por su dirección. + +```py + rango = rangos['Hoja1.A1:B5'] + app.debug(rango) +``` + +
+ +### **in** + +Verificar si un rango esta en la colección. + +```py + doc = app.active + hoja = doc.active + rangos = doc.selection + + resultado = hoja['D5:F10'] in rangos + app.debug(resultado) +``` + +
+ +### **index** + +Referencia a un rango por índice. + +```py + doc = app.active + rangos = doc.selection + + rango = rangos[1] + app.debug(rango) +``` + +
+ +### **iter** + +Iterar entre los rangos. + +```py + doc = app.active + for rango in doc.selection: + app.debug(rango) +``` + +```sh +20/08/2022 13:27:03 - DEBUG - Range: $Sheet1.$B$4:$D$7 +20/08/2022 13:27:03 - DEBUG - Range: $Sheet1.$G$10:$H$14 +``` + +
+ +### **len** + +Contar los rangos en la colección. + +```py + doc = app.active + contar = len(doc.selection) + app.debug(contar) +``` + +
+ +### **selection** + +Obtener una referencia desde la selección actual. Deben de estar seleccionados más de un rango de celdas. + +```py + doc = app.active + seleccion = doc.selection + app.debug(seleccion) +``` + +```sh +20/08/2022 13:21:17 - DEBUG - Ranges: ('Sheet1.A5:C8', 'Sheet1.E11:F14') +``` + +
+ +## Propiedades + +--- + +### **data** + +Devolver y establecer datos. + +```py + doc = app.active + rangos = doc.selection + + datos = rangos.data + app.debug(datos) + rangos.data = datos +``` + +!!! warning "Cuidado" + + Al asignar esta propiedad, cada matriz de datos debe tener exactamente el mismo tamaño del rango destino. + +
+ +### **names** + +Devolver las direcciones de los rangos. + +```py + doc = app.active + rangos = doc.selection + + nombres = rangos.names + app.debug(nombres) +``` + +
+ +### **style** + +Establecer el estilo de todos los rangos de la colección. + +```py + doc = app.active + rangos = doc.selection + rangos.style = 'Good' +``` + +
+ +## Métodos + +--- + +### **add** + +```py + doc = app.active + hoja = doc.active + + rangos = doc.ranges() + rangos.add(hoja['A1:B2']) + rangos.add(hoja['D5:F10']) + app.debug(rangos) +``` + +
+ +### **ranges** + +Crear un nuevo contender de rangos vacío. + +```py + doc = app.active + rangos = doc.ranges() + app.debug(rangos) +``` + +
+ +### **remove** + +```py + rangos.remove(hoja['A1:B2']) +``` + +
\ No newline at end of file diff --git a/doc/docs/calc/sheets.md b/doc/docs/calc/sheets.md new file mode 100644 index 0000000..095aab4 --- /dev/null +++ b/doc/docs/calc/sheets.md @@ -0,0 +1,354 @@ +--- +title: Hojas +--- + +## Trabajar con hojas + +--- + +### Referencia por **índice** + +```py + doc = app.active + hoja = doc[0] + app.debug(hoja.name) +``` + + +### Referencia por **nombre** + +```py + doc = app.active + hoja = doc['datos'] + app.debug(hoja.name) +``` + +### **in** + +Verificar por nombre si una hoja existe. + +```py + doc = app.active + existe = 'Hoja2' in doc + app.debug(existe) +``` + +### **len** + +Contar la cantidad de hojas en el documento. + +```py + doc = app.active + contar = len(doc) + app.debug(contar) +``` + +### **iter** + +Recorrer todas las hojas. + +```py + doc = app.active + for hoja in doc: + app.debug(hoja) +``` + +
+ +## Propiedades + +--- + +### **code_name** + +Nombre editable y accesible solo por código. + +```py + hoja = app.active.active + + app.msgbox(hoja.code_name) + hoja.code_name = 'datos' + app.msgbox(hoja.code_name) +``` + +
+ +### **color** + +Color de la pestaña. + +```py + hoja = app.active.active + app.msgbox(hoja.color) + + hoja.color = 'red' + app.msgbox(hoja.color) + + # RGB + hoja.color = (125, 200, 10) + app.msgbox(hoja.color) +``` + +
+ +### **doc** + +Devuelve al documento Calc donde esta la hoja. + +```py + hoja = app.active.active + + doc = hoja.doc + app.debug(doc.title) +``` + +
+ +### **is_protected** + +Devuelve verdadero (True) si la hoja esta protegida + +```py + hoja = app.active.active + + esta_protegida = hoja.is_protected + app.debug(esta_protegida) +``` + +
+ +### **name** + +Nombre visible y editable por el usuario. + +```py + hoja = app.active.active + + app.debug(hoja.name) + hoja.name = 'Nuevo Nombre' + app.debug(hoja.name) +``` + +
+ +### **password** + +Establecer una contraseña. + +!!! tip "Consejo" + + Si la hoja ya esta protegida, aún sin contraseña, este método no tendrá ningún efecto. + +```py + hoja = app.active.active + hoja.password = 'siscaloburropanzon' + app.debug(hoja.is_protected) +``` + +
+ +### **used_area** + +Referencia al área de usuario actual. + +```py + hoja = app.active.active + + rango = hoja.used_area + app.debug(rango) +``` + +
+ +### **visible** + +Muestra u oculta la hoja + +```py + hoja = app.active.active + + app.msgbox(hoja.visible) + hoja.visible = not hoja.visible + app.msgbox(hoja.visible) + hoja.visible = not hoja.visible +``` + +!!! tip "Cuidado" + + Solo funcionará con dos o más hojas, por que debe haber al menos una visible. Siempre puedes trabajar con todo el documento oculto. + +
+ +## Métodos + +--- + +### **activate** + +Pasar el foco a la hoja. + +!!! tip inline end "Recuerde" + + No es necesario activar una hoja para manipularse. + +```py + doc = app.active + hoja = doc[-1] + hoja.activate() +``` + +
+ +### **copy** + +!!! tip "Consejo" + + Siempre valide que no exista el nuevo nombre. + +```py + doc = app.active + hoja = doc[0] + + nuevo_nombre = f'{hoja.name}_2' + if not nuevo_nombre in doc: + hoja.copy(nuevo_nombre) +``` + +Si no se establece el nuevo nombre, se generá de forma automática: `nombre + índice`. + +```py + hoja.copy() +``` + +### **copy_to** + +Copiar la hoja a otro documento. Se usa el mismo nombre. + +```py + doc = app.active + hoja = doc.active + + documento_nuevo = app.docs.new() + hoja.copy_to(documento_nuevo) +``` + +Usar un nuevo nombre. + +```python + hoja.copy_to(documento_nuevo, 'Nuevo nombre') +``` + +
+ +### **move** + +Mover a la última posición. + +```py + doc = app.active + hoja = doc[0] + hoja.move() +``` + +Mover a una posición especifica. + +```py + doc = app.active + hoja = doc[0] + hoja.move(3) +``` + +
+ +### **remove** + +Remover hoja. + +```py + sheet = app.active.active + sheet.remove() +``` + +!!! warning "Cuidado" + + Siempre debe existir al menos una hoja. + +
+ +### **unprotect** + +Quitar contraseña. + +```py + hoja = app.active.active + + hoja.password = 'siscaloburropanzon' + app.msgbox(hoja.is_protected) + + hoja.unprotect('siscaloburropanzon') + app.msgbox(hoja.is_protected) +``` + +
+ +## Eventos + +--- + +### **names** + +Obtener una tupla con los eventos soportados por la hoja. + +```py + hoja = app.active.active + + for nombre in hoja.events.names: + app.debug(nombre) +``` + +```sh +23/04/2023 16:59:26 - DEBUG - OnFocus +23/04/2023 16:59:26 - DEBUG - OnUnfocus +23/04/2023 16:59:26 - DEBUG - OnSelect +23/04/2023 16:59:26 - DEBUG - OnDoubleClick +23/04/2023 16:59:26 - DEBUG - OnRightClick +23/04/2023 16:59:26 - DEBUG - OnChange +23/04/2023 16:59:26 - DEBUG - OnCalculate +``` + +
+ +### Asignar una macro a un evento. + +```py +def on_select(source): + app.debug(source.AbsoluteName) + return + + +def main(): + doc = app.active + hoja = doc.active + + if 'OnSelect' in hoja.events: + macro = {'library': 'test', 'name': 'on_select'} + hoja.events['OnSelect'] = macro + + return +``` + +
+ +### Eliminar la asignación del evento. + +```py + hoja.events['OnSelect'] = {} +``` + +O + +```py + hoja.events.remove('OnFocus') +``` + +
\ No newline at end of file diff --git a/doc/docs/dp/drawpage.md b/doc/docs/dp/drawpage.md new file mode 100644 index 0000000..e1f6846 --- /dev/null +++ b/doc/docs/dp/drawpage.md @@ -0,0 +1,109 @@ +--- +title: DrawPage +--- + +La página de dibujo es la capa gráfica donde se agregan las formas y las imágenes en los documentos. La forma de acceder es la misma, solo cambia el tipo de documento. + +## Hoja de Calc + +### **draw_page** + +```py + hoja = app.active.active + pagina_dibujo = hoja.draw_page +``` + +### **dp** + +Alias de `draw_page` + +```py + hoja = app.active.active + pagina_dibujo = hoja.dp +``` + +### **shapes** + +Alias de `draw_page` + +```py + hoja = app.active.active + pagina_dibujo = hoja.shapes +``` + + +
+ +Una vez referenciada, sus métodos y propiedades son las mismas. + +--- + +
+ +## Formas + +--- + +### **index** + +Acceso por índice + +```py + forma = formas[0] + app.debug(forma) +``` + +Acceso por nombre + +```py + forma = formas['Rectangulo1'] + app.debug(forma) +``` + +
+ +### **in** + +Verificar si una forma esta en la colección por nombre. + +```py + app.debug('Shape 1' in formas) +``` + +
+ +### **iter** + +Iterar los elementos gráficos de la página de dibujo. + +```py + for f in formas: + app.debug(f) +``` + +
+ +### **len** + +Contar los elementos gráficos en la página de dibujo. + +```py + app.debug(len(formas)) +``` + +
+ +## Métodos + +--- + +### **add** + +Agrega una nueva forma (un rectángulo) y la devuelve. + +```py + forma = formas.add('Rectangle') + app.debug(forma) +``` + +
\ No newline at end of file diff --git a/doc/docs/dp/shapes.md b/doc/docs/dp/shapes.md new file mode 100644 index 0000000..2e731d4 --- /dev/null +++ b/doc/docs/dp/shapes.md @@ -0,0 +1,7 @@ +## Propiedades + +--- + +## Métodos + +--- \ No newline at end of file diff --git a/doc/mkdocs.yml b/doc/mkdocs.yml index 2ce9bd3..0e47fee 100644 --- a/doc/mkdocs.yml +++ b/doc/mkdocs.yml @@ -24,6 +24,14 @@ nav: - docs/index.md - Propiedades: docs/properties.md - Métodos: docs/methods.md + - Calc: + - calc/index.md + - Hojas: calc/sheets.md + - Rangos: calc/ranges.md + - Celdas: calc/cells.md + - Página de dibujo: + - dp/drawpage.md + - Formas: dp/shapes.md theme: name: material locale: es diff --git a/source/easymacro/__init__.py b/source/easymacro/__init__.py index 2798484..88ef035 100644 --- a/source/easymacro/__init__.py +++ b/source/easymacro/__init__.py @@ -11,6 +11,7 @@ from .easydrawpage import LOGalleries def __getattr__(name): classes = { 'active': LODocuments().active, + 'active_sheet': LODocuments().active.active, 'clipboard': ClipBoard, 'cmd': LOMain.commands, 'color': Color(), diff --git a/source/easymacro/easycalc.py b/source/easymacro/easycalc.py index 5b85e3c..d01452d 100644 --- a/source/easymacro/easycalc.py +++ b/source/easymacro/easycalc.py @@ -90,9 +90,10 @@ class LOCellStyles(): # ~ IsStartOfNewPage class LOSheetRows(): - def __init__(self, sheet, obj): + def __init__(self, sheet, obj, range_address): self._sheet = sheet self._obj = obj + self._ra = range_address def __getitem__(self, index): if isinstance(index, int): @@ -106,7 +107,8 @@ class LOSheetRows(): return self.obj.Count def __str__(self): - return self.obj.Name + name = f'Rows: {self._ra.StartRow} - {self._ra.EndRow}' + return name @property def obj(self): @@ -239,6 +241,7 @@ class LOCalcRange(): def __init__(self, obj): self._obj = obj self._is_cell = obj.ImplementationName == self.CELL + self._shape = None def __contains__(self, rango): if isinstance(rango, LOCalcRange): @@ -303,6 +306,7 @@ class LOCalcRange(): @property def is_range(self): + """True if range is not cell""" return not self._is_cell @property @@ -523,6 +527,17 @@ class LOCalcRange(): col2 = ra.EndColumn + 1 return LOCalcRange(self.sheet[row1:row2, col1:col2].obj) + @property + def shape(self): + return self._shape + @shape.setter + def shape(self, shape): + shape.anchor = self + shape.resize_with_cell = True + shape.possize = self.possize + return + + # ~ Fix @property def array_formula(self): return self.obj.ArrayFormula @@ -535,12 +550,10 @@ class LOCalcRange(): cursor = self.obj.Spreadsheet.createCursorByRange(self.obj) return cursor - # ~ To doc @property def position(self): return self.obj.Position - # ~ To doc @property def size(self): return self.obj.Size @@ -561,20 +574,19 @@ class LOCalcRange(): def y(self): return self.obj.Position.Y - # ~ To doc @property def possize(self): data = { - 'Width': self.size.Width, - 'Height': self.size.Height, - 'X': self.position.X, - 'Y': self.position.Y, + 'Width': self.width, + 'Height': self.height, + 'X': self.x, + 'Y': self.y, } return data @property def rows(self): - return LOSheetRows(self.sheet, self.obj.Rows) + return LOSheetRows(self.sheet, self.obj.Rows, self.range_address) @property def row(self): @@ -592,17 +604,26 @@ class LOCalcRange(): return def offset(self, rows=0, cols=1): + """Get cell offset""" ra = self.range_address col = ra.EndColumn + cols row = ra.EndRow + rows return LOCalcRange(self.sheet[row, col].obj) def to_size(self, cols: int, rows: int): + """Expande range to size""" cursor = self.cursor cursor.collapseToSize(cols, rows) rango = self.obj.Spreadsheet[cursor.AbsoluteName] return LOCalcRange(rango) + def len(self): + """Get size of range in rows and columns""" + ra = self.range_address + rows = ra.EndRow - ra.StartRow + 1 + cols = ra.EndColumn - ra.StartColumn + 1 + return rows, cols + class LOCalcSheet(BaseObject): @@ -623,10 +644,12 @@ class LOCalcSheet(BaseObject): @property def doc(self): + """Get parent doc""" return LOCalc(self.obj.DrawPage.Forms.Parent) @property def name(self): + """Get name sheet""" return self._obj.Name @name.setter def name(self, value): @@ -634,6 +657,7 @@ class LOCalcSheet(BaseObject): @property def code_name(self): + """Get code name""" return self._obj.CodeName @code_name.setter def code_name(self, value): @@ -641,6 +665,7 @@ class LOCalcSheet(BaseObject): @property def visible(self): + """Get visible""" return self._obj.IsVisible @visible.setter def visible(self, value): @@ -648,6 +673,7 @@ class LOCalcSheet(BaseObject): @property def color(self): + """Get color tab""" return self._obj.TabColor @color.setter def color(self, value): @@ -655,12 +681,14 @@ class LOCalcSheet(BaseObject): @property def used_area(self): + """Get used area""" cursor = self.create_cursor() cursor.gotoEndOfUsedArea(True) return self[cursor.AbsoluteName] @property def is_protected(self): + """Get is protected""" return self._obj.isProtected() @property @@ -668,10 +696,12 @@ class LOCalcSheet(BaseObject): return '' @password.setter def password(self, value): + """Set password protect""" self.obj.protect(value) @property def draw_page(self): + """Get draw page""" return LODrawPage(self.obj.DrawPage) @property def dp(self): @@ -686,6 +716,7 @@ class LOCalcSheet(BaseObject): @property def events(self): + """Get events""" return LOEvents(self.obj.Events) @property @@ -701,6 +732,7 @@ class LOCalcSheet(BaseObject): return def unprotect(self, value): + """Unproyect sheet""" try: self.obj.unprotect(value) return True @@ -709,6 +741,7 @@ class LOCalcSheet(BaseObject): return False def move(self, pos: int=-1): + """Move sheet""" index = pos if pos < 0: index = len(self.doc) @@ -716,10 +749,12 @@ class LOCalcSheet(BaseObject): return def remove(self): + """Auto remove""" self.doc.remove(self.name) return def copy(self, new_name: str='', pos: int=-1): + """Copy sheet""" index = pos if pos < 0: index = len(self.doc) @@ -727,8 +762,7 @@ class LOCalcSheet(BaseObject): return new_sheet def copy_to(self, doc: Any, target: str='', pos: int=-1): - """Copy sheet to other document. - """ + """Copy sheet to other document.""" index = pos if pos < 0: index = len(doc) @@ -909,7 +943,6 @@ class LOCalc(LODocument): self._cc.select(obj) return - @run_in_thread def start_range_selection(self, controllers: Any, args: dict={}): """Start select range selection by user diff --git a/source/easymacro/easydrawpage.py b/source/easymacro/easydrawpage.py index 0895238..05dca93 100644 --- a/source/easymacro/easydrawpage.py +++ b/source/easymacro/easydrawpage.py @@ -145,6 +145,10 @@ class LODrawPage(BaseObject): break return result + def __len__(self): + """Count shapes""" + return self.count + @property def name(self): return self.obj.Name @@ -201,7 +205,6 @@ class LODrawPage(BaseObject): if properties: set_properties(shape, properties) - # ~ return LOShape(self.obj[index], index) return LOShape(self.obj[index]) def remove(self, shape): diff --git a/source/easymacro/easyevents.py b/source/easymacro/easyevents.py index 276c630..8ce65a6 100644 --- a/source/easymacro/easyevents.py +++ b/source/easymacro/easyevents.py @@ -80,15 +80,12 @@ class EventsRangeSelectionListener(EventsListenerBase, XRangeSelectionListener): super().__init__(controller, '') def done(self, event): - range_selection = event.RangeDescriptor - print(event) event_name = 'range_selection_done' if hasattr(self._controller, event_name): - getattr(self._controller, event_name)(range_selection) + getattr(self._controller, event_name)(event.RangeDescriptor) return def aborted(self, event): - range_selection = event.RangeDescriptor event_name = 'range_selection_aborted' if hasattr(self._controller, event_name): getattr(self._controller, event_name)() diff --git a/source/easymacro/easyshape.py b/source/easymacro/easyshape.py index 99a7f91..f3488b4 100644 --- a/source/easymacro/easyshape.py +++ b/source/easymacro/easyshape.py @@ -54,6 +54,24 @@ class LOShape(BaseObject): def obj(self): return self._obj + @property + def anchor(self): + return self.obj.Anchor + @anchor.setter + def anchor(self, obj): + if hasattr(obj, 'obj'): + obj = obj.obj + self.obj.Anchor = obj + return + + @property + def resize_with_cell(self): + return self.obj.ResizeWithCell + @resize_with_cell.setter + def resize_with_cell(self, value): + self.obj.ResizeWithCell = value + return + @property def properties(self): # ~ properties = self.obj.PropertySetInfo.Properties