Update documentation

This commit is contained in:
Mauricio 2023-04-23 11:31:58 -06:00
parent f3e23f77cf
commit d0c6375b4b
252 changed files with 2588 additions and 73263 deletions

View File

@ -1,6 +0,0 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

View File

@ -1,57 +0,0 @@
baseURL = 'https://doc.cuates.net/easymacro'
languageCode = 'en-us'
title = "EasyMacro's documentation"
theme = "hugo-theme-learn"
# For search functionality
[outputs]
home = [ "HTML", "RSS", "JSON"]
[params]
themeVariant = "blue"
custom_css = ["css/custom.css"]
defaultContentLanguage = "en"
defaultContentLanguageInSubdir= true
[Languages]
[Languages.en]
contentDir = "content/en"
title = "EasyMacro's documentation"
weight = 1
languageName = "English"
landingPageURL = "/en"
landingPageName = "<i class='fas fa-home'></i> Home"
staticDir2 = "images_en"
[Languages.es]
contentDir = 'content/es'
title = "Documentación para EasyMacro"
weight = 2
languageName = "Español"
landingPageURL = "/easymacro/es"
landingPageName = "<i class='fas fa-home'></i> Inicio"
[Languages.pt]
contentDir = 'content/pt'
title = "Documentação para EasyMacro"
weight = 3
languageName = "Português"
landingPageURL = "/pt"
landingPageName = "<i class='fas fa-home'></i> Inicio"
[Languages.fr]
contentDir = 'content/fr'
title = "Documentation du EasyMacro"
weight = 4
languageName = "Français"
landingPageURL = "/fr"
landingPageName = "<i class='fas fa-home'></i> Accueil"
[[menu.shortcuts]]
name = "<i class='fab fa-gitlab'></i> Git Repo"
url = "https://git.cuates.net/elmau/easymacro"
weight = 10

View File

@ -1,15 +0,0 @@
# Welcome to easymacros documentation!
#### Free Software, not gratis software
**easymacro** its a library for easily develop macros en LibreOffice con Python. It is an abstraction layer between the extensive and complex LibreOffice API UNO and your code.
Probably, you will be more happy if used it. :)
You can used **easymacro** with any extension or directly in your macros.
{{% notice note %}}
This project is in continuous development.
{{% /notice %}}

View File

@ -1,51 +0,0 @@
+++
title = "Installation"
weight = 1
+++
## Clone repository
Clone repository in your favorite folder projects.
```
git clone https://git.cuates.net/elmau/easymacro
```
and copy library into pythonpath in your macros.
```
/home/USER/.config/libreoffice/4/user/Scripts/python/pythonpath/easymacro.py
```
or used hard link. Replace `ABSOLUTE_PATH` for absolute path in your system and `USER` for your real name user.
```
ln ABSOLUTE_PATH/easymacro/source/easymacro.py /home/USER/.config/libreoffice/4/user/Scripts/python/pythonpath/
```
## Test
In your favorite macros file, for example `mymacros.py`:
```
vim /home/USER/.config/libreoffice/4/user/Scripts/python/mymacros.py
```
copy this code:
```python
import easymacro as app
def main():
app.msgbox(app.INFO_DEBUG)
return
```
and execute from LibreOffice, if you see similar next info, great!
![Test instalation](install_01.png)
you are ready for develop with easymacro.
Happy develop!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

View File

@ -1,7 +0,0 @@
+++
title = "Tools for debug"
weight = 2
+++
## INFO_DEBUG

View File

@ -1,19 +0,0 @@
## Documentación de easymacro!
#### Software Libre, no software gratis.
**easymacro** es una librería para desarrollar más fácilmente macros en LibreOffice con Python. Es una capa de abstracción entre la extensa y compleja API UNO de LibreOffice y tu código.
Probablemente, será más feliz si la usa :)
Puede utilizar **easymacro** con cualquier extensión o directamente en sus macros.
Aportaciones en Junas (G1)
```
A5DdXxCKPw3QKWVdDVs7CzkNugNUW1sHu5zDJFWxCU2h
```
{{% notice note %}}
Este proyecto esta en continuo desarrollo.
{{% /notice %}}

View File

@ -1,137 +0,0 @@
+++
title = "LibreOffice"
weight = 4
+++
### fonts
Devolver todas las fuentes visibles en LibreOffice. Mire [FontDescriptor][1]
```python
fonts = app.fonts()
for f in fonts:
app.debug(f'Nombre: {f.Name} - Estilo: {f.StyleName}')
```
### filters
Devolver todos los filtros soportados en LibreOffice. Mire la [ayuda][2] y en [API FilterFactory][3] para más detalles.
```python
filtros = app.filters()
for f in filtros:
info = f"Nombre UI: {f['UIName']} - Nombre: {f['Name']} - Tipo: {f['Type']}"
app.debug(info)
```
### dispatch
Ejecutar cualquier comando `UNO` de LibreOffice, mire la [lista de comandos][4] y [API dispatch][5].
Este método automáticamente agrega el prefijo necesario: `.uno:`
```python
doc = app.active
comando = 'Gallery'
app.dispatch(doc, comando)
```
{{% notice tip %}}
Use este método solamente si no hay un método equivalente en `easymacro` o directamente en el API de LibreOffice.
{{% /notice %}}
### clipboard
Envíar contenido al portapapeles.
```python
app.clipboard.set('Los 7 samuráis')
```
Recuperar contenido del portapapeles.
```python
content = app.clipboard.get()
app.debug(content)
```
### disable
Deshabilitar un comando. Para una lista de comandos mire [DispatchCommands][4].
```python
comando = 'OpenFromCalc'
resultado = app.cmd.disable(comando)
app.debug(resultado)
```
`OpenFromCalc` es la opción para abrir documentos en Calc, deshabilita o habilita la entrada del menú y el icono en la barra de herramientas.
### enabled
Habilitar un comando.
```python
comando = 'OpenFromCalc'
resultado = app.cmd.enabled(comando)
app.debug(resultado)
```
### get_config
Obtener valores de la configuración de LibreOffice.
```python
nombre_node = '/org.openoffice.Office.Common/Help'
clave = 'System'
valor = app.get_config(nombre_node, clave)
app.debug(valor)
nombre_node = '/org.openoffice.Office.Common/Misc/'
clave = 'FirstRun'
valor = app.get_config(nombre_node, clave)
app.debug(valor)
clave = 'UseSystemFileDialog'
valor = app.get_config(nombre_node, clave)
app.debug(valor)
```
```
17/08/2022 14:14:12 - DEBUG - UNIX
17/08/2022 14:14:12 - DEBUG - False
17/08/2022 14:14:12 - DEBUG - True
```
### set_config
Establece un nuevo valor en la configuración de LibreOffice.
```python
nombre_nodo = '/org.openoffice.Office.UI/ColorScheme'
clave = 'CurrentColorScheme'
nuevo_valor = 'LibreOffice Dark'
resultado = app.set_config(nombre_nodo, clave, nuevo_valor)
app.debug(resultado)
```
Algunos nodos y claves interesantes:
* `/org.openoffice.Office.Common/Save/Document`
* AutoSave
* AutoSaveTimeIntervall
{{% notice warning %}}
No todos los valores de los nodos se pueden cambiar, algunos valores son de solo lectura.
{{% /notice %}}
[1]: https://api.libreoffice.org/docs/idl/ref/structcom_1_1sun_1_1star_1_1awt_1_1FontDescriptor.html
[2]: https://help.libreoffice.org/latest/en-US/text/shared/guide/convertfilters.html
[3]: https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1document_1_1FilterFactory.html
[4]: https://wiki.documentfoundation.org/Development/DispatchCommands
[5]: https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1frame_1_1XDispatch.html#a42beb1ea2ddae35c076b6e65867025ea

View File

@ -1,114 +0,0 @@
+++
title = "Accesos directos"
weight = 1
+++
#### Globales
Iterar en todos los accesos directos. Accesos directos disponibles para todas las aplicaciones.
```python
for acceso_directo, comando in app.shortcuts:
app.debug(acceso_directo, comando)
```
Devolver una lista de tuplas con toda la información.
```python
datos = app.shortcuts.get_all()
app.debug(datos)
```
Verificar si un acceso directo esta asignado.
```python
acceso_directo = 'Shift+Ctrl+Alt+T'
app.debug(acceso_directo in app.shortcuts)
```
### set
Establecer un acceso directo a un comando.
```python
sc = app.shortcuts
acceso_directo = 'Shift+Ctrl+Alt+T'
comando = 'MacroDialog'
sc.set(acceso_directo, comando)
```
Establecer un acceso directo a una macro.
```python
sc = app.shortcuts
acceso_directo = 'Shift+Ctrl+Alt+M'
macro = {'library': 'test', 'name': 'pruebas'}
sc.set(acceso_directo, macro)
```
### get_by_shortcut
Devolver el comando asociado a un acceso directo.
```python
sc = app.shortcuts
acceso_directo = 'Shift+Ctrl+Alt+M'
comando = sc.get_by_shortcut(acceso_directo)
app.debug(comando)
```
### get_by_command
Devolver el acceso directo asociado a un comando. Puede haber más de uno.
```python
sc = app.shortcuts
comando = 'MacroDialog'
acceso_directo = sc.get_by_command(comando)
app.debug(acceso_directo)
```
### remove_by_shortcut
Eliminar por acceso directo.
```python
sc = app.shortcuts
acceso_directo = 'Shift+Ctrl+Alt+T'
sc.remove_by_shortcut(acceso_directo)
```
### remove_by_command
Eliminar por comando.
```python
sc = app.shortcuts
macro = {'library': 'test', 'name': 'pruebas'}
sc.remove_by_command(macro)
```
### reset
Reiniciar todas las modificaciones.
```python
app.shortcuts.reset()
```
#### Modificar accesos directos, solo en una aplicación.
Por ejemplo Calc.
```python
sc = app.shortcuts['calc']
```
Los métodos son los mismos que los globales.
Para las demas aplicaciones: `writer`, `draw`, `impress`, `math`.

View File

@ -1,322 +0,0 @@
+++
title = "Calc"
weight = 6
+++
#### Trabajar con Calc
### active
```python
doc = app.active
app.debug(doc.type)
```
#### Propiedades
### headers
Mostrar u ocultar encabezados de filas y columnas.
```python
doc = app.active
app.msgbox(doc.headers)
doc.headers = not doc.headers
app.msgbox(doc.headers)
doc.headers = not doc.headers
```
### tabs
Mostrar u ocultar las pestañas de las hojas.
```python
doc = app.active
app.msgbox(doc.tabs)
doc.tabs = not doc.tabs
app.msgbox(doc.tabs)
doc.tabs = not doc.tabs
```
### selection
Devolver la selección activa.
```python
doc = app.active
seleccion = doc.selection
app.debug(seleccion)
```
{{% notice warning %}}
**Cuidado**, la selección actual pueden ser muchas cosas diferentes.
{{% /notice %}}
### names
Devolver una tupla con los nombres de todas las hojas.
```python
doc = app.active
nombres = doc.names
app.debug(nombres)
```
### active
Devuelve la hoja activa.
```python
doc = app.active
hoja = doc.active
app.debug(hoja)
```
#### Métodos
### activate
Activar hoja, argumento como objeto.
```python
doc = app.active
hoja = doc[-1]
doc.activate(hoja)
```
Activar hoja por nombre.
```python
doc = app.active
doc.activate('Hoja3')
```
### select
Seleccionar una celda o rango.
```python
doc = app.active
cell = doc[0]['A1']
doc.select(cell)
```
{{% notice tip %}}
**NO** es necesario seleccionar celdas o rangos para manipularlos.
{{% /notice %}}
### 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:
```python
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
```
### insert
Inserta una nueva hoja.
```python
doc = app.active
hoja = doc.insert('OtraHoja')
```
Insertar varias hojas. Devolverá la última insertada.
```python
nombres = ('Enero', 'Febrero', 'Marzo')
hoja = doc.insert(nombres)
app.debug(hoja)
```
Creando una nueva instancia y asignandola.
```python
doc = app.active
doc['NuevaHoja'] = doc.new_sheet()
```
{{% notice warning %}}
Si la hoja existe, obtendrá un error, verifique siempre que no exista primero.
{{% /notice %}}
### move
Mover hojas.
Pasar la hoja como objeto, de forma predetermianda se mueve a la última posición.
```python
doc = app.active
hoja = doc[0]
doc.move(hoja)
```
Pasar la hoja por nombre.
```python
doc = app.active
doc.move('Hoja1')
```
Especificar la posición destino.
```python
doc = app.active
hoja = doc[0]
doc.move(hoja, 2)
```
### remove
Eliminar hoja.
```python
doc = app.active
sheet = doc[0]
doc.remove(sheet)
```
Eliminar por nombre.
```python
doc.remove('Hoja2')
```
### copy
Copiar hoja dentro del mismo documento.
```python
doc = app.active
hoja = doc[0]
doc.copy_sheet(hoja, 'Otra hoja')
```
Por nombre.
```python
doc.copy_sheet('Hoja1', 'Hoja2')
```
Si no se establece el nuevo nombre, se generá de forma automática: `nombre + índice`.
```python
doc.copy_sheet(hoja)
```
### copy_from
Copiar hojas de otro documento. Copiar con el mismo nombre.
```python
doc = app.active
documento_origen = app.docs['Contactos.ods']
nombre_origen = 'Nombres'
doc.copy_from(documento_origen, nombre_origen)
```
Copiar con un nuevo nombre.
```python
doc.copy_from(documento_origen, nombre_origen, 'NuevoNombre')
```
Si solo se establece el documento origen, se copian todas las hojas.
```python
doc.copy_from(documento_origen)
```
### sort
Ordenar hojas en orden alfabetico.
```python
doc = app.active
doc.sort()
```
Ordenar de forma inversa.
```python
doc = app.active
doc.sort(True)
```
### Eventos del documento.
Obtener una tupla con los eventos soportados por el documento.
```python
doc = app.active
nombres = doc.events.names
app.debug(nombres)
```
#### Asignar una macro a un evento.
```python
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.
```python
doc = app.active
doc.events['OnFocus'] = {}
```
O
```python
doc = app.active
doc.events.remove('OnFocus')
```

View File

@ -1,85 +0,0 @@
+++
title = "Celdas y rangos"
weight = 3
+++
#### Trabajar con celdas y rangos
### selection
Referencia por selección actual.
```python
seleccion = app.selection
app.debug(seleccion)
```
```
20/08/2022 15:32:36 - DEBUG - Cell: $Sheet1.$A$2
20/08/2022 15:32:39 - DEBUG - Range: $Sheet1.$C$8:$D$11
```
### address
Referencia por dirección.
```python
hoja = app.active_sheet
celda = hoja['A1']
rango = hoja['C10:D15']
app.debug(celda)
app.debug(rango)
```
### position
Referencia por posición.
Para celdas: `HOJA[fila,columna]`
Para rangos: `HOJA[fila_inicial:fila_final, columna_inicial:columna_final]`
```python
hoja = app.active_sheet
# ~ Cell A10
celda = hoja[9,0]
# ~ Range A1:C10
rango = hoja[0:10,0:3]
```
### iter
Iterar cada celda de un rango.
```python
hoja = app.active_sheet
rango = hoja['B10:C15']
for celda in rango:
app.debug(celda)
```
### contains
Verificar si un rango esta dentro de otro.
```python
hoja = app.active_sheet
celda = hoja['C5']
rango = hoja['A1:E10']
resultado = celda in rango
app.debug(resultado)
celda = hoja['C50']
resultado = celda in rango
app.debug(resultado)
```

View File

@ -1,23 +0,0 @@
+++
title = "Métodos"
weight = 2
+++
### 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)
```
[1]: https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1sheet_1_1CellFlags.html

View File

@ -1,344 +0,0 @@
+++
title = "Propiedades"
weight = 1
+++
### is_cell
Verdadero (True) si el rango es de una sola celda.
```python
hoja = app.active_sheet
celda = hoja['A1']
app.debug(celda.is_cell)
rango = hoja['A1:C5']
app.debug(rango.is_cell)
```
### name
Devuelve la dirección de la celda o rango como texto.
```python
hoja = app.active_sheet
celda = hoja['A1']
app.debug(celda.name)
rango = hoja['A1:C5']
app.debug(rango.name)
```
### address
Devuelve la dirección de la celda como una estructura: `com.sun.star.table.CellAddress`
```python
hoja = app.active_sheet
celda = hoja['A1']
if celda.is_cell:
app.debug(celda.address)
```
### range_address
Devuelve la dirección del rango como una estructura: `com.sun.star.table.CellRangeAddress`
```python
hoja = app.active_sheet
rango = hoja['A1:C5']
if not rango.is_cell:
app.debug(rango.range_address)
```
### filas y columnas
Devolver el tamaño del rango en filas y columnas.
```python
hoja = app.active_sheet
rango = hoja['A1:E100']
filas = len(rango)
columnas = rango.len_columns
app.debug(filas, columnas)
```
### sheet
Devuelve la hoja padre.
```python
rango = hoja['A1:C5']
hoja = rango.sheet
app.debug(hoja)
```
### doc
Devuelve el documento padre.
```python
rango = hoja['A1:C5']
doc = rango.doc
app.debug(doc)
```
### style
Devuelve o aplica el estilo de celda.
```python
rango = hoja['A1:C5']
rango.style = 'Good'
```
### current_region
Devuelve la región actual.
```python
celda = hoja['A1']
rango = celda.current_region
app.debug(rango)
```
### range_data
Devuelve la región actual del rango excepto la primer fila.
```python
celda = hoja['A1']
rango = celda.range_data
app.debug(rango)
```
### back_color
Devuelve o aplica el color de fondo del rango.
```python
rango = hoja['A1:E10']
rango.back_color = 'red'
```
### type
Devuelve el tipo de contenido de la celda: texto, número o formula.
```python
celda = hoja['A1']
app.debug(celda.type)
```
### error
Si la celda tiene una formula con error, devuelve el número de error.
```python
celda = hoja['A1']
app.debug(celda.error)
```
### string
Devuelve o establece el contenido de la celda como texto.
```python
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)
```
### float
Devuelve o establece el contenido de la celda como valor.
```python
celda = hoja['A1']
celda.float = 12345
app.debug(celda.type, celda.float)
```
### formula
Devuelve o establece la formula de la celda.
```python
celda = hoja['A1']
celda.formula = '=RAND()'
app.debug(celda.type, celda.formula)
```
### date
Devuelve o establece el contenido de la celda como fecha.
```python
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 - <class 'datetime.date'> 1974-01-15
```
### time
Devuelve o establece el contenido de la celda como tiempo.
```python
celda = hoja['A1']
celda.time = app.dates.time(10, 11, 12)
app.debug(type(celda.time), celda.time)
```
### datetime
Devuelve o establece el contenido de la celda como fecha y tiempo.
```python
celda = hoja['A1']
celda.datetime = app.dates.datetime(1974, 1, 15, 10, 11, 12)
app.debug(type(celda.datetime), celda.datetime)
```
### value
Devuelve o establece el valor de la celda, estableciendo el tipo de dato automáticamente.
```python
hoja = app.active_sheet
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)
```
### data_array
Devuelve o establece los datos de un rango. Es un alias de DataArray.
```python
rango = app.selection
datos = rango.data_array
app.debug(datos)
rango.data_array = datos
```
{{% notice warning %}}
El tamaño de los datos, debe ser **exactamente** del tamaño del rango destino. De lo contrario obtendrá un error.
{{% /notice %}}
### formula_array
Devuelve o establece los datos de un rango. Es un alias de FormulaArray.
```python
rango = app.selection
datos = rango.data_array
app.debug(datos)
datos = rango.formula_array
app.debug(datos)
rango.formula_array = datos
```
{{% notice tip %}}
**data_array** devolverá los resultados de las celdas con formulas. **formula_array** devolverá las formulas en dichas celdas.
{{% /notice %}}
### 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.
```python
hoja = app.active_sheet
celda = hoja['A1']
datos = (
(1, 'Uno'),
(2, 'Dos'),
(3, 'Tres'),
)
celda.data = datos
app.debug(celda.current_region.data)
```
{{% notice tip %}}
Siempre valide que haya suficientes celdas libres para los datos para evitar sobreescribirlos.
{{% /notice %}}
### dict
Devuelve o establece los datos como diccionarios.
```python
hoja = app.active_sheet
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)
```
### next_free
Devuelve la siguiente celda libre después de la región actual.
```python
hoja = app.active_sheet
celda = hoja['A1']
celda_libre = celda.next_free
app.debug(celda_libre)
```

View File

@ -1,83 +0,0 @@
+++
title = "Conjuntos de Rangos"
weight = 2
+++
#### Trabajar con conjuntos de rangos
### Selección
Obtener una referencia desde la selección actual. Deben de estar seleccionados más de un rango de celdas.
```python
doc = app.active
seleccion = doc.selection
app.debug(seleccion)
```
```
20/08/2022 13:21:17 - DEBUG - Ranges: ('Sheet1.A5:C8', 'Sheet1.E11:F14')
```
### len
Contar los rangos.
```python
doc = app.active
contar = len(doc.selection)
app.debug(contar)
```
### iter
Iterar entre los rangos.
```python
doc = app.active
for rango in doc.selection:
app.debug(rango)
```
```
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
```
### index
Referencia a un rango por índice.
```python
doc = app.active
rangos = doc.selection
rango = rangos[1]
app.debug(rango)
```
### address
Referencia a un rango por su dirección.
```python
rango = rangos['Hoja1.A1:B5']
app.debug(rango)
```
### contain
Verificar si un rango esta en la colección.
```python
doc = app.active
hoja = doc.active
rangos = doc.selection
resultado = hoja['D5:F10'] in rangos
app.debug(resultado)
```

View File

@ -1,42 +0,0 @@
+++
title = "Métodos"
weight = 2
+++
### ranges
Crear un nuevo contender de rangos vacío.
```python
doc = app.active
rangos = doc.ranges()
app.debug(rangos)
```
### add
```python
doc = app.active
hoja = doc.active
rangos = doc.ranges()
rangos.add(hoja['A1:B2'])
rangos.add(hoja['D5:F10'])
app.debug(rangos)
```
### remove
```python
rangos.remove(hoja['A1:B2'])
```
### get_ranges
```python
```

View File

@ -1,46 +0,0 @@
+++
title = "Propiedades"
weight = 1
+++
# names
Devolver las direcciones de los rangos.
```python
doc = app.active
rangos = doc.selection
nombres = rangos.names
app.debug(nombres)
```
### data
Devolver y establecer datos.
```python
doc = app.active
rangos = doc.selection
datos = rangos.data
app.debug(datos)
rangos.data = datos
```
{{% notice warning %}}
Cada rango debe tener exactamente el mismo tamaño.
{{% /notice %}}
### style
Establecer el estilo de todos los rangos.
```python
doc = app.active
rangos = doc.selection
rangos.style = 'Good'
```

View File

@ -1,56 +0,0 @@
+++
title = "Hojas"
weight = 1
+++
#### Trabajar con hojas
### Referencia por índice
```python
doc = app.active
hoja = doc[0]
app.debug(hoja.name)
```
### Referencia por nombre
```python
doc = app.active
hoja = doc['datos']
app.debug(hoja.name)
```
### in
Verificar por nombre si una hoja existe.
```python
doc = app.active
existe = 'Hoja2' in doc
app.debug(existe)
```
### len
Contar la cantidad de hojas en el documento.
```python
doc = app.active
contar = len(doc)
app.debug(contar)
```
### iter
Recorrer todas las hojas.
```python
doc = app.active
for hoja in doc:
app.debug(hoja)
```

View File

@ -1,48 +0,0 @@
+++
title = "Eventos"
weight = 3
+++
#### Eventos de la hoja.
Obtener una tupla con los eventos soportados por la hoja.
```python
hoja = app.active.active
nombres = hoja.events.names
app.debug(nombres)
```
#### Asignar una macro a un evento.
```python
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.
```python
hoja.events['OnSelect'] = {}
```
O
```python
hoja.events.remove('OnFocus')
```

View File

@ -1,101 +0,0 @@
+++
title = "Métodos"
weight = 2
+++
### unprotect
Quitar contraseña.
```python
hoja = app.active.active
hoja.password = 'siscaloburropanzon'
app.msgbox(hoja.is_protected)
hoja.unprotect('siscaloburropanzon')
app.msgbox(hoja.is_protected)
```
### activate
Pasar el foco a la hoja.
```python
doc = app.active
hoja = doc[-1]
hoja.activate()
```
### move
Mover a la última posición.
```python
doc = app.active
hoja = doc[0]
hoja.move()
```
Mover a una posición especifica.
```python
doc = app.active
hoja = doc[0]
hoja.move(3)
```
### remove
Remover hoja.
```python
sheet = app.active.active
sheet.remove()
```
{{% notice warning %}}
Siempre debe existir al menos una hoja.
{{% /notice %}}
### copy
{{% notice tip %}}
Siempre valida que no exista el nuevo nombre.
{{% /notice %}}
```python
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`.
```python
hoja.copy()
```
### copy_to
Copiar la hoja a otro documento. Se usa el mismo nombre.
```python
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')
```

View File

@ -1,113 +0,0 @@
+++
title = "Propiedades"
weight = 1
+++
### doc
Devuelve al documento Calc donde esta la hoja.
```python
doc = app.active
hoja = doc.active
doc = hoja.doc
app.debug(doc.title)
```
### name
Nombre visible y editable por el usuario.
```python
doc = app.active
hoja = doc.active
app.msgbox(hoja.name)
hoja.name = 'Nuevo Nombre'
app.msgbox(hoja.name)
```
### code_name
Nombre editable y accesible solo por código.
```python
doc = app.active
hoja = doc.active
app.msgbox(hoja.code_name)
hoja.code_name = 'datos'
app.msgbox(hoja.code_name)
```
### visible
Muestra u oculta la hoja
```python
hoja = app.active.active
app.msgbox(hoja.visible)
hoja.visible = not hoja.visible
app.msgbox(hoja.visible)
hoja.visible = not hoja.visible
```
{{% notice tip %}}
Solo funcionará con dos o más hojas, por que debe haber al menos una visible.
{{% /notice %}}
### color
Color de la pestaña.
```python
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)
```
### used_area
Referencia al área de usuario actual.
```python
hoja = app.active.active
rango = hoja.used_area
app.debug(rango)
```
### is_protected
Devuelve verdadero (True) si la hoja esta protegida
```python
hoja = app.active.active
esta_protegida = hoja.is_protected
app.debug(esta_protegida)
```
### password
Establecer una contraseña.
```python
hoja = app.active.active
hoja.password = 'siscaloburropanzon'
app.debug(hoja.is_protected)
```

View File

@ -1,76 +0,0 @@
+++
title = "Cuadros de diálogo"
weight = 20
+++
#### Trabajar con cuadros de diálogo
### create
##### Desde archivo
Crear un cuadro de diálogo desde un archivo `xdl` previamente creado desde el editor de cuadros de diálogo dentro de LibreOffice y exportado a un archivo.
```python
def crear_cuadro_de_dialogo():
path = '/home/mau/Desktop/Dialog1.xdl'
propiedades = {'Path': path}
dialog = app.dialog.create(propiedades)
dialog.open()
return
```
##### Desde mis macros
Si el cuadro de diálogo esta en la librería `Standard`.
```python
def crear_cuadro_de_dialogo():
propiedades = {
'Location': 'user',
'Name': 'Dialog1',
}
dialog = app.dialog.create(propiedades)
dialog.open()
return
```
Si el cuadro de diálogo esta en otra librería.
```python
def crear_cuadro_de_dialogo():
propiedades = {
'Location': 'user',
'Library': 'MiAplicacion',
'Name': 'Dialog2',
}
dialog = app.dialog.create(propiedades)
dialog.open()
return
```
Si el cuadro de diálogo esta en el documento activo en la librería `Standard`.
```python
def crear_cuadro_de_dialogo():
propiedades = {
'Location': 'document',
'Name': 'miApp',
}
dialog = app.dialog.create(propiedades)
dialog.open()
return
```
##### Crear dinámicamente
Crear un cuadro de diálogo vacío.
```python
def crear_cuadro_de_dialogo():
dialog = app.dialog.create()
dialog.open()
return
```

View File

@ -1,67 +0,0 @@
+++
title = "Documentos"
weight = 5
+++
#### Trabajar con Documentos
### active
Documento activo.
```python
doc = app.active
app.msgbox(doc.title)
```
### iteration
Iterar en todos los documentos abiertos.
```python
for doc in app.docs:
app.debug(doc.type, doc.title)
```
### count
Contar los documentos abiertos.
```python
cuantos = len(app.docs)
app.debug(cuantos)
```
### contain
Verificar si un documento esta en la colección.
```python
resultado = 'mi_archivo.ods' in app.docs
app.debug(resultado)
```
### index
Devolver por índice.
```python
doc = app.docs[1]
app.debug(doc.type, doc.title)
```
### name
Devolver por nombre.
```python
nombre = 'mi_archivo.ods'
if nombre in app.docs:
doc = app.docs[nombre]
app.debug(doc.type, doc.title)
```

View File

@ -1,244 +0,0 @@
+++
title = "Métodos"
weight = 2
+++
### new
Crear nuevo documento, la aplicación predeterminada es Calc.
```python
doc = app.docs.new()
app.debug(doc.type)
```
Para un nuevo documento `writer`.
```python
doc = app.docs.new('writer')
app.debug(doc.type)
```
Otros documentos.
```python
doc = app.docs.new('draw')
app.debug(doc.type)
doc = app.docs.new('impress')
app.debug(doc.type)
doc = app.docs.new('math')
app.debug(doc.type)
```
Crear con argumentos.
```python
propiedades = {'Hidden': True}
doc = app.docs.new('writer', propiedades)
mensaje = f'{doc.type} - {doc.title}'
app.msgbox(mensaje)
doc.visible = True
```
{{% notice tip %}}
No es necesario que el documento este visible para manipularse.
{{% /notice %}}
### open
Abrir archivos.
```python
ruta = '/home/mau/Mi_archivo.ods'
doc = app.docs.open(ruta)
```
{{% notice tip %}}
No es necesario pasar las rutas en formato URL.
{{% /notice %}}
Puede abrir cualquier archivo que sea soportado por LibreOffice.
```python
ruta = '/home/mau/ejemplo.xlsx'
doc = app.docs.open(ruta)
```
Abrir con argumentos.
```python
ruta = '/home/mau/ejemplo.ods'
argumentos = {'Password': 'siscaloburropanzon'}
doc = app.docs.open(ruta, argumentos)
```
### save
Guardar un nuevo documento.
```python
path = '/home/mau/nuevo_documento.ods'
doc = app.docs.new()
doc.save(path)
```
Cualquier archivo, previamente guardado, que sea modificado puede ser guardado con:
```python
doc.save()
```
Abrir un archivo existente y guardarlo con otro nombre.
```python
ruta = '/home/mau/ejemplo.ods'
doc = app.docs.open(ruta)
nueva_ruta = '/home/mau/otro_nombre.ods'
doc.save(nueva_ruta)
```
### close
Cerrar un archivo.
```python
doc = app.docs.new()
app.msgbox(doc.title)
doc.close()
```
### to_pdf
Exportar a PDF.
```python
doc = app.active
ruta = '/home/mau/ejemplo.pdf'
doc.to_pdf(ruta)
```
Si no se establece una ruta, se devuelve el PDF en memoria.
```python
doc = app.active
pdf = doc.to_pdf()
app.debug(pdf)
```
Mire las [opciones del filtro de exportación a PDF][1], puede pasarlas como un diccionario como segundo argumento de este método.
### export
Exportar a otros formatos.
```python
doc = app.docs.new()
ruta = '/home/mau/miarchivo.xlsx'
filtro = 'xlsx'
doc.export(ruta, filtro)
ruta = '/home/mau/miarchivo.xls'
filtro = 'xls'
doc.export(ruta, filtro)
doc = app.docs.new('writer')
ruta = '/home/mau/miarchivo.docx'
filtro = 'docx'
doc.export(ruta, filtro)
ruta = '/home/mau/miarchivo.doc'
filtro = 'doc'
doc.export(ruta, filtro)
ruta = '/home/mau/miarchivo.rtf'
filtro = 'rtf'
doc.export(ruta, filtro)
```
Exportar en memoria.
```python
doc = app.docs.new()
filtro = 'xlsx'
excel_doc = doc.export(filter_name=filtro)
```
### set_focus
Enviar el foco al documento.
```python
for doc in app.docs:
app.debug(doc.title)
doc.set_focus()
app.sleep(1)
```
### copy
Copiar la selección activa al portapapeles.
```python
doc = app.active
doc.copy()
```
### paste
Copiar el contenido del portapapeles, en la selección actual.
```python
doc = app.active
doc.paste()
```
### paste_special
Mostrar el cuadro de diálogo `Pegado Especial`.
{{% notice tip %}}
Solo se mostrará si existe contenido en el portapapeles.
{{% /notice %}}
```python
doc = app.active
doc.paste_special()
```
### paste_values
Pegar solo los valores.
```python
doc = app.active
doc.paste_values()
```
Si el destino no esta vacío, el usuario verá el cuadro de mensaje de confirmación.
### clear_undo
La mayoría de las acciones realizadas por código, quedan en el historial de acciones, por lo que el usuario puede deshacerlas. Para eviar esto se puede limpiar este historial.
```python
doc = app.active
doc.clear_undo()
```
[1]: https://wiki.documentfoundation.org/Macros/Python_Guide/PDF_export_filter_data

View File

@ -1,189 +0,0 @@
+++
title = "Propiedades"
weight = 1
+++
#### Propiedades comúnes a todos los documentos.
### obj
**Solo lectura**. Devolver el objeto original pyUNO.
```python
doc = app.active
app.debug(type(doc))
app.debug(type(doc.obj))
```
```
18/08/2022 21:59:05 - DEBUG - <class 'easymacro.easycalc.LOCalc'>
18/08/2022 21:59:05 - DEBUG - <class 'pyuno'>
```
### title
Título del documento.
```python
doc = app.active
app.debug(doc.title)
doc.title = 'Nuevo Titulo'
app.debug(doc.title)
```
### type
**Solo lectura**. Devolver el tipo de documento: calc, writer, etc.
```python
doc = app.active
app.debug(doc.type)
```
### uid
**Solo lectura**. Devolver el valor interno RuntimeUID del documento.
```python
doc = app.active
app.debug(doc.uid)
```
### is_saved
**Solo lectura**. Si el documento ya ha sido guardado en disco.
```python
doc = app.active
app.debug(doc.is_saved)
```
### is_modified
**Solo lectura**. Si el documento ha sido modificado.
```python
doc = app.active
app.debug(doc.is_modified)
```
### is_read_only
**Solo lectura**. Si el documento es de solo lectura.
```python
doc = app.active
app.debug(doc.is_read_only)
```
### path
**Solo lectura**. Devolver la ruta en disco del documento.
```python
doc = app.active
app.debug(doc.path)
```
### dir
**Solo lectura**. Devolver solo el directorio de la ruta en disco del documento.
```python
doc = app.active
app.debug(doc.dir)
```
### file_name
**Solo lectura**. Devolver el nombre con extensión de la ruta del documento.
```python
doc = app.active
app.debug(doc.file_name)
```
### name
**Solo lectura**. Devolver el nombre sin extensión de la ruta del documento.
```python
doc = app.active
app.debug(doc.name)
```
### visible
Ocultar o mostrar un documento.
```python
doc = app.active
doc.visible = False
app.msgbox(doc.visible)
doc.visible = True
```
{{% notice tip %}}
No es necesario que el documento este visible para manipularse.
{{% /notice %}}
### zoom
Devolver o establecer el porcentaje de zoom del documento.
```python
doc = app.active
zoom = doc.zoom
app.msgbox(zoom)
doc.zoom = zoom * 2
app.msgbox(doc.zoom)
doc.zoom = zoom
```
### status_bar
Controlar la barra de estado, es importante siempre actualizar en otro hilo.
```python
@app.run_in_thread
def controlar_barra_estado(sb, texto, limite):
sb.start(texto, limite)
for i in range(limite):
sb.setValue(i)
app.sleep(1)
sb.end()
return
def main():
doc = app.active
controlar_barra_estado(doc.status_bar, 'Línea: ', 10)
return
```
Es importante siempre devolver el control de la barra de estado a la aplicación con el método `end`.
### selection
Devolver la selección actual.
```python
doc = app.active
selection = doc.selection
app.debug(selection)
```
{{% notice warning %}}
**Cuidado**, la selección actual pueden ser muchas cosas diferentes.
{{% /notice %}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

View File

@ -1,153 +0,0 @@
+++
title = "Fechas y tiempo"
weight = 2
+++
{{% notice tip %}}
La fecha inicial en Calc y en Python es diferente.
{{% /notice %}}
### today
Obtener la fecha de hoy.
```python
d = app.dates
app.msgbox(d.today)
```
### now
Obtener la fecha y hora actuales.
```python
d = app.dates
app.msgbox(d.now)
```
### time
Obtener la hora actual.
```python
d = app.dates
app.msgbox(d.now.time())
```
### epoch
Obtener el [tiempo Unix][1]
```python
d = app.dates
app.msgbox(d.epoch)
```
### date
Devolver una fecha
```python
d = app.dates
date = d.date(1974, 1, 15)
app.msgbox(date)
```
### time
Devolver un tiempo
```python
d = app.dates
time = d.time(10, 20, 15)
app.msgbox(time)
```
### datetime
Devolver fecha y hora
```python
d = app.dates
dt = d.datetime(1974, 1, 15, 10, 11, 12)
app.msgbox(dt)
```
### str_to_date
Convertir una cadena en fecha. Mira este [excelente recurso][2]
```python
d = app.dates
cadena = '1974-01-15'
plantilla = '%Y-%m-%d'
fecha = d.str_to_date(cadena, plantilla)
app.msgbox(fecha)
app.msgbox(type(fecha))
```
Para obtener un valor válido para establecer en una celda de Calc.
```python
d = app.dates
cadena = '1974-01-15'
plantilla = '%Y-%m-%d'
fecha = d.str_to_date(cadena, plantilla, True)
app.msgbox(fecha)
app.msgbox(type(fecha))
```
### calc_to_date
Convierte el valor de una celda en una fecha Python, por ejemplo, la fecha inicial configurada en Calc.
```python
d = app.dates
value_from_cell = 1
fecha = d.calc_to_date(value_from_cell)
app.msgbox(fecha)
app.msgbox(type(fecha))
```
### start y end
Medir tiempo en segundos.
```python
d = app.dates
d.start()
app.sleep(5)
seconds = d.end()
app.msgbox(seconds)
```
Regresar timedelta en vez de segundos.
```python
d = app.dates
d.start()
app.sleep(5)
td = d.end(False)
app.msgbox(td)
```
[1]: https://en.wikipedia.org/wiki/Unix_time
[2]: https://strftime.org

View File

@ -1,109 +0,0 @@
+++
title = "Correo electrónico"
weight = 3
+++
#### Enviar correo electrónico.
{{% notice tip %}}
Siempre guarda las contraseñas de la forma más segura posible.
{{% /notice %}}
### send
Enviar un correo electrónico.
```python
from conf import PASSWORD
SERVER = dict(
server = 'mail.correo.net' ,
port = 405,
ssl = True,
user = 'no-responder@pruebas.mx',
password = PASSWORD,
)
body = "Hola Ingrid\n\n¿Como estas?\n\nSaludos cordiales"
message = dict(
to = 'ingrid@bergman.mx',
subject = 'Te amo...',
body = body,
)
app.email.send(SERVER, message)
```
Puede usar los campos `cc` (Con Copia) y `bcc` (Con Copia Oculta), así como separar por comas las direcciones destino para enviar a más de un correo.
```python
to = 'mail1@correo.com,mail2@correo.com,mail3@correo.com'
cc = 'otro@correo.com'
bcc = 'oculto@correo.com'
```
Podemos enviar más de un mensaje.
```python
mensaje1 = dict(
to = 'ingrid@correo.net',
subject = 'Te amo...',
body = "Hola Ingrid\n\n¿Como estas?\n\nSaludos cordiales",
)
mensaje2 = dict(
to = 'sophia@correo.net',
subject = 'A ti también...',
body = "Hola Sophia\n\n¿Como estas?\n\nSaludos cordiales",
)
mensajes = (mensaje1, mensaje2)
app.email.send(SERVER, mensajes)
```
```
16/08/2022 13:01:49 - DEBUG - Connect to: mail.server.net
16/08/2022 13:01:50 - DEBUG - Email sent...
16/08/2022 13:01:51 - DEBUG - Email sent...
16/08/2022 13:01:51 - DEBUG - Close connection...
```
Enviar un archivo adjunto.
```python
archivo = '/home/mau/temp.txt'
mensaje = dict(
to = 'ingrid@bergman.mx',
subject = 'Te amo...',
body = "Hola Ingrid\n\n¿Como estas?\n\nSaludos cordiales",
files = archivo,
)
app.email.send(SERVER, mensaje)
```
O varios.
```python
archivos = (
'/home/mau/temp.txt',
'/home/mau/datos.csv',
)
```
Si tu cliente de correo usa el formato `mbox`, puede guardar los correos enviados en una carpeta dentro de la configuración de su cliente de correo.
```python
ruta = '/home/mau/.thunderbird/7iznrbyw.default/Mail/Local Folders/LibreOffice'
mensaje = dict(
to = 'ingrid@bergman.mx',
subject = 'Te amo...',
body = "Hola Ingrid\n\n¿Como estas?\n\nSaludos cordiales",
path = ruta,
)
app.email.send(SERVER, mensaje)
```
{{% notice tip %}}
Todos los correos se envían siempre en otro hilo de ejecución.
{{% /notice %}}

View File

@ -1,65 +0,0 @@
+++
title = "Ejecutar macros"
weight = 6
+++
Ejecutar cualquier macro, de forma predeterminada se llaman a las macros en Python localizadas en el perfil de usuario.
```python
import easymacro as app
def mostrar_info():
app.msgbox(app.INFO_DEBUG)
return
def main(args=None):
macro = {
'library': 'test',
'name': 'mostrar_info',
}
app.macro.call(macro)
return
```
Ejecutar una macro compartida en LibreOffice Macros.
```python
macro = {
'library': 'HelloWorld',
'name': 'HelloWorldPython',
'location': 'share',
}
app.macro.call(macro)
```
Ejecutar una macro Basic.
```vb
Sub mostrar_info()
MsgBox "Mejor usa Python :)"
End Sub
```
```python
macro = {
'language': 'Basic',
'library': 'Standard',
'module': 'Module1',
'name': 'mostrar_info',
}
app.macro.call(macro)
```
Cualquier macro se puede ejecutar en otro hilo.
```python
app.macro.call(macro, True)
```
Más información en: [Scripting Framework URI Specification][1]
[1]: https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification

View File

@ -1,69 +0,0 @@
+++
title = "Mensajes"
weight = 1
+++
#### Cuadros de mensaje
### msgbox
Mostrar mensaje estandar.
```python
mensaje = 'Maldito Mundo'
titulo = 'Mi Macro'
app.msgbox(mensaje, titulo)
```
### warning
Mostrar mensaje con icono de advertencia.
```python
mensaje = 'Cuidado, esta acción es peligrosa'
titulo = 'Mi Macro'
app.warning(mensaje, titulo)
```
### errorbox
Mostrar mensaje con icono de error.
```python
mensaje = 'ERROR: contacte a soporte'
titulo = 'Mi Macro'
app.errorbox(mensaje, titulo)
```
### question
Hacer una pregunta mostrando el icono de interrogación y mostrando los botones de comando `Si` y `No`. La respuesta siempre es verdadera (`True`) si el usuario selecciona `si` y falsa (`False`) en caso contrario.
```python
mensaje = '¿Es fácil Python?'
titulo = 'Mi Macro'
resultado = app.question(mensaje, titulo)
app.msgbox(resultado)
```
### inputbox
Muestra un mensaje al usuario, permitiendo capturar una respuesta.
```python
mensaje = 'Escribe tu nombre'
nombre = app.inputbox(mensaje)
app.msgbox(nombre)
```
Para ocultar solo en pantalla lo que captura el usuario, como contraseñas.
```python
mensaje = 'Captura la contraseña'
echochar = '*'
contraseña = app.inputbox(mensaje, echochar=echochar)
app.msgbox(contraseña)
```

View File

@ -1,569 +0,0 @@
+++
title = "Rutas y archivos"
weight = 2
+++
#### Trabajar con rutas y archivos.
### path
Obtener información de una ruta.
```python
ruta_archivo = '/home/mau/mi_archivo.ods'
p = app.paths(ruta_archivo)
app.debug(p.path)
app.debug(p.file_name)
app.debug(p.name)
app.debug(p.ext)
app.debug(p.size)
app.debug(p.url)
```
```
15/08/2022 14:40:08 - DEBUG - /home/mau
15/08/2022 14:40:08 - DEBUG - mi_archivo.ods
15/08/2022 14:40:08 - DEBUG - mi_archivo
15/08/2022 14:40:08 - DEBUG - ods
15/08/2022 14:40:08 - DEBUG - 7011
15/08/2022 14:40:08 - DEBUG - file:///home/mau/mi_archivo.ods
```
Obtener la misma información como un tupla.
```python
ruta_archivo = '/home/mau/mi_archivo.ods'
p = app.paths(ruta_archivo)
app.debug(p.info)
```
```
15/08/2022 14:43:01 - DEBUG - ('/home/mau', 'mi_archivo.ods', 'mi_archivo', 'ods', 7011, 'file:///home/mau/mi_archivo.ods')
```
O como diccionario.
```python
ruta_archivo = '/home/mau/mi_archivo.ods'
p = app.paths(ruta_archivo)
app.debug(p.dict)
```
```
15/08/2022 14:43:01 - DEBUG - {'path': '/home/mau', 'file_name': 'mi_archivo.ods', 'name': 'mi_archivo', 'ext': 'ods', 'size': 7011, 'url': 'file:///home/mau/mi_archivo.ods'}
```
### home
Obtener la carpeta de inicio del usuario.
```python
p = app.paths
app.debug(p.home)
```
### documents
Obtener la carpeta Documentos del usuario.
```python
p = app.paths
app.debug(p.documents)
```
### user_profile
Obtener la ruta del perfil de usuario.
```python
p = app.paths
app.debug(p.user_profile)
```
### user_config
Obtener la ruta de la carpeta `config` en el perfil de usuario.
```python
p = app.paths
app.debug(p.user_config)
```
### python
Obtener la ruta del ejecutable `python`
```python
p = app.paths
app.debug(p.python)
```
### to_system
Pasar una ruta en formato URL al formato del sistema de archivos del SO.
```python
p = app.paths
ruta_url = 'file:///home/mau/mi_archivo.ods'
ruta = p.to_system(ruta_url)
app.debug(ruta)
```
### to_url
Pasar una ruta del sistema de archivos del SO al formato URL.
```python
p = app.paths
ruta = '/home/mau/mi_archivo.ods'
ruta_url = p.to_url(ruta)
app.debug(ruta_url)
```
### config
Obtener rutas de la configuración de LibreOffice. Por default obtiene la ruta de `Documentos`, para otras ruta mire [Api XPathSettings][1]
```python
p = app.paths
ruta = p.config()
app.debug(ruta)
ruta = p.config('UserConfig')
app.debug(ruta)
```
{{% notice tip %}}
Algunas rutas pueden ser más de una, separados por `;`, en este caso, el resultado es una lista con las rutas.
{{% /notice %}}
### join
Concatenar rutas.
```python
p = app.paths
ruta = p.join('/home/mau', 'pruebas', 'archivo.ods')
app.debug(ruta)
```
### exists
Verificar si una ruta existe.
```python
p = app.paths
resultado = p.exists('/home/mau/test/archivo.ods')
app.debug(resultado)
```
### exists_app
Verificar si una aplicación existe.
```python
p = app.paths
resultado = p.exists_app('noexiste')
app.debug(resultado)
resultado = p.exists_app('soffice')
app.debug(resultado)
```
### is_dir
Verificar si la ruta es un directorio.
```python
p = app.paths
resultado = p.is_dir('/home/mau')
app.debug(resultado)
```
### is_file
Verificar si la ruta es un archivo.
```python
p = app.paths
resultado = p.is_file('/home/mau/mi_archivo.ods')
app.debug(resultado)
```
### temp_file
Crear un archivo temporal, es borrado automáticamente al cerrarse.
```python
p = app.paths
f = p.temp_file()
f.write(app.INFO_DEBUG)
f.close()
```
Usado en `contexto`, se cierra automáticamente.
```python
with p.temp_file() as f:
app.debug(f.name)
f.write('test')
```
### temp_dir
Crear un directorio temporal, al salir del contexto, es eliminado junto con todo su contenido del sistema de archivos.
```python
p = app.paths
with p.temp_dir() as d:
app.debug(p.exists(d))
app.debug(d)
app.debug(p.exists(d))
```
### get
Permitir al usuario seleccionar archivos, devuelve solo la ruta. De forma predeterminada abre en la carpeta `Documentos`.
```python
p = app.paths
ruta = p.get()
app.debug(ruta)
```
Establecer que abra en otro directorio.
```python
ruta = p.get('/tmp')
app.debug(ruta)
```
Agregar un filtro.
```python
ruta = p.get(filters='ods')
app.debug(ruta)
```
Agregar multiples filtros.
```python
ruta = p.get(filters='xml,txt')
app.debug(ruta)
```
Permitir selecciones multiples.
```python
ruta = p.get(filters='xml,txt', multiple=True)
app.debug(ruta)
```
### get_dir
Permitir al usuario seleccionar un directorio, devuelve solo la ruta. De forma predeterminada abre en la carpeta `Documentos`.
```python
p = app.paths
ruta = p.get_dir()
app.debug(ruta)
```
Establecer que abra en otro directorio.
```python
ruta = p.get_dir('/tmp')
app.debug(ruta)
```
### get_for_save
Permitir seleccionar un directorio y capturar el nombre del archivo, devuelve la ruta completa.
```python
p = app.paths
ruta = p.get_for_save()
app.debug(ruta)
```
Establecer que inicie en otro directorio.
```python
ruta = p.get_for_save('/tmp')
app.debug(ruta)
```
Si se establece un filtro, automáticamente se agrega la extensión.
```python
ruta = p.get_for_save(filters='txt')
app.debug(ruta)
```
### files
Obtener archivos de una ruta, no recursivamente. De forma predeterminada regresa todos, incluyendo archivos ocultos.
```python
ruta = '/home/mau'
p = app.paths
archivos = p.files(ruta)
for a in archivos:
app.debug(a)
```
Filtrar por tipo de archivo.
```python
p = app.paths
archivos = p.files(ruta, '*.pdf')
```
Obtener archivos de forma recursiva.
```python
p = app.paths
archivos = p.files(ruta, '**/*.xml')
```
### walk
Obtener archivos de forma recursiva.
```python
p = app.paths
ruta = '/home/mau/Documents'
archivos = p.walk(ruta)
for a in archivos:
app.debug(a)
```
Con filtro.
```python
archivos = p.walk(ruta, 'ods')
```
Con filtros.
```python
archivos = p.walk(ruta, 'ods|odt')
```
### dirs
Obtener los directorios de una ruta, no recursivamente.
```python
p = app.paths
ruta = '/home/mau/Documents'
folders = p.dirs(ruta)
for f in folders:
app.debug(f)
```
### walk_dirs
Obtener los directorios de una ruta, no recursivamente.
```python
p = app.paths
ruta = '/home/mau/Documents'
folders = p.walk_dirs(ruta)
for f in folders:
app.debug(f)
```
Obtener información en una lista de tuplas: (ID_FOLDER, ID_PADRE, NOMBRE)
```python
folders = p.walk_dirs(ruta, True)
```
### extension
Obtener la ruta de instalación de una extensión a partir de su ID.
```python
p = app.paths
id_ext = 'net.elmau.zaz.talk'
ruta = p.extension(id_ext)
app.debug(ruta)
```
### replace_ext
Reemplazar extensión de un archivo.
```python
p = app.paths
ruta = '/home/mau/mi_archivo.ods'
ruta_nueva = p.replace_ext(ruta, 'pdf')
app.debug(ruta_nueva)
```
### open
Abrir cualquier archivo con el programas predeterminado del SO.
```python
p = app.paths
ruta = '/home/mau/archivo.pdf'
p.open(ruta)
ruta = '/home/mau/index.html'
p.open(ruta)
```
### save y read
Guardar y leer datos, el encoding predeterminado es UTF8.
```python
p = app.paths
datos = """¿Quieres saber quién eres? No preguntes. Actúa.
La acción te delineará y definirá.
Thomas Jefferson
"""
ruta = '/home/mau/temp.txt'
p.save(ruta, datos)
datos = p.read(ruta)
app.msgbox(datos)
```
Cambiar el encoding.
```python
app.paths.save(ruta, datos, 'iso-8859-1')
```
### save_bin y read_bin
Guardar y leer datos binarios.
```python
p = app.paths
datos = b'Datos binarios'
ruta = '/home/mau/temp.bin'
p.save_bin(ruta, datos)
datos = p.read_bin(ruta)
app.msgbox(datos)
```
### save_json y read_json
Guardar y leer en formato json.
```python
p = app.paths
ruta = '/home/mau/datos.json'
datos = {
'tipo': 'calc',
'nombre': 'miarchivo.ods',
}
p.save_json(ruta, datos)
datos = p.read_json(ruta)
app.msgbox(datos)
```
### save_csv y read_csv
Exportar e importar datos en formato CSV. Vea la documentación [CSV][2] para los argumentos que puede usar.
```python
p = app.paths
ruta = '/home/mau/datos.csv'
ahora = app.dates.now
datos = (
(1, 'uno', ahora),
(2, 'dos', ahora),
(3, 'tres', ahora),
)
p.save_csv(ruta, datos)
datos = p.read_csv(ruta)
app.msgbox(datos)
```
### kill
Borra archivos o directorios con todo su contenido. Devuelve verdadero (True) en caso de exito y falso (Falso) en cualquier otro caso.
{{% notice warning %}}
Este proceso es destructivo, es buena practica siempre solicitar confirmación al usuario.
{{% /notice %}}
```python
p = app.paths
ruta = '/home/mau/temp.bin'
resultado = p.kill(ruta)
app.msgbox(resultado)
```
### copy
Copiar archivos. Devuelve la ruta completa final destino.
De un origen a una carpeta destino
```python
p = app.paths
ruta_origen = '/home/mau/temp.txt'
ruta_destino = '/home/mau/Desktop'
ruta = p.copy(ruta_origen, ruta_destino)
app.debug(ruta)
```
Cambiar el nombre destino.
```python
ruta_origen = '/home/mau/temp.txt'
ruta_destino = '/home/mau/Desktop'
nuevo_nombre = 'datos.csv'
ruta = p.copy(ruta_origen, ruta_destino, nuevo_nombre)
app.debug(ruta)
```
[1]: http://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1util_1_1XPathSettings.html
[2]: https://docs.python.org/3.7/library/csv.html

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

View File

@ -1,42 +0,0 @@
+++
title = "URL"
weight = 8
+++
### get
Método `get`.
```python
def prueba_get():
url = 'https://api.ipify.org'
respuesta = app.url.get(url)
if respuesta.status_code == 200:
mi_ip = respuesta.body.decode()
app.debug(f'IP: {mi_ip}')
else:
app.debug(respuesta.status_code)
return
```
```
16/08/2022 22:14:13 - DEBUG - IP: 199.203.174.159
```
Respuestas en formato json.
```python
def prueba_get():
url = 'https://api.ipify.org/?format=json'
respuesta = app.url.get(url)
if respuesta.status_code == 200:
datos = respuesta.json()
app.debug(f'IP: {datos["ip"]}')
else:
app.debug(respuesta.status_code)
return
```

View File

@ -1,198 +0,0 @@
+++
title = "Utilidades"
weight = 9
+++
### dict_to_property
Convertir diccionarios en PropertyValue
```python
datos = {
'Hidden': True,
'Password': 'letmein',
}
propiedades = app.dict_to_property(datos)
app.msgbox(propiedades)
```
### data_to_dict
Convertir `PropertyValue` en diccionarios
```python
datos = app.data_to_dict(propiedades)
app.msgbox(datos)
```
Convertir `tuplas` a diccionario.
```python
tupla_de_tuplas = (
('Hidden', True),
('Password', 'letmein'),
)
datos = app.data_to_dict(tupla_de_tuplas)
app.msgbox(datos)
```
Convertir `listas` a diccionario.
```python
lista_de_listas = [
['Hidden', True],
['Password', 'letmein'],
]
datos = app.data_to_dict(lista_de_listas)
app.msgbox(datos)
```
### sleep
Hacer una pausa de X segundos.
```python
app.sleep(5)
```
### render
Reemplazar variables en cadenas de texto.
```python
plantilla = """Hola $nombre
Te envío este archivo: $archivo
Saludos cordiales
"""
datos = {
'nombre': 'Ingrid Bergman',
'archivo': 'carta_de_amor.odt'
}
resultado = app.render(plantilla, datos)
app.msgbox(resultado)
```
### run
Ejecutar un programa.
```python
nombre_aplicacion = 'gnome-calculator'
app.shell.run(nombre_aplicacion)
```
Ejecutar comandos shell y capturar la salida.
```python
comandos = 'ls -lh ~'
resultado = app.shell.run(comandos, True)
app.debug(resultado)
```
```
drwxr-xr-x 4 mau mau 4.0K Aug 15 23:36 Desktop
drwxr-xr-x 6 mau mau 4.0K Jun 9 23:32 Documents
drwxr-xr-x 5 mau mau 4.0K Aug 16 13:09 Downloads
drwxr-xr-x 3 mau mau 4.0K Aug 14 15:19 Pictures
drwxr-xr-x 10 mau mau 4.0K Jun 19 19:36 Projects
drwxr-xr-x 2 mau mau 4.0K May 11 22:36 Templates
drwxr-xr-x 2 mau mau 4.0K Jul 19 13:37 Videos
```
Ejectuar comandos y capturar la salida línea a línea.
```python
comandos = 'ls -lh /home/mau'
for line in app.shell.popen(comandos):
app.debug(line)
```
### digest
Obtener hash. Por default se regresa en hexadecimal.
```python
datos = 'LibreOffice con Python'
digest = app.hash.digest('md5', datos)
app.debug('MD5 = ', digest)
digest = app.hash.digest('sha1', datos)
app.debug('SHA1 = ', digest)
digest = app.hash.digest('sha256', datos)
app.debug('SHA256 = ', digest)
digest = app.hash.digest('sha512', datos)
app.debug('SHA512 = ', digest)
```
```
16/08/2022 18:48:07 - DEBUG - MD5 = 3801759ead20abc3ce0d0095289bdcfd
16/08/2022 18:48:07 - DEBUG - SHA1 = 1df74aaae9658c21074aa5a2d4c2055dcf79f0db
16/08/2022 18:48:07 - DEBUG - SHA256 = 228e90b15b6259307e580677939b1f2f45e9317461e98f603af8fcac0f9a598f
16/08/2022 18:48:07 - DEBUG - SHA512 = 3ef45f79f3bfd2b251d250489c91b631306456405510397fb1a7ee37005d196376b7d6ca86a9895f4eb97eb74813965c24d6564a383f4bdb1360665c8fbb192a
```
Para obtener bytes.
```
digest = app.hash.digest('md5', datos, False)
app.debug('MD5 = ', digest)
```
```
16/08/2022 18:48:07 - DEBUG - MD5 = b'8\x01u\x9e\xad \xab\xc3\xce\r\x00\x95(\x9b\xdc\xfd'
```
### config
Puede guardar datos de configuración de su macro o extensión dentro del perfil de usuario.
```python
nombre = 'mi_extension'
datos = {
'ruta': '/home/mau/pruebas',
'guardar': True,
}
if app.config.set(nombre, datos):
app.debug('Configuración guardada...')
```
Y recuperarlos en cualquier momento.
```
datos = app.config.get(nombre)
app.debug(datos)
```
### color
Puede ver los colores que puede usar en Wikipedia [Colores Web][1]
```python
color_nombre = 'darkblue'
color = app.color(color_nombre)
app.debug(color)
color_rgb = (125, 200, 10)
color = app.color(color_rgb)
app.debug(color)
color_html = '#008080'
color = app.color(color_html)
app.debug(color)
```
[1]: https://es.wikipedia.org/wiki/Colores_web

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

View File

@ -1,8 +0,0 @@
# Bienvenue dans la documentation easymacro!
**easymacro** est une bibliothèque permettant de développer facilement des macros LibreOffice avec Python. Il s'agit d'une couche d'abstraction entre l'API étendue et complexe de LibreOffice UNO et votre code.
Vous serez probablement plus heureux si vous l'utilisez :)
Vous pouvez utiliser **easymacro** avec n'importe quelle extension ou directement dans vos macros.

View File

@ -1,8 +0,0 @@
# Bem-vindo à documentação easymacro!
**easymacro*** é uma biblioteca para desenvolver facilmente macros en LibreOffice con Python. É uma camada de abstração entre o extenso e complexo LibreOffice API UNO e seu código.
Provavelmente, você ficará mais feliz se o utilizar :)
Você pode usar **easymacro** com qualquer extensão ou diretamente em suas macros.

View File

@ -1,52 +0,0 @@
+++
title = "Instalação"
weight = 1
+++
## Clonar repositorio
Clone el repositorio en su directorio de proyectos favorito.
```
git clone https://git.cuates.net/elmau/easymacro
```
y copie la librería dentro de la carpeta **pythonpath** en la carpeta de macros Python dentro de su perfil de usuario. Reemplace **USUARIO** por su usuario real.
```
/home/`USUARIO`/.config/libreoffice/4/user/Scripts/python/pythonpath/easymacro.py
```
o use un vínculo duro. Reemplace **RUTA_ABSOLUTA** por la ruta absoluta donde se localice **easymacro.py** en su sistema de archivos y **USUARIO** por su nombre de usuario.
```
ln `RUTA_ABSOLUTA`/easymacro/source/easymacro.py /home/`USUARIO`/.config/libreoffice/4/user/Scripts/python/pythonpath/
```
## Probar
En su archivo de macros favorito, por ejemplo **mismacros.py**:
```
vim /home/`USUARIO`/.config/libreoffice/4/user/Scripts/python/mismacros.py
```
Copie el siguiente código:
```python
import easymacro as app
def main():
app.msgbox(app.INFO_DEBUG)
return
```
Ejecute la macro **main** desde LibreOffice, si ve un cuadro de mensaje con información similar a la siguiente, !felicidades¡
![Test instalation](install_01.png)
Esta listo para desarrollar macros con **easymacro.py**.
!Feliz programación!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

162
doc/docs/app/index.md Normal file
View File

@ -0,0 +1,162 @@
---
title: Aplicación
---
### **fonts**
Devolver todas las fuentes visibles en LibreOffice. Mire [FontDescriptor][1]
```py
fuentes = app.fonts()
for f in fuentes:
app.debug(f'Nombre: {f.Name} - Estilo: {f.StyleName}')
```
<br>
### **filters**
Devolver todos los filtros soportados en LibreOffice. Mire la [ayuda][2] y en [API FilterFactory][3] para más detalles.
```py
filtros = app.filters()
for f in filtros:
info = f"Nombre UI: {f['UIName']} - Nombre: {f['Name']} - Tipo: {f['Type']}"
app.debug(info)
```
<br>
### **dispatch**
Ejecutar cualquier comando `UNO` de LibreOffice, mire la [lista de comandos][4] y [API dispatch][5].
Este método automáticamente agrega el prefijo necesario: `.uno:`
```py
doc = app.active
comando = 'Gallery'
app.dispatch(doc, comando)
```
!!! tip "Recomendación"
Use este método solamente si no hay un método equivalente en `easymacro` o directamente en el API de LibreOffice.
<br>
### **clipboard**
#### **set**
Envíar contenido (solo texto) al portapapeles.
```py
app.clipboard.set('Los 7 samuráis')
```
#### **get**
Recuperar contenido del portapapeles.
```py
content = app.clipboard.get()
app.debug(content)
```
<br>
### **comandos**
!!! warning "Cuidado"
En este momento, en LibreOffice 7.4, este comando provoca el cierre de la aplicación.
#### **disable**
Deshabilitar un comando. Para una lista de comandos mire [DispatchCommands][4].
```py
comando = 'OpenFromCalc'
resultado = app.cmd.disable(comando)
app.debug(resultado)
```
`OpenFromCalc` es la opción para abrir documentos en Calc, deshabilita o habilita la entrada del menú y el icono en la barra de herramientas.
<br>
#### **enabled**
Habilitar un comando.
```py
comando = 'OpenFromCalc'
resultado = app.cmd.enabled(comando)
app.debug(resultado)
```
<br>
### **Configuración**
#### **get_config**
Obtener valores de la configuración de LibreOffice.
```py
nombre_node = '/org.openoffice.Office.Common/Help'
clave = 'System'
valor = app.get_config(nombre_node, clave)
app.debug(valor)
nombre_node = '/org.openoffice.Office.Common/Misc/'
clave = 'FirstRun'
valor = app.get_config(nombre_node, clave)
app.debug(valor)
clave = 'UseSystemFileDialog'
valor = app.get_config(nombre_node, clave)
app.debug(valor)
```
```
17/08/2022 14:14:12 - DEBUG - UNIX
17/08/2022 14:14:12 - DEBUG - False
17/08/2022 14:14:12 - DEBUG - True
```
<br>
#### **set_config**
Establece un nuevo valor en la configuración de LibreOffice.
```py
nombre_nodo = '/org.openoffice.Office.UI/ColorScheme'
clave = 'CurrentColorScheme'
nuevo_valor = 'LibreOffice Dark'
resultado = app.set_config(nombre_nodo, clave, nuevo_valor)
app.debug(resultado)
```
<br>
Algunos nodos y claves interesantes:
* `/org.openoffice.Office.Common/Save/Document`
* AutoSave
* AutoSaveTimeIntervall
!!! warning "Atención"
No todos los valores de los nodos se pueden cambiar, algunos valores son de solo lectura.
<br>
[1]: https://api.libreoffice.org/docs/idl/ref/structcom_1_1sun_1_1star_1_1awt_1_1FontDescriptor.html
[2]: https://help.libreoffice.org/latest/en-US/text/shared/guide/convertfilters.html
[3]: https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1document_1_1FilterFactory.html
[4]: https://wiki.documentfoundation.org/Development/DispatchCommands
[5]: https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1frame_1_1XDispatch.html#a42beb1ea2ddae35c076b6e65867025ea

View File

@ -1,9 +1,5 @@
+++
title = "Menús"
weight = 2
+++
### insert
### **insert**
Insertar nuevo menú en Calc.
@ -11,93 +7,102 @@ En la propiedad `CommandURL` es posible establecer tanto un comando UNO de Libre
El nombre del menú es importante para cuando se quiera eliminar.
```python
nombre_menu = 'zaz.my.menu'
menu = {
'Label': 'My menu',
'CommandURL': nombre_menu,
'Submenu': [
{
'Label': 'Open Macros Dialog...',
'CommandURL': 'MacroDialog',
},
{
'Label': '-',
},
{
'Label': 'My macro',
'CommandURL': {'library': 'test', 'name': 'hola'},
},
{
'Label': 'Execute macro...',
'CommandURL': 'RunMacro',
'ShortCut': 'Shift+Ctrl+Alt+E',
},
]
}
```py
nombre_menu = 'zaz.my.menu'
menu = {
'Label': 'My menu',
'CommandURL': nombre_menu,
'Submenu': [
{
'Label': 'Open Macros Dialog...',
'CommandURL': 'MacroDialog',
},
{
'Label': '-',
},
{
'Label': 'My macro',
'CommandURL': {'library': 'test', 'name': 'hola'},
},
{
'Label': 'Execute macro...',
'CommandURL': 'RunMacro',
'ShortCut': 'Shift+Ctrl+Alt+E',
},
]
}
menus_calc = app.menus['calc']
menus_calc.insert(menu)
menus_calc = app.menus['calc']
menus_calc.insert(menu)
```
!!! tip
### remove
Para controlar los menús de las demás aplicaciones, solo hay que cambiar el nombre de la aplicación.
<br>
### **remove**
Eliminar un menú existente.
```python
nombre_menu = 'zaz.my.menu'
menus_calc = app.menus['calc']
menus_calc.remove(nombre_menu)
```py
nombre_menu = 'zaz.my.menu'
menus_calc = app.menus['calc']
menus_calc.remove(nombre_menu)
```
#### Insertar nuevo menú en uno existente.
<br>
### **Insertar en menú existente**
Dentro del menú Herramientas (`tools`), después de la opción `Macros...`
```python
menu = app.menus['calc']['tools']
```py
menu = app.menus['calc']['tools']
menu_nombre = 'zaz.my.menu'
menu_nuevo = {
'Label': 'My menu',
'CommandURL': menu_nombre,
'Submenu': [
{
'Label': 'Open Macros Dialog...',
'CommandURL': 'MacroDialog',
},
{
'Label': '-',
},
{
'Label': 'My macro',
'CommandURL': {'library': 'test', 'name': 'hello'},
},
{
'Label': 'Execute macro...',
'CommandURL': 'RunMacro',
'ShortCut': 'Shift+Ctrl+Alt+E',
},
]
}
menu_nombre = 'zaz.my.menu'
menu_nuevo = {
'Label': 'My menu',
'CommandURL': menu_nombre,
'Submenu': [
{
'Label': 'Open Macros Dialog...',
'CommandURL': 'MacroDialog',
},
{
'Label': '-',
},
{
'Label': 'My macro',
'CommandURL': {'library': 'test', 'name': 'hello'},
},
{
'Label': 'Execute macro...',
'CommandURL': 'RunMacro',
'ShortCut': 'Shift+Ctrl+Alt+E',
},
]
}
if menu_nombre in menu:
menu.remove(menu_nombre)
else:
menu.insert(menu_nuevo, '.uno:MacrosMenu')
if menu_nombre in menu:
menu.remove(menu_nombre)
else:
menu.insert(menu_nuevo, '.uno:MacrosMenu')
```
### debug
<br>
### **debug**
Para saber los nombres de cualquier menú.
```python
menu = app.menus['calc']['tools']
menu.debug()
```py
menu = app.menus['calc']['tools']
menu.debug()
```
```
```sh
(0) .uno:SpellDialog
(1) .uno:SpellOnline
(2) .uno:ThesaurusDialog
@ -169,3 +174,5 @@ menu.debug()
(27) .uno:ConfigureDialog
(28) .uno:OptionsTreeDialog
```
<br>

126
doc/docs/app/shortcuts.md Normal file
View File

@ -0,0 +1,126 @@
### **Globales**
Iterar en todos los accesos directos. Accesos directos disponibles para todas las aplicaciones.
```py
for acceso_directo, comando in app.shortcuts:
app.debug(acceso_directo, comando)
```
Devolver una lista de tuplas con toda la información.
```py
datos = app.shortcuts.get_all()
app.debug(datos)
```
Verificar si un acceso directo esta asignado.
```py
acceso_directo = 'Shift+Ctrl+Alt+T'
app.debug(acceso_directo in app.shortcuts)
```
<br>
### **set**
Establecer un acceso directo a un comando.
```py
sc = app.shortcuts
acceso_directo = 'Shift+Ctrl+Alt+T'
comando = 'MacroDialog'
sc.set(acceso_directo, comando)
```
Establecer un acceso directo a una macro.
!!! tip inline end
Para la asignación de una macros, aplican las mismas reglas de: [ejecutar macros](../../tools/macros/)
```py
sc = app.shortcuts
acceso_directo = 'Shift+Ctrl+Alt+M'
macro = {'library': 'test', 'name': 'pruebas'}
sc.set(acceso_directo, macro)
```
<br>
### **get_by_shortcut**
Devolver el comando asociado a un acceso directo.
```py
sc = app.shortcuts
acceso_directo = 'Shift+Ctrl+Alt+M'
comando = sc.get_by_shortcut(acceso_directo)
app.debug(comando)
```
<br>
### **get_by_command**
Devolver el acceso directo asociado a un comando. Puede haber más de uno.
```py
sc = app.shortcuts
comando = 'MacroDialog'
acceso_directo = sc.get_by_command(comando)
app.debug(acceso_directo)
```
<br>
### **remove_by_shortcut**
Eliminar por acceso directo.
```py
sc = app.shortcuts
acceso_directo = 'Shift+Ctrl+Alt+T'
sc.remove_by_shortcut(acceso_directo)
```
<br>
### **remove_by_command**
Eliminar por comando.
```py
sc = app.shortcuts
macro = {'library': 'test', 'name': 'pruebas'}
sc.remove_by_command(macro)
```
<br>
### **reset**
Reiniciar todas las modificaciones.
```py
app.shortcuts.reset()
```
<br>
### **Por aplicación**
Modificar accesos directos, solo en una aplicación.
Por ejemplo Calc.
```py
sc = app.shortcuts['calc']
```
Los métodos son los mismos que los globales.
Para las demas aplicaciones: `writer`, `draw`, `impress`, `math`.
<br>

View File

@ -1,15 +1,14 @@
+++
title = "Herramientas para depurar"
weight = 2
+++
## Herramientas para depurar
### INFO_DEBUG
<br>
### **INFO_DEBUG**
Mostrar información de depuración en un cuadro de mensaje.
Si tiene cualquier problema en su código durante el desarrollo de sus macros, puede [abrir un ticket][1] de soporte en el sistema de ticket de este proyecto. Siempre copie la información de depuración mostrada en este mensaje.
```python
```py
import easymacro as app
def info():
@ -17,14 +16,14 @@ def info():
return
```
![Info debug](tools_01.png)
![Info debug](img/install_01.png)
### debug
### **debug**
Mostrar información en la terminal.
```python
```py
import easymacro as app
def test_debug():
@ -33,16 +32,23 @@ def test_debug():
return
```
Para ver este mensaje, es necesario iniciar LibreOffice desde la línea de comandos:
```
11/08/2022 18:15:45 - DEBUG - Verificar esta información...
soffice --calc
```
Después de ejecutar la macro anterior, debe de ver:
```
21/04/2023 17:04:49 - DEBUG - Verificar esta información...
```
### info
<br>
### **info**
Mostrar mensajes informativos en la terminal.
```python
```py
import easymacro as app
def test_info():
@ -55,12 +61,13 @@ def test_info():
11/08/2022 18:23:53 - INFO - Iniciando proceso...
```
<br>
### error
### **error**
Mostrar mensajes de error en la terminal.
```python
```py
import easymacro as app
def test_error():
@ -73,12 +80,13 @@ def test_error():
11/08/2022 18:27:34 - ERROR - Error 505
```
<br>
### save_log
### **save_log**
Guardar registro en un archivo, automáticamente se agrega la fecha y hora.
```python
```py
import easymacro as app
def test_save_log():
@ -95,12 +103,15 @@ cat ~/log.txt
2022-08-11 18:30:11 - 'Maldito Mundo'
```
<br>
### msgbox
### **msgbox**
Mostrar cualquier información en un cuadro de mensaje.
```python
import easymacro as app
def message():
msg = 'Por favor, consume menos.'
@ -117,11 +128,19 @@ def message():
return
```
### catch_exception
<br>
### **catch_exception**
Capturar cualquier error que se produzca al ejecutar una macro.
```python
!!! warning inline end "Cuidado"
Usa este método solo en tiempo de desarrollo. **No la use en producción**.
```py
import easymacro as app
@app.catch_exception
def test_capturar_error():
r = 1 / 0
@ -138,28 +157,30 @@ Traceback (most recent call last):
ZeroDivisionError: division by zero
```
{{% notice warning %}}
Usa este método solo en tiempo de desarrollo. No la uses en producción.
{{% /notice %}}
<br>
### mri
### **mri**
[MRI][2] es la mejor extensión para inspeccionar cualquier objeto UNO de LibreOffice. Necesita instalarla primero para poder llamarla.
```py
import easymacro as app
```python
def inspeccionar_objeto():
obj = app.active
app.mri(obj)
return
```
### inspect
<br>
### **inspect**
Inspeccionar un objeto.
```python
```py
import easymacro as app
def inspeccionar_objeto():
doc = app.active
data = app.inspect(doc)
@ -170,7 +191,7 @@ def inspeccionar_objeto():
return
```
Vaciar en una hoja de calculo.
Vaciar la información del objeto en una hoja de calculo.
```python
def inspeccionar_objeto():

75
doc/docs/docs/index.md Normal file
View File

@ -0,0 +1,75 @@
---
title: Documentos
---
## Trabajar con Documentos
<br>
### **active**
Devuelve el documento activo.
```py
doc = app.active
app.msgbox(doc.title)
```
<br>
### **iteration**
Iterar en todos los documentos abiertos.
```py
for doc in app.docs:
app.debug(doc.type, doc.title)
```
<br>
### **count**
Contar los documentos abiertos.
```py
cuantos = len(app.docs)
app.debug(cuantos)
```
<br>
### **contain**
Verificar si un documento esta en la colección.
```py
resultado = 'mi_archivo.ods' in app.docs
app.debug(resultado)
```
<br>
### **index**
Devolver por índice.
```py
doc = app.docs[1]
app.debug(doc.type, doc.title)
```
<br>
### **name**
Devolver por nombre.
```py
nombre = 'mi_archivo.ods'
if nombre in app.docs:
doc = app.docs[nombre]
app.debug(doc.type, doc.title)
```
<br>

263
doc/docs/docs/methods.md Normal file
View File

@ -0,0 +1,263 @@
## Métodos comúnes a todos los documentos.
<br>
### **clear_undo**
La mayoría de las acciones realizadas por código, quedan en el historial de acciones, por lo que el usuario puede deshacerlas. Para evitar esto se puede limpiar este historial.
```py
doc = app.active
doc.clear_undo()
```
<br>
### **close**
Cerrar un archivo.
```py
doc = app.docs.new()
app.msgbox(doc.title)
doc.close()
```
<br>
### **copy**
Copiar la selección activa al portapapeles.
```py
doc = app.active
doc.copy()
```
<br>
### **export**
Exportar a otros formatos.
```py
doc = app.docs.new()
ruta = '/home/elmau/miarchivo.xlsx'
filtro = 'xlsx'
doc.export(ruta, filtro)
ruta = '/home/elmau/miarchivo.xls'
filtro = 'xls'
doc.export(ruta, filtro)
doc = app.docs.new('writer')
ruta = '/home/elmau/miarchivo.docx'
filtro = 'docx'
doc.export(ruta, filtro)
ruta = '/home/elmau/miarchivo.doc'
filtro = 'doc'
doc.export(ruta, filtro)
ruta = '/home/elmau/miarchivo.rtf'
filtro = 'rtf'
doc.export(ruta, filtro)
```
Exportar en memoria.
```python
doc = app.docs.new()
filtro = 'xlsx'
excel_doc = doc.export(filter_name=filtro)
```
<br>
### **new**
Crear nuevo documento, la aplicación predeterminada es Calc.
```py
doc = app.docs.new()
app.debug(doc.type)
```
Para un nuevo documento `writer`.
```py
doc = app.docs.new('writer')
app.debug(doc.type)
```
Otros documentos.
```py
doc = app.docs.new('draw')
app.debug(doc.type)
doc = app.docs.new('impress')
app.debug(doc.type)
doc = app.docs.new('math')
app.debug(doc.type)
```
Crear con argumentos.
```py
propiedades = {'Hidden': True}
doc = app.docs.new('writer', propiedades)
mensaje = f'{doc.type} - {doc.title}'
app.msgbox(mensaje)
doc.visible = True
```
!!! tip
No es necesario que un documento este visible para manipularse.
<br>
### **open**
Abrir archivos.
```py
ruta = '/home/elmau/mi_archivo.ods'
doc = app.docs.open(ruta)
```
!!! tip "Consejo"
No es necesario pasar las rutas en formato URL.
Puede abrir cualquier archivo que sea soportado por LibreOffice.
```py
ruta = '/home/elmau/ejemplo.xlsx'
doc = app.docs.open(ruta)
```
Abrir con argumentos.
```py
ruta = '/home/elmau/ejemplo.ods'
argumentos = {'Password': 'siscaloburropanzon'}
doc = app.docs.open(ruta, argumentos)
```
<br>
### **paste**
Copiar el contenido del portapapeles, en la selección actual.
```py
doc = app.active
doc.paste()
```
<br>
### **paste_special**
Mostrar el cuadro de diálogo `Pegado Especial`.
!!! tip "Consejo"
Solo se mostrará si existe contenido en el portapapeles.
```py
doc = app.active
doc.paste_special()
```
<br>
### **paste_values**
Pegar solo los valores.
```py
doc = app.active
doc.paste_values()
```
Si el destino no esta vacío, el usuario verá el cuadro de mensaje de confirmación.
<br>
### **save**
Guardar un nuevo documento.
```py
path = '/home/elmau/nuevo_documento.ods'
doc = app.docs.new()
doc.save(path)
```
Cualquier archivo, previamente guardado, que sea modificado puede ser guardado con:
```python
doc.save()
```
Abrir un archivo existente y guardarlo con otro nombre.
```py
ruta = '/home/mau/ejemplo.ods'
doc = app.docs.open(ruta)
nueva_ruta = '/home/mau/otro_nombre.ods'
doc.save(nueva_ruta)
```
<br>
### **set_focus**
Enviar el foco al documento.
```py
for doc in app.docs:
app.debug(doc.title)
doc.set_focus()
app.sleep(1)
```
<br>
### **to_pdf**
Exportar a PDF.
```py
doc = app.active
ruta = '/home/elmau/ejemplo.pdf'
doc.to_pdf(ruta)
```
Si no se establece una ruta, se devuelve el PDF en memoria.
```py
doc = app.active
pdf = doc.to_pdf()
app.debug(pdf)
```
Mire las [opciones del filtro de exportación a PDF][1], puede pasarlas como un diccionario como segundo argumento de este método.
Por ejemplo, exportar solo las páginas 2 a 4:
```py
doc = app.active
ruta = '/home/elmau/ejemplo.pdf'
opciones = {'PageRange': '2-4'}
doc.to_pdf(ruta, opciones)
```
<br>
[1]: https://wiki.documentfoundation.org/Macros/Python_Guide/PDF_export_filter_data

220
doc/docs/docs/properties.md Normal file
View File

@ -0,0 +1,220 @@
## Propiedades comúnes a todos los documentos.
<br>
Recordemos, el documento activo lo referenciamos con:
```py
doc = app.active
```
<br>
### **dir**
**Solo lectura**. Devolver solo el directorio de la ruta en disco del documento.
```py
doc = app.active
app.debug(doc.dir)
```
<br>
### **file_name**
**Solo lectura**. Devolver el nombre con extensión de la ruta del documento.
```py
doc = app.active
app.debug(doc.file_name)
```
<br>
### **is_modified**
**Solo lectura**. Si el documento ha sido modificado.
```py
doc = app.active
app.debug(doc.is_modified)
```
<br>
### **is_read_only**
**Solo lectura**. Si el documento es de solo lectura.
```py
doc = app.active
app.debug(doc.is_read_only)
```
<br>
### **is_saved**
**Solo lectura**. Si el documento ya ha sido guardado en disco.
```py
doc = app.active
app.debug(doc.is_saved)
```
<br>
### **name**
**Solo lectura**. Devolver el nombre sin extensión de la ruta del documento.
```py
doc = app.active
app.debug(doc.name)
```
<br>
### **obj**
**Solo lectura**. Devolver el objeto original pyUNO.
```py
doc = app.active
app.debug(type(doc))
app.debug(type(doc.obj))
```
```sh
18/08/2022 21:59:05 - DEBUG - <class 'easymacro.easycalc.LOCalc'>
18/08/2022 21:59:05 - DEBUG - <class 'pyuno'>
```
<br>
### **path**
**Solo lectura**. Devolver la ruta en disco del documento.
```py
doc = app.active
app.debug(doc.path)
```
<br>
### **selection**
Devolver la selección actual.
```py
doc = app.active
selection = doc.selection
app.debug(selection)
```
<br>
!!! warning "Cuidado"
La selección actual pueden ser muchas cosas diferentes.
<br>
### **status_bar**
Controlar la barra de estado, es importante siempre actualizar en otro hilo.
```py
@app.run_in_thread
def controlar_barra_estado(sb, texto, limite):
sb.start(texto, limite)
for i in range(limite):
sb.setValue(i)
app.sleep(1)
sb.end()
return
def main():
doc = app.active
controlar_barra_estado(doc.status_bar, 'Línea: ', 10)
return
```
Es importante siempre devolver el control de la barra de estado a la aplicación con el método `end`.
<br>
### **title**
Título del documento.
```py
doc = app.active
app.debug(doc.title)
doc.title = 'Nuevo Titulo'
app.debug(doc.title)
```
!!! tip "Consejo"
El cambio no es permanente, solo mientras el documento esta abierto.
<br>
### **type**
**Solo lectura**. Devolver el tipo de documento: calc, writer, etc.
```py
doc = app.active
app.debug(doc.type)
```
<br>
### **uid**
**Solo lectura**. Devolver el valor interno RuntimeUID del documento.
```py
doc = app.active
app.debug(doc.uid)
```
<br>
### **visible**
Ocultar o mostrar un documento.
```py
doc = app.active
doc.visible = False
app.msgbox(doc.visible)
doc.visible = True
```
!!! tip "Consejo"
No es necesario que el documento este visible para manipularse.
<br>
### **zoom**
Devolver o establecer el porcentaje de zoom del documento.
```py
doc = app.active
zoom = doc.zoom
app.msgbox(zoom)
doc.zoom = zoom * 2
app.msgbox(doc.zoom)
doc.zoom = zoom
```
<br>

BIN
doc/docs/img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
doc/docs/img/install_01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
doc/docs/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

29
doc/docs/index.md Normal file
View File

@ -0,0 +1,29 @@
# Bienvenido a la documentación para EasyMacro
**Software Libre, no software gratis**
<br>
**easymacro** es una librería para desarrollar más fácilmente macros en LibreOffice con Python. Es una capa de abstracción entre la extensa y compleja API UNO de LibreOffice y tu código.
Probablemente, será más feliz si la usa :)
Puede utilizar **easymacro** con cualquier extensión o directamente en sus macros.
<br>
- Proyectos similiares o relacionados en Python:
* [python-ooo-dev-tools](https://python-ooo-dev-tools.readthedocs.io)
* [oooscript](https://oooscript.readthedocs.io)
* [python-ooouno-ex](https://github.com/Amourspirit/python-ooouno-ex)
- Proyectos similiares o relacionados en otros lenguajes:
* [Java LibreOffice Programming](https://flywire.github.io/lo-p/)
<br>
Aportaciones:
- en Moneda Libre Ğ1 (Junas):<br>
`A5DdXxCKPw3QKWVdDVs7CzkNugNUW1sHu5zDJFWxCU2h`
<br>

View File

@ -1,8 +1,3 @@
+++
title = "Instalación"
weight = 1
+++
## Clonar repositorio
Clone el repositorio en su directorio de proyectos favorito.
@ -19,13 +14,13 @@ cd easymacro/source
copie la carpeta `easymacro` a la carpeta **pythonpath** en la carpeta de macros Python dentro de su perfil de usuario. Reemplace **USUARIO** por su usuario real.
```
/home/`USUARIO`/.config/libreoffice/4/user/Scripts/python/pythonpath
/home/USUARIO/.config/libreoffice/4/user/Scripts/python/pythonpath
```
o use un vínculo simbólico. Reemplace **RUTA_ABSOLUTA** por la ruta absoluta donde se localice **easymacro** en su sistema de archivos y **USUARIO** por su nombre de usuario.
o use un vínculo simbólico (recomendado). Reemplace **RUTA_ABSOLUTA** por la ruta absoluta donde se localice **easymacro** en su sistema de archivos y **USUARIO** por su nombre de usuario.
```
ln -s `RUTA_ABSOLUTA`/easymacro/source/easymacro /home/`USUARIO`/.config/libreoffice/4/user/Scripts/python/pythonpath/
ln -s RUTA_ABSOLUTA/easymacro/source/easymacro /home/USUARIO/.config/libreoffice/4/user/Scripts/python/pythonpath/
```
@ -34,12 +29,12 @@ ln -s `RUTA_ABSOLUTA`/easymacro/source/easymacro /home/`USUARIO`/.config/libreof
En su archivo de macros favorito, por ejemplo **mismacros.py**. Use su editor de texto plano o IDE favorito.
```
vim /home/`USUARIO`/.config/libreoffice/4/user/Scripts/python/mismacros.py
vim /home/USUARIO/.config/libreoffice/4/user/Scripts/python/mismacros.py
```
Copie el siguiente código:
```python
```py
import easymacro as app
def main():
@ -49,7 +44,7 @@ def main():
Ejecute la macro **main** desde LibreOffice, si ve un cuadro de mensaje con información similar a la siguiente, !felicidades¡
![Test instalation](install_01.png)
![Test instalation](img/install_01.png)
Esta todo listo para empezar a desarrollar macros con **easymacro**.

177
doc/docs/tools/datetime.md Normal file
View File

@ -0,0 +1,177 @@
!!! tip "Atención"
La fecha inicial en Calc y en Python son diferentes.
<br>
### **today**
Obtener la fecha actual.
```py
d = app.dates
app.msgbox(d.today)
```
<br>
### **now**
Obtener la fecha y hora actuales.
```py
d = app.dates
app.msgbox(d.now)
```
<br>
### **time**
Obtener la hora actual.
```py
d = app.dates
app.msgbox(d.now.time())
```
<br>
### **epoch**
Obtener el [tiempo Unix][1]
```py
d = app.dates
app.msgbox(d.epoch)
```
<br>
### **date**
Devolver una fecha
```py
d = app.dates
date = d.date(1974, 1, 15)
app.msgbox(date)
```
<br>
### **time**
Devolver una hora
```py
d = app.dates
time = d.time(10, 20, 15)
app.msgbox(time)
```
<br>
### **datetime**
Devolver fecha y hora
```py
d = app.dates
dt = d.datetime(1974, 1, 15, 10, 11, 12)
app.msgbox(dt)
```
<br>
### **str_to_date**
Convertir una cadena en fecha. Mira este [excelente recurso][2]
```py
d = app.dates
cadena = '1974-01-15'
plantilla = '%Y-%m-%d'
fecha = d.str_to_date(cadena, plantilla)
app.msgbox(fecha)
app.msgbox(type(fecha))
```
Para obtener un valor válido para establecer en una celda de Calc.
```py
d = app.dates
cadena = '1974-01-15'
plantilla = '%Y-%m-%d'
fecha = d.str_to_date(cadena, plantilla, True)
app.msgbox(fecha)
app.msgbox(type(fecha))
```
<br>
### **calc_to_date**
Convierte el valor de una celda en una fecha Python, por ejemplo, la fecha inicial configurada en Calc.
```py
d = app.dates
valor_en_celda = 0
fecha = d.calc_to_date(valor_en_celda)
app.msgbox(fecha)
app.msgbox(type(fecha))
```
<br>
### **sleep**
Pausar la ejecución por X segundos.
!!! tip inline end "Atención"
La pausa es bloqueante.
```py
d = app.dates
app.sleep(3)
app.msgbox('Fin')
```
<br>
### **start** y **end**
Medir tiempo en segundos.
```py
d = app.dates
d.start()
app.sleep(5)
seconds = d.end()
app.msgbox(seconds)
```
Regresar timedelta en vez de segundos.
```py
d = app.dates
d.start()
app.sleep(5)
td = d.end(False)
app.msgbox(td)
```
[1]: https://es.wikipedia.org/wiki/Tiempo_Unix
[2]: https://strftime.org

144
doc/docs/tools/email.md Normal file
View File

@ -0,0 +1,144 @@
## Enviar correo electrónico.
!!! tip "Cuidado"
Siempre guarda las contraseñas de la forma más segura posible.
!!! warning "Cuidado"
Consulta con el proveedor de tu correo electrónico, la configuración "exacta" necesaria para conectarse a tu servidor. Algunos proveedores no permiten (o dificultan) la conexión desde fuera de su infraestructura.
<br>
### **send**
Enviar un correo electrónico.
```py
from conf import PASSWORD
SERVIDOR = dict(
server = 'mail.correo.net' ,
port = 405,
ssl = True,
user = 'no-responder@pruebas.mx',
password = PASSWORD,
)
body = "Hola Ingrid\n\n¿Como estas?\n\nSaludos cordiales"
mensaje = dict(
to = 'ingrid@bergman.mx',
subject = 'Te amo...',
body = body,
)
app.email.send(SERVIDOR, mensaje)
```
Algunos servidores requieren activar también `starttls`:
```py
from conf import PASSWORD
SERVIDOR = dict(
server = 'mail.correo.net' ,
port = 405,
ssl = True,
starttls = True,
user = 'no-responder@pruebas.mx',
password = PASSWORD,
)
```
!!! tip "Importante"
Todos los correos se envían siempre en otro hilo de ejecución.
<br>
#### Enviar con copia y copia oculta
Dentro de los datos del mensaje, puede usar los campos `cc` (Con Copia) y `bcc` (Con Copia Oculta), así como separar por comas las direcciones destino para enviar a más de un correo.
```py
to = 'mail1@correo.com,mail2@correo.com,mail3@correo.com'
cc = 'otro@correo.com'
bcc = 'oculto@correo.com'
```
<br>
#### Envíar más de un mensaje
```py
mensaje1 = dict(
to = 'ingrid@correo.net',
subject = 'Te amo...',
body = "Hola Ingrid\n\n¿Como estas?\n\nSaludos cordiales",
)
mensaje2 = dict(
to = 'sophia@correo.net',
subject = 'A ti también...',
body = "Hola Sophia\n\n¿Como estas?\n\nSaludos cordiales",
)
mensajes = (mensaje1, mensaje2)
app.email.send(SERVIDOR, mensajes)
```
```sh
16/08/2022 13:01:49 - DEBUG - Connect to: mail.server.net
16/08/2022 13:01:50 - DEBUG - Email sent...
16/08/2022 13:01:51 - DEBUG - Email sent...
16/08/2022 13:01:51 - DEBUG - Close connection...
```
<br>
#### Adjuntos
Enviar un archivo adjunto.
```py
archivo = '/home/mau/temp.txt'
mensaje = dict(
to = 'ingrid@bergman.mx',
subject = 'Te amo...',
body = "Hola Ingrid\n\n¿Como estas?\n\nSaludos cordiales",
files = archivo,
)
app.email.send(SERVIDOR, mensaje)
```
O varios.
```py
archivos = (
'/home/mau/temp.txt',
'/home/mau/datos.csv',
)
```
<br>
#### Guardar mensajes
Si su cliente de correo usa el formato `mbox` (Thunderbird por ejemplo), puede guardar los correos enviados en una carpeta dentro de la configuración de su cliente de correo.
```py
ruta = '/home/elmau/.thunderbird/7iznrbyw.default/Mail/Local Folders/LibreOffice'
mensaje = dict(
to = 'ingrid@bergman.mx',
subject = 'Te amo...',
body = "Hola Ingrid\n\n¿Como estas?\n\nSaludos cordiales",
path = ruta,
)
app.email.send(SERVIDOR, mensaje)
```

View File

@ -1,103 +1,114 @@
+++
title = "Herramientas"
weight = 3
+++
---
title: Información
---
Recuerda, es necesario importar la librería.
Recuerda, es necesario importar primero la librería.
```python
```py
import easymacro as app
```
#### Información sobre la PC
<br>
### OS
## Información sobre la PC
### **OS**
Obtener el sistema operativo.
```python
```py
app.msgbox(app.OS)
```
<br>
### DESKTOP
### **DESKTOP**
Obtener el tipo de escritorio, solo en GNU/Linux.
```python
```py
app.msgbox(app.DESKTOP)
```
<br>
### PC
### **PC**
Obtener el nombre de la computadora.
```python
```py
app.msgbox(app.PC)
```
<br>
### USER
### **USER**
Obtener el nombre de usuario.
```python
```py
app.msgbox(app.USER)
```
<br>
### IS_WIN
### **IS_WIN**
Saber si estamos en Windows.
```python
```py
app.msgbox(app.IS_WIN)
```
<br>
### IS_MAC
### **IS_MAC**
Saber si estamos en OSX.
Saber si estamos en OS X.
```python
```py
app.msgbox(app.IS_MAC)
```
#### Información sobre LibreOffice
<br>
### NAME
## Información sobre LibreOffice
### **NAME**
Nombre de la aplicación.
```python
```py
app.msgbox(app.NAME)
```
<br>
### VERSION
### **VERSION**
Versión de la aplicación.
```python
```py
app.msgbox(app.VERSION)
```
<br>
### LANG
### **LANG**
Lenguaje de la aplicación.
```python
```py
app.msgbox(app.LANG)
```
<br>
### LANGUAGE
### **LANGUAGE**
Lenguaje con variante.
```python
```py
app.msgbox(app.LANGUAGE)
```

90
doc/docs/tools/macros.md Normal file
View File

@ -0,0 +1,90 @@
Podemos ejecutar cualquier macro disponible en LibreOffice. De forma predeterminada se llaman a las macros en Python localizadas en el perfil de usuario.
### **call**
```py
import easymacro as app
def mostrar_info():
app.msgbox(app.INFO_DEBUG)
return
def main(args=None):
macro = {
'library': 'examples',
'name': 'mostrar_info',
}
app.macro.call(macro)
return
```
<br>
#### Macros compartidas.
Ejecutar una macro compartida en LibreOffice Macros.
```py
macro = {
'library': 'HelloWorld',
'name': 'HelloWorldPython',
'location': 'share',
}
app.macro.call(macro)
```
<br>
#### Macros en Basic
Ejecutar una macro Basic.
```vbscript
Sub mostrar_info()
MsgBox "Mejor usa Python :)"
End Sub
```
```py
macro = {
'language': 'Basic',
'library': 'Standard',
'module': 'Module1',
'name': 'mostrar_info',
}
app.macro.call(macro)
```
<br>
#### Macros en JavaScript
Si ejecutas este ejempplo, asegurate de ejecutarlo con un documento Writer abierto, la macro de ejemplo en JavaScript esta disponible en LibreOffice.
```py
macro = {
'language': 'JavaScript',
'library': 'HelloWorld',
'name': 'helloworld.js',
'location': 'share',
}
app.macro.call(macro)
```
<br>
Cualquier macro se puede ejecutar en otro hilo.
```py
app.macro.call(macro, True)
```
<br>
Más información en: [Scripting Framework URI Specification][1]
<br>
[1]: https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification

View File

@ -0,0 +1,69 @@
## Cuadros de mensaje
### **msgbox**
Mostrar mensaje estandar.
```py
mensaje = 'Maldito Mundo'
titulo = 'Mi Macro'
app.msgbox(mensaje, titulo)
```
<br>
### **warning**
Mostrar mensaje con icono de advertencia.
```py
mensaje = 'Cuidado, esta acción es peligrosa'
titulo = 'Mi Macro'
app.warning(mensaje, titulo)
```
<br>
### **errorbox**
Mostrar mensaje con icono de error.
```py
mensaje = 'ERROR: contacte a soporte'
titulo = 'Mi Macro'
app.errorbox(mensaje, titulo)
```
<br>
### **question**
Hacer una pregunta mostrando el icono de interrogación y mostrando los botones de comando `Si` y `No`. La respuesta siempre es verdadera (`True`) si el usuario selecciona `si` y falsa (`False`) en caso contrario.
```py
mensaje = '¿Es fácil Python?'
titulo = 'Mi Macro'
resultado = app.question(mensaje, titulo)
app.msgbox(resultado)
```
<br>
### **inputbox**
Muestra un mensaje al usuario, permitiendo capturar una respuesta.
```py
mensaje = 'Escribe tu nombre'
nombre = app.inputbox(mensaje)
app.msgbox(nombre)
```
Para ocultar solo en pantalla lo que captura el usuario, como contraseñas.
```py
mensaje = 'Captura la contraseña'
echochar = '*'
contraseña = app.inputbox(mensaje, echochar=echochar)
app.msgbox(contraseña)
```

678
doc/docs/tools/paths.md Normal file
View File

@ -0,0 +1,678 @@
## Trabajar con rutas y archivos.
<br>
### **path**
Obtener información de una ruta.
```py
ruta_archivo = '/home/elmau/mi_archivo.ods'
p = app.paths(ruta_archivo)
app.debug(p.path)
app.debug(p.file_name)
app.debug(p.name)
app.debug(p.ext)
app.debug(p.size)
app.debug(p.url)
```
```
15/08/2022 14:40:08 - DEBUG - /home/elmau
15/08/2022 14:40:08 - DEBUG - mi_archivo.ods
15/08/2022 14:40:08 - DEBUG - mi_archivo
15/08/2022 14:40:08 - DEBUG - ods
15/08/2022 14:40:08 - DEBUG - 7011
15/08/2022 14:40:08 - DEBUG - file:///home/elmau/mi_archivo.ods
```
Obtener la misma información como un tupla.
```py
ruta_archivo = '/home/elmau/mi_archivo.ods'
p = app.paths(ruta_archivo)
app.debug(p.info)
```
```
15/08/2022 14:43:01 - DEBUG - ('/home/elmau', 'mi_archivo.ods', 'mi_archivo', 'ods', 7011, 'file:///home/mau/mi_archivo.ods')
```
O como diccionario.
```py
ruta_archivo = '/home/elmau/mi_archivo.ods'
p = app.paths(ruta_archivo)
app.debug(p.dict)
```
```
15/08/2022 14:43:01 - DEBUG - {'path': '/home/elmau', 'file_name': 'mi_archivo.ods', 'name': 'mi_archivo', 'ext': 'ods', 'size': 7011, 'url': 'file:///home/mau/mi_archivo.ods'}
```
<br>
### **home**
Obtener la carpeta de inicio del usuario.
```py
p = app.paths
app.debug(p.home)
```
<br>
### **documents**
Obtener la carpeta Documentos del usuario.
```py
p = app.paths
app.debug(p.documents)
```
<br>
### **user_profile**
Obtener la ruta del perfil de usuario.
```py
p = app.paths
app.debug(p.user_profile)
```
<br>
### **user_config**
Obtener la ruta de la carpeta `config` en el perfil de usuario.
```py
p = app.paths
app.debug(p.user_config)
```
<br>
### **python**
Obtener la ruta del ejecutable `python`
```py
p = app.paths
app.debug(p.python)
```
<br>
### **to_system**
Pasar una ruta en formato URL al formato del sistema de archivos del SO.
```py
p = app.paths
ruta_url = 'file:///home/elmau/mi_archivo.ods'
ruta = p.to_system(ruta_url)
app.debug(ruta)
```
<br>
### **to_url**
Pasar una ruta del sistema de archivos del SO al formato URL.
```py
p = app.paths
ruta = '/home/mau/mi_archivo.ods'
ruta_url = p.to_url(ruta)
app.debug(ruta_url)
```
<br>
### **config**
Obtener rutas de la configuración de LibreOffice. Por default obtiene la ruta de `Documentos`, para otras ruta mire [Api XPathSettings][1]
```py
p = app.paths
ruta = p.config()
app.debug(ruta)
ruta = p.config('UserConfig')
app.debug(ruta)
```
!!! tip "Atención"
Algunas rutas pueden ser más de una, separados por `;`, en este caso, el resultado es una lista con las rutas.
<br>
### **join**
Concatenar rutas.
```py
p = app.paths
ruta = p.join('/home/mau', 'pruebas', 'archivo.ods')
app.debug(ruta)
```
<br>
### **exists**
Verificar si una ruta existe.
```py
p = app.paths
resultado = p.exists('/home/mau/test/archivo.ods')
app.debug(resultado)
```
<br>
### **exists_app**
Verificar si una aplicación existe.
```py
p = app.paths
resultado = p.exists_app('noexiste')
app.debug(resultado)
resultado = p.exists_app('soffice')
app.debug(resultado)
```
<br>
### **is_dir**
Verificar si la ruta es un directorio.
```py
p = app.paths
resultado = p.is_dir('/home/elmau')
app.debug(resultado)
```
<br>
### **is_file**
Verificar si la ruta es un archivo.
```py
p = app.paths
resultado = p.is_file('/home/elmau/mi_archivo.ods')
app.debug(resultado)
```
<br>
### **temp_file**
Crear un archivo temporal, es borrado automáticamente al cerrarse.
```python
p = app.paths
f = p.temp_file()
f.write(app.INFO_DEBUG)
f.close()
```
Usado en `contexto`, se cierra automáticamente.
```py
with p.temp_file() as f:
app.debug(f.name)
f.write('test')
```
<br>
### **temp_dir**
Crear un directorio temporal, al salir del contexto, es eliminado junto con todo su contenido del sistema de archivos.
```py
p = app.paths
with p.temp_dir() as d:
app.debug(p.exists(d))
app.debug(d)
app.debug(p.exists(d))
```
<br>
### **get**
Permitir al usuario seleccionar archivos, devuelve solo la ruta. De forma predeterminada abre en la carpeta `Documentos`.
```py
p = app.paths
ruta = p.get()
app.debug(ruta)
```
Establecer que abra en otro directorio.
```py
ruta = p.get('/tmp')
app.debug(ruta)
```
Agregar un filtro.
```py
ruta = p.get(filters='ods')
app.debug(ruta)
```
Agregar multiples filtros.
```py
ruta = p.get(filters='xml,txt')
app.debug(ruta)
```
Permitir selecciones multiples.
```py
rutas = p.get(filters='xml,txt', multiple=True)
app.debug(rutas)
```
<br>
### **get_dir**
Permitir al usuario seleccionar un directorio, devuelve solo la ruta. De forma predeterminada abre en la carpeta `Documentos`.
```py
p = app.paths
ruta = p.get_dir()
app.debug(ruta)
```
Establecer que abra en otro directorio.
```py
ruta = p.get_dir('/tmp')
app.debug(ruta)
```
<br>
### **get_for_save**
Permitir seleccionar un directorio y capturar el nombre del archivo, devuelve la ruta completa.
```py
p = app.paths
ruta = p.get_for_save()
app.debug(ruta)
```
Establecer que inicie en otro directorio.
```py
ruta = p.get_for_save('/tmp')
app.debug(ruta)
```
Si se establece un filtro, automáticamente se agrega la extensión.
```python
ruta = p.get_for_save(filters='txt')
app.debug(ruta)
```
!!! tip "Atención"
Si el archivo capturado existe, el usuario verá una advertencia de sobreescritura.
<br>
### **files**
Obtener archivos de una ruta, no recursivamente. De forma predeterminada regresa todos, incluyendo archivos ocultos.
```py
ruta = '/home/elmau'
p = app.paths
archivos = p.files(ruta)
for a in archivos:
app.debug(a)
```
Filtrar por tipo de archivo.
```py
p = app.paths
archivos = p.files(ruta, '*.pdf')
```
Obtener archivos de forma recursiva.
```py
p = app.paths
archivos = p.files(ruta, '**/*.xml')
```
!!! warning "Cuidado:"
Dependiendo de la cantidad de archivo en la ruta origen, este proceso puede ser costoso en tiempo.
<br>
### **walk**
Obtener archivos de forma recursiva.
```py
p = app.paths
ruta = '/home/elmau/Documents'
archivos = p.walk(ruta)
for a in archivos:
app.debug(a)
```
Con filtro.
```py
archivos = p.walk(ruta, 'ods')
```
Varios filtros.
```py
archivos = p.walk(ruta, 'ods|odt')
```
<br>
### **dirs**
Obtener los directorios de una ruta, no recursivamente.
```py
p = app.paths
ruta = '/home/elmau/Documents'
folders = p.dirs(ruta)
for f in folders:
app.debug(f)
```
<br>
### **walk_dirs**
Obtener los directorios de una ruta, recursivamente.
```py
p = app.paths
ruta = '/home/elmau/Documents'
folders = p.walk_dirs(ruta)
for f in folders:
app.debug(f)
```
Obtener información en una lista de tuplas: (`ID_FOLDER`, `ID_PADRE`, `NOMBRE`)
```py
folders = p.walk_dirs(ruta, True)
```
<br>
### **extension**
Obtener la ruta de instalación de una extensión a partir de su ID.
```py
p = app.paths
id_ext = 'net.elmau.zaz.talk'
ruta = p.extension(id_ext)
app.debug(ruta)
```
<br>
### **replace_ext**
Reemplazar extensión de un archivo. El reemplazo es solo en la variable, no en el archivo físico.
```py
p = app.paths
ruta = '/home/elmau/mi_archivo.ods'
ruta_nueva = p.replace_ext(ruta, 'pdf')
app.debug(ruta_nueva)
```
<br>
### **open**
Abrir cualquier archivo con el programa predeterminado del SO.
```py
p = app.paths
ruta = '/home/elmau/archivo.pdf'
p.open(ruta)
ruta = '/home/elmau/index.html'
p.open(ruta)
```
<br>
### **save** y **read**
Guardar y leer datos, el encoding predeterminado es UTF8.
```py
p = app.paths
datos = """¿Quieres saber quién eres? No preguntes. Actúa.
La acción te delineará y definirá.
Thomas Jefferson
"""
ruta = '/home/elmau/temp.txt'
p.save(ruta, datos)
datos = p.read(ruta)
app.msgbox(datos)
```
Cambiar el encoding.
```py
app.paths.save(ruta, datos, 'iso-8859-1')
```
<br>
### **save_bin** y **read_bin**
Guardar y leer datos binarios.
```py
p = app.paths
datos = b'Datos binarios'
ruta = '/home/elmau/temp.bin'
p.save_bin(ruta, datos)
datos = p.read_bin(ruta)
app.msgbox(datos)
```
<br>
### **save_json** y **read_json**
Guardar y leer en formato json.
```py
p = app.paths
ruta = '/home/elmau/datos.json'
datos = {
'tipo': 'calc',
'nombre': 'miarchivo.ods',
}
p.save_json(ruta, datos)
datos = p.read_json(ruta)
app.msgbox(datos)
```
<br>
### **save_csv** y **read_csv**
Exportar e importar datos en formato CSV. Vea la documentación [CSV][2] para los argumentos que puede usar.
```py
p = app.paths
ruta = '/home/elmau/datos.csv'
ahora = app.dates.now
datos = (
(1, 'uno', ahora),
(2, 'dos', ahora),
(3, 'tres', ahora),
)
p.save_csv(ruta, datos)
datos = p.read_csv(ruta)
app.msgbox(datos)
```
<br>
### **kill**
Borra archivos o directorios con todo su contenido. Devuelve verdadero (True) en caso de exito y falso (Falso) en cualquier otro caso.
!!! warning inline end "Cuidado"
Este proceso es destructivo, es buena practica siempre solicitar confirmación al usuario.
```py
p = app.paths
ruta = '/home/elmau/temp.bin'
resultado = p.kill(ruta)
app.msgbox(resultado)
```
<br>
### **copy**
Copiar archivos. Devuelve la ruta completa final destino.
De un archivo origen a una carpeta destino con el mismo nombre.
```py
p = app.paths
ruta_origen = '/home/elmau/temp.txt'
ruta_destino = '/home/elmau/Desktop'
ruta = p.copy(ruta_origen, ruta_destino)
app.debug(ruta)
```
Cambiando el nombre destino.
```py
ruta_origen = '/home/elmau/temp.txt'
ruta_destino = '/home/elmau/Desktop'
nuevo_nombre = 'datos.csv'
ruta = p.copy(ruta_origen, ruta_destino, nuevo_nombre)
app.debug(ruta)
```
<br>
### **zip**
Comprimir un archivo en el mismo directorio, lo comprime y le asigna el mismo nombre con extensión `zip`.
```py
p = app.paths
origen = '/home/elmau/temp.txt'
destino = p.zip(origen)
app.debug(destino)
```
Comprimir varios archivos estableciendo ruta y nombre destino.
```py
archivos = (
'/home/elmau/temp.txt',
'/home/elmau/ids',
'/home/elmau/ids.ods')
destino = p.zip(archivos, '/home/elmau/destino.zip')
app.debug(destino)
```
Comprimir un directorio.
```py
directorio = '/home/elmau/pruebas'
destino = p.zip(directorio, '/home/elmau/pruebas.zip')
app.debug(destino)
```
<br>
### **zip_content**
Devuelve una lista con los nombres de los archivos contenidos en el archivo `zip`.
```py
archivo = '/home/elmau/temp.zip'
contenido = p.zip_content(archivo)
app.debug(contenido)
```
<br>
### **unzip**
Descomprime un archivo `zip` en el mismo directorio.
```py
p = app.paths
archivo = '/home/elmau/temp.zip'
p.unzip(archivo)
```
Descomprime un archivo `zip` en otro directorio.
```py
archivo = '/home/elmau/temp.zip'
destino = '/home/elmau/Desktop'
p.unzip(archivo, destino)
```
[1]: http://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1util_1_1XPathSettings.html
[2]: https://docs.python.org/3.7/library/csv.html

76
doc/docs/tools/request.md Normal file
View File

@ -0,0 +1,76 @@
Gracias a [mureq](https://github.com/slingamn/mureq) una sencilla librería para hacer peticiciones HTTP, similar a [requests](https://requests.readthedocs.io) pero más sencilla y en un solo archivo.
### **get**
Método `get`.
```py
def prueba_get():
url = 'https://api.ipify.org'
respuesta = app.url.get(url)
if respuesta.status_code == 200:
mi_ip = respuesta.body.decode()
app.debug(f'IP: {mi_ip}')
else:
app.debug(respuesta.status_code)
return
```
```sh
16/08/2022 22:14:13 - DEBUG - IP: 199.203.174.159
```
<br>
#### **json**
Respuestas en formato json.
```py
def prueba_get():
url = 'https://api.ipify.org/?format=json'
respuesta = app.url.get(url)
if respuesta.status_code == 200:
datos = respuesta.json()
app.debug(f'IP: {datos["ip"]}')
else:
app.debug(respuesta.status_code)
return
```
<br>
## **post**
Método `post`
```py
def prueba_post():
url = 'https://translate.terraprint.co/translate'
data = dict(
q = 'Hello World',
source = 'en',
target = 'es',
)
respuesta = app.url.post(url, json=data)
if respuesta.status_code != 200:
app.debug(respuesta.status_code)
return
datos = respuesta.json()
app.debug(datos)
return
```
```sh
elmau@oficina ~> soffice --calc
22/04/2023 14:57:50 - DEBUG - {'translatedText': 'Hola Mundo'}
```
<br>

View File

@ -1,18 +1,12 @@
+++
title = "Hilos"
weight = 5
+++
#### Ejecutar macros en otros hilos.
## Ejecutar macros en otros hilos.
Las macros se ejecutan en un hilo que bloquea cualquier otro proceso dentro de la aplicación.
Si ejecutas la siguiente macro `main`, nota que no puedes hacer algo más dentro de LibreOffice durante los 5 segundos que dura el proceso.
```python
```py
import easymacro as app
def hacer_pausa(segundos):
app.sleep(segundos)
app.debug('He terminado')
@ -24,13 +18,15 @@ def main():
return
```
Hasta que aparece el cuadro de mensaje con la palabra `Fin` y lo cierras, el usuario puede seguir usando la aplicación.
Hasta que aparece el cuadro de mensaje con la palabra `Fin` y lo cierras, el usuario puede seguir usando la aplicación. En algunos casos no queremos esto, para ello se usan los hilos de ejecución.
### run_in_thread
<br>
### **run_in_thread**
Ahora ejecutamos la macro en otro hilo, "decorando" cualquier macro con `run_in_thread`
```python
```py
@app.run_in_thread
def hacer_pausa(segundos):
app.sleep(segundos)
@ -45,6 +41,8 @@ def main():
Nota que ahora el mensaje aparece inmediatamente y no tras los 5 segundos.
{{% notice warning %}}
Ponga mucha atención en **no ejecutar macros en otros hilo** que dependen de algo suceptible de ser cambiado o interceptado por el usuario, por ejemplo, la celda activa.
{{% /notice %}}
!!! warning "Cuidado"
Ponga mucha atención en **no ejecutar macros en otros hilos** que dependen de algo suceptible de ser cambiado o interceptado por el usuario, por ejemplo, la celda activa.
<br>

View File

@ -1,16 +1,15 @@
+++
title = "Timer"
weight = 7
+++
El `timer` siempre se ejecuta en otro hilo.
### once
### **once**
Ejecutar macro una sola vez en X segundos.
!!! tip "Atención"
```python
Asegurese siempre de establecer un nombre único para cada timer.
```py
import easymacro as app
@ -18,7 +17,7 @@ NOMBRE = 'reloj'
def mostrar_hora():
app.debug(app.dates.now_time)
app.debug(app.dates.now.time())
return
@ -37,14 +36,16 @@ def main(args=None):
return
```
### cancel
<br>
### **cancel**
Cancelar ejecución, antes del tiempo establecido.
```python
```py
def main(args=None):
iniciar_conteo()
app.sleep(3)
app.sleep(2)
detener_conteo()
return
@ -53,21 +54,23 @@ def detener_conteo():
return
```
```
16/08/2022 21:18:50 - INFO - Event: "reloj", started... execute in 60 seconds
```sh
16/08/2022 21:18:50 - INFO - Event: "reloj", started... execute in 5 seconds
16/08/2022 21:18:55 - INFO - Cancel event: "reloj", ok...
```
### start
<br>
### **start**
Ejecutar macro cada X segundos.
```python
```py
NOMBRE = 'reloj'
def mostrar_hora():
app.debug(app.dates.now_time)
app.debug(app.dates.now.time())
return
@ -80,22 +83,25 @@ def iniciar_reloj():
app.timer.start(NOMBRE, segundos, macro)
return
def main(args=None):
iniciar_reloj()
return
```
### stop
<br>
### **stop**
Detener timer.
```python
```py
def detener_reloj():
app.timer.stop(NOMBRE)
return
```
```
```sh
16/08/2022 21:25:37 - INFO - Timer 'reloj' started, execute macro: 'mostrar_hora'
16/08/2022 21:25:38 - DEBUG - 21:25:38
16/08/2022 21:25:39 - DEBUG - 21:25:39
@ -105,12 +111,10 @@ def detener_reloj():
16/08/2022 21:25:48 - INFO - Timer stopped...
```
<br>
{{% notice tip %}}
Asegurese siempre de establecer un nombre único para cada timer.
{{% /notice %}}
!!! warning "Cuidado"
Asegurese siempre de ejecutar macros que NO bloqueen la interfaz del usuario.
{{% notice warning %}}
Asegurese siempre de ejecutar macros que NO bloqueen la interfaz del usuario.
{{% /notice %}}
<br>

210
doc/docs/tools/utils.md Normal file
View File

@ -0,0 +1,210 @@
### **dict_to_property**
Convertir diccionarios en PropertyValue
```py
datos = {
'Hidden': True,
'Password': 'letmein',
}
propiedades = app.dict_to_property(datos)
app.msgbox(propiedades)
```
<br>
### **data_to_dict**
Convertir `PropertyValue` en diccionarios
```py
datos = app.data_to_dict(propiedades)
app.msgbox(datos)
```
Convertir `tuplas` a diccionario.
```py
tupla_de_tuplas = (
('Hidden', True),
('Password', 'letmein'),
)
datos = app.data_to_dict(tupla_de_tuplas)
app.msgbox(datos)
```
Convertir `listas` a diccionario.
```py
lista_de_listas = [
['Hidden', True],
['Password', 'letmein'],
]
datos = app.data_to_dict(lista_de_listas)
app.msgbox(datos)
```
<br>
### **sleep**
Hacer una pausa de X segundos.
```py
app.sleep(5)
```
<br>
### **render**
Reemplazar variables en cadenas de texto.
```py
plantilla = """Hola $nombre
Te envío este archivo: $archivo
Saludos cordiales
"""
datos = {
'nombre': 'Ingrid Bergman',
'archivo': 'carta_de_amor.odt'
}
resultado = app.render(plantilla, datos)
app.msgbox(resultado)
```
<br>
### **run**
Ejecutar un programa.
```py
nombre_aplicacion = 'gnome-calculator'
app.shell.run(nombre_aplicacion)
```
Ejecutar comandos shell y capturar la salida.
```py
comandos = 'ls -lh ~'
resultado = app.shell.run(comandos, True)
app.debug(resultado)
```
```sh
drwxr-xr-x 4 mau mau 4.0K Aug 15 23:36 Desktop
drwxr-xr-x 6 mau mau 4.0K Jun 9 23:32 Documents
drwxr-xr-x 5 mau mau 4.0K Aug 16 13:09 Downloads
drwxr-xr-x 3 mau mau 4.0K Aug 14 15:19 Pictures
drwxr-xr-x 10 mau mau 4.0K Jun 19 19:36 Projects
drwxr-xr-x 2 mau mau 4.0K May 11 22:36 Templates
drwxr-xr-x 2 mau mau 4.0K Jul 19 13:37 Videos
```
Ejectuar comandos y capturar la salida línea a línea.
```py
comandos = 'ls -lh /home/elmau'
for linea in app.shell.popen(comandos):
app.debug(linea)
```
<br>
### **digest**
Obtener hash. Por default se regresa en hexadecimal.
```py
datos = 'LibreOffice con Python'
digest = app.hash.digest('md5', datos)
app.debug('MD5 = ', digest)
digest = app.hash.digest('sha1', datos)
app.debug('SHA1 = ', digest)
digest = app.hash.digest('sha256', datos)
app.debug('SHA256 = ', digest)
digest = app.hash.digest('sha512', datos)
app.debug('SHA512 = ', digest)
```
```
16/08/2022 18:48:07 - DEBUG - MD5 = 3801759ead20abc3ce0d0095289bdcfd
16/08/2022 18:48:07 - DEBUG - SHA1 = 1df74aaae9658c21074aa5a2d4c2055dcf79f0db
16/08/2022 18:48:07 - DEBUG - SHA256 = 228e90b15b6259307e580677939b1f2f45e9317461e98f603af8fcac0f9a598f
16/08/2022 18:48:07 - DEBUG - SHA512 = 3ef45f79f3bfd2b251d250489c91b631306456405510397fb1a7ee37005d196376b7d6ca86a9895f4eb97eb74813965c24d6564a383f4bdb1360665c8fbb192a
```
Para obtener bytes.
```py
digest = app.hash.digest('md5', datos, False)
app.debug('MD5 = ', digest)
```
```sh
16/08/2022 18:48:07 - DEBUG - MD5 = b'8\x01u\x9e\xad \xab\xc3\xce\r\x00\x95(\x9b\xdc\xfd'
```
<br>
### **config**
Puede guardar datos de configuración de su macro o extensión dentro del perfil de usuario.
```py
nombre = 'mi_extension'
datos = {
'ruta': '/home/mau/pruebas',
'guardar': True,
}
if app.config.set(nombre, datos):
app.debug('Configuración guardada...')
```
Y recuperarlos en cualquier momento.
```py
datos = app.config.get(nombre)
app.debug(datos)
```
!!! tip
No olvide respaldar el perfil de usuario si quiere conservar esta información cuando se reinstala LibreOffice o falla el perfil de usuario.
<br>
### **color**
Puede ver los colores que puede usar en Wikipedia [Colores Web][1]
```py
color_nombre = 'darkblue'
color = app.color(color_nombre)
app.debug(color)
color_rgb = (125, 200, 10)
color = app.color(color_rgb)
app.debug(color)
color_html = '#008080'
color = app.color(color_html)
app.debug(color)
```
<br>
[1]: https://es.wikipedia.org/wiki/Colores_web

View File

@ -1,53 +0,0 @@
<a id="logo" href='{{ (cond (and (ne .Site.Params.landingPageURL nil) (.Site.IsMultiLingual)) .Site.Params.landingPageURL "/") }}'>
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="100.000000pt" height="75.000000pt" viewBox="0 0 200.000000 150.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,149.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1181 1473 c-19 -10 -43 -30 -54 -45 -24 -32 -33 -110 -19 -160 5
-19 7 -40 3 -45 -5 -9 -83 -26 -106 -23 -5 1 -32 3 -60 6 -51 4 -133 28 -240
69 -34 13 -83 26 -110 30 -72 10 -118 21 -228 58 -83 27 -99 30 -107 18 -12
-21 4 -47 50 -77 21 -14 41 -32 44 -40 7 -18 66 -54 88 -54 10 0 44 -20 75
-44 51 -39 131 -76 165 -76 5 0 32 -16 58 -35 26 -19 53 -35 59 -35 12 0 14
-46 4 -133 -7 -61 -47 -112 -97 -120 -19 -3 -53 -18 -76 -33 -46 -31 -240
-268 -310 -381 -30 -48 -53 -74 -70 -78 -29 -8 -190 -169 -190 -190 0 -27 15
-16 87 63 41 45 87 85 110 96 30 13 50 34 84 89 24 39 95 136 157 214 113 143
171 193 220 193 27 0 86 52 100 87 6 16 12 68 15 116 l3 88 -30 16 c-17 9 -47
29 -67 44 -20 16 -47 29 -60 29 -36 1 -106 36 -159 80 -29 25 -58 40 -74 40
-18 0 -40 13 -64 38 -21 20 -51 47 -68 59 -27 21 -24 21 52 -6 45 -16 126 -37
180 -46 55 -10 116 -26 136 -35 21 -10 61 -23 90 -30 29 -7 62 -17 73 -23 18
-9 130 -28 165 -27 8 0 36 3 63 6 38 5 50 11 61 33 8 16 10 36 5 51 -43 145
73 260 167 166 34 -34 34 -34 34 -130 0 -85 -2 -96 -20 -106 -17 -9 -70 -87
-70 -103 0 -4 24 -7 54 -7 38 0 60 -6 79 -20 14 -11 39 -20 56 -20 33 0 151
-41 188 -66 12 -8 46 -23 75 -34 48 -18 184 -100 166 -100 -4 0 -22 6 -40 14
-78 33 -157 49 -217 43 -35 -4 -81 -1 -112 6 -30 7 -81 12 -114 12 l-60 -1
-45 -84 c-49 -93 -42 -85 -404 -435 -198 -192 -250 -234 -347 -288 -23 -13
-29 -21 -21 -29 7 -7 32 2 84 32 58 32 122 89 286 248 117 114 247 239 290
279 63 58 88 89 127 163 l49 92 70 -7 c39 -3 121 -10 181 -14 119 -9 166 -19
232 -46 94 -38 101 15 11 73 -90 58 -314 158 -372 167 -27 4 -60 14 -74 23
-14 9 -43 18 -65 22 l-41 5 38 38 c37 38 38 38 42 135 5 85 3 101 -15 129 -40
64 -111 87 -170 56z"/>
<path d="M1120 210 c0 -109 2 -130 15 -130 13 0 15 21 15 130 0 109 -2 130
-15 130 -13 0 -15 -21 -15 -130z"/>
<path d="M900 200 l0 -120 80 0 c64 0 80 3 80 15 0 12 -14 15 -65 15 l-65 0 0
45 0 45 60 0 c47 0 60 3 60 15 0 12 -13 15 -60 15 l-60 0 0 35 0 35 65 0 c37
0 65 4 65 10 0 6 -33 10 -80 10 l-80 0 0 -120z"/>
<path d="M1320 200 c0 -100 3 -120 15 -120 12 0 15 18 15 102 0 56 3 98 7 94
4 -3 18 -37 33 -74 34 -90 53 -90 89 0 14 36 30 70 34 74 4 4 7 -38 7 -94 0
-84 3 -102 15 -102 13 0 15 20 15 120 l0 120 -27 0 c-26 0 -31 -7 -59 -83
l-31 -82 -29 83 c-27 76 -31 82 -56 82 l-28 0 0 -120z"/>
<path d="M1628 263 c-10 -2 -18 -10 -18 -16 0 -8 16 -11 49 -9 41 3 51 0 60
-16 9 -18 6 -20 -35 -25 -48 -5 -84 -30 -84 -58 0 -54 43 -79 93 -54 20 10 33
12 35 5 2 -5 11 -10 19 -10 13 0 15 13 11 76 -3 65 -7 79 -27 95 -22 18 -63
23 -103 12z m97 -115 c-14 -48 -66 -62 -89 -25 -15 24 15 47 62 47 30 0 33 -2
27 -22z"/>
<path d="M1820 187 c0 -58 4 -77 18 -89 27 -24 48 -27 76 -13 14 8 26 10 26 4
0 -5 7 -9 15 -9 12 0 15 17 15 90 0 73 -3 90 -15 90 -12 0 -15 -14 -15 -64 0
-68 -14 -96 -49 -96 -31 0 -41 22 -41 92 0 54 -3 68 -15 68 -12 0 -15 -15 -15
-73z"/>
</g>
</svg>
</a>

56
doc/mkdocs.yml Normal file
View File

@ -0,0 +1,56 @@
site_name: EasyMacro para LibreOffice
site_url: https://doc.cuates.net/easymacro/
repo_url: https://git.cuates.net/elmau/easymacro/
nav:
- Home: index.md
- Instalación: install.md
- Depurar: debug.md
- Herramientas:
- tools/index.md
- Mensajes: tools/messages.md
- Fechas y tiempo: tools/datetime.md
- Rutas y archivos: tools/paths.md
- Correo electrónico: tools/email.md
- Hilos: tools/threads.md
- Ejecutar macros: tools/macros.md
- Timer: tools/timer.md
- Peticiones HTTP: tools/request.md
- Utilidades: tools/utils.md
- LibreOffice:
- app/index.md
- Accesos directos: app/shortcuts.md
- Menús: app/menus.md
- Documentos:
- docs/index.md
- Propiedades: docs/properties.md
- Métodos: docs/methods.md
theme:
name: material
locale: es
font: false
highlightjs: true
palette:
primary: green
features:
- navigation.path
- content.code.copy
- content.code.select
markdown_extensions:
- admonition
- pymdownx.details
- pymdownx.superfences
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.superfences
#~ extra:
#~ alternate:
#~ - name: Español
#~ link: /
#~ lang: es
#~ - name: English
#~ link: /en/
#~ lang: en

View File

@ -1,59 +0,0 @@
<!DOCTYPE html>
<html lang="en" class="js csstransforms3d">
<head>
<meta charset="utf-8"> <meta name="description" content="">
<link rel="icon" href="/easymacro/images/favicon.png" type="image/png">
<title>404 Page not found</title>
<link href="/easymacro/css/nucleus.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/fontawesome-all.min.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/hybrid.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/featherlight.min.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/perfect-scrollbar.min.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/theme.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/hugo-theme.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/theme-blue.css?1661091037" rel="stylesheet">
<style>
:root #header + #content > #left > #rlblock_left {
display: none !important;
}
p,
li,
ul {
text-align: center
}
ul {
list-style-type: none;
}
</style>
</head>
<body class="" data-url="/">
<section id="body" style="margin-left:0px;">
<div id="overlay"></div>
<div id="chapter">
<div id="body-inner">
<h1>Error</h1>
<p>
</p>
<p>Woops. Looks like this page doesn&#39;t exist ¯\_(ツ)_/¯.</p>
<p></p>
<p><a href='/easymacro'>Go to homepage</a></p>
<p><img src='/images/gopher-404.jpg' style="width:50%" alt="Page not found!"></p>
</div>
</div>
</section>
</body>
</html>

View File

@ -1,482 +0,0 @@
<!DOCTYPE html>
<html lang="en" class="js csstransforms3d">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Hugo 0.101.0" />
<meta name="description" content="">
<link rel="icon" href="/easymacro/images/favicon.png" type="image/png">
<title>Categories :: EasyMacro&#39;s documentation</title>
<link href="/easymacro/css/nucleus.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/fontawesome-all.min.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/hybrid.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/featherlight.min.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/perfect-scrollbar.min.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/auto-complete.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/atom-one-dark-reasonable.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/theme.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/tabs.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/hugo-theme.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/theme-blue.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/custom.css?1661091037" rel="stylesheet">
<script src="/easymacro/js/jquery-3.3.1.min.js?1661091037"></script>
<style>
:root #header + #content > #left > #rlblock_left{
display:none !important;
}
</style>
</head>
<body class="" data-url="/easymacro/categories/">
<nav id="sidebar" class="">
<div id="header-wrapper">
<div id="header">
<a id="logo" href='/en'>
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="100.000000pt" height="75.000000pt" viewBox="0 0 200.000000 150.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,149.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1181 1473 c-19 -10 -43 -30 -54 -45 -24 -32 -33 -110 -19 -160 5
-19 7 -40 3 -45 -5 -9 -83 -26 -106 -23 -5 1 -32 3 -60 6 -51 4 -133 28 -240
69 -34 13 -83 26 -110 30 -72 10 -118 21 -228 58 -83 27 -99 30 -107 18 -12
-21 4 -47 50 -77 21 -14 41 -32 44 -40 7 -18 66 -54 88 -54 10 0 44 -20 75
-44 51 -39 131 -76 165 -76 5 0 32 -16 58 -35 26 -19 53 -35 59 -35 12 0 14
-46 4 -133 -7 -61 -47 -112 -97 -120 -19 -3 -53 -18 -76 -33 -46 -31 -240
-268 -310 -381 -30 -48 -53 -74 -70 -78 -29 -8 -190 -169 -190 -190 0 -27 15
-16 87 63 41 45 87 85 110 96 30 13 50 34 84 89 24 39 95 136 157 214 113 143
171 193 220 193 27 0 86 52 100 87 6 16 12 68 15 116 l3 88 -30 16 c-17 9 -47
29 -67 44 -20 16 -47 29 -60 29 -36 1 -106 36 -159 80 -29 25 -58 40 -74 40
-18 0 -40 13 -64 38 -21 20 -51 47 -68 59 -27 21 -24 21 52 -6 45 -16 126 -37
180 -46 55 -10 116 -26 136 -35 21 -10 61 -23 90 -30 29 -7 62 -17 73 -23 18
-9 130 -28 165 -27 8 0 36 3 63 6 38 5 50 11 61 33 8 16 10 36 5 51 -43 145
73 260 167 166 34 -34 34 -34 34 -130 0 -85 -2 -96 -20 -106 -17 -9 -70 -87
-70 -103 0 -4 24 -7 54 -7 38 0 60 -6 79 -20 14 -11 39 -20 56 -20 33 0 151
-41 188 -66 12 -8 46 -23 75 -34 48 -18 184 -100 166 -100 -4 0 -22 6 -40 14
-78 33 -157 49 -217 43 -35 -4 -81 -1 -112 6 -30 7 -81 12 -114 12 l-60 -1
-45 -84 c-49 -93 -42 -85 -404 -435 -198 -192 -250 -234 -347 -288 -23 -13
-29 -21 -21 -29 7 -7 32 2 84 32 58 32 122 89 286 248 117 114 247 239 290
279 63 58 88 89 127 163 l49 92 70 -7 c39 -3 121 -10 181 -14 119 -9 166 -19
232 -46 94 -38 101 15 11 73 -90 58 -314 158 -372 167 -27 4 -60 14 -74 23
-14 9 -43 18 -65 22 l-41 5 38 38 c37 38 38 38 42 135 5 85 3 101 -15 129 -40
64 -111 87 -170 56z"/>
<path d="M1120 210 c0 -109 2 -130 15 -130 13 0 15 21 15 130 0 109 -2 130
-15 130 -13 0 -15 -21 -15 -130z"/>
<path d="M900 200 l0 -120 80 0 c64 0 80 3 80 15 0 12 -14 15 -65 15 l-65 0 0
45 0 45 60 0 c47 0 60 3 60 15 0 12 -13 15 -60 15 l-60 0 0 35 0 35 65 0 c37
0 65 4 65 10 0 6 -33 10 -80 10 l-80 0 0 -120z"/>
<path d="M1320 200 c0 -100 3 -120 15 -120 12 0 15 18 15 102 0 56 3 98 7 94
4 -3 18 -37 33 -74 34 -90 53 -90 89 0 14 36 30 70 34 74 4 4 7 -38 7 -94 0
-84 3 -102 15 -102 13 0 15 20 15 120 l0 120 -27 0 c-26 0 -31 -7 -59 -83
l-31 -82 -29 83 c-27 76 -31 82 -56 82 l-28 0 0 -120z"/>
<path d="M1628 263 c-10 -2 -18 -10 -18 -16 0 -8 16 -11 49 -9 41 3 51 0 60
-16 9 -18 6 -20 -35 -25 -48 -5 -84 -30 -84 -58 0 -54 43 -79 93 -54 20 10 33
12 35 5 2 -5 11 -10 19 -10 13 0 15 13 11 76 -3 65 -7 79 -27 95 -22 18 -63
23 -103 12z m97 -115 c-14 -48 -66 -62 -89 -25 -15 24 15 47 62 47 30 0 33 -2
27 -22z"/>
<path d="M1820 187 c0 -58 4 -77 18 -89 27 -24 48 -27 76 -13 14 8 26 10 26 4
0 -5 7 -9 15 -9 12 0 15 17 15 90 0 73 -3 90 -15 90 -12 0 -15 -14 -15 -64 0
-68 -14 -96 -49 -96 -31 0 -41 22 -41 92 0 54 -3 68 -15 68 -12 0 -15 -15 -15
-73z"/>
</g>
</svg>
</a>
</div>
<div class="searchbox">
<label for="search-by"><i class="fas fa-search"></i></label>
<input data-search-input id="search-by" type="search" placeholder="Search...">
<span data-search-clear=""><i class="fas fa-times"></i></span>
</div>
<script type="text/javascript" src="/easymacro/js/lunr.min.js?1661091037"></script>
<script type="text/javascript" src="/easymacro/js/auto-complete.js?1661091037"></script>
<script type="text/javascript">
var baseurl = "https:\/\/doc.cuates.net\/easymacro";
</script>
<script type="text/javascript" src="/easymacro/js/search.js?1661091037"></script>
</div>
<section id="homelinks">
<ul>
<li>
<a class="padding" href='/en'><i class='fas fa-home'></i> Home</a>
</li>
</ul>
</section>
<div class="highlightable">
<ul class="topics">
<li data-nav-id="/easymacro/installation/" title="Installation" class="dd-item
">
<a href="/easymacro/installation/">
Installation
</a>
</li>
<li data-nav-id="/easymacro/tools_debug/" title="Tools for debug" class="dd-item
">
<a href="/easymacro/tools_debug/">
Tools for debug
</a>
</li>
</ul>
<section id="shortcuts">
<h3>More</h3>
<ul>
<li>
<a class="padding" href="https://git.cuates.net/elmau/easymacro"><i class='fab fa-gitlab'></i> Git Repo</a>
</li>
</ul>
</section>
<section id="prefooter">
<hr/>
<ul>
<li>
<a class="padding">
<i class="fas fa-language fa-fw"></i>
<div class="select-style">
<select id="select-language" onchange="location = this.value;">
<option id="en" value="https://doc.cuates.net/easymacro/categories/" selected>English</option>
<option id="es" value="https://doc.cuates.net/easymacro/es/categories/">Español</option>
<option id="pt" value="https://doc.cuates.net/easymacro/pt/categories/">Português</option>
<option id="fr" value="https://doc.cuates.net/easymacro/fr/categories/">Français</option>
</select>
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="255px" height="255px" viewBox="0 0 255 255" style="enable-background:new 0 0 255 255;" xml:space="preserve">
<g>
<g id="arrow-drop-down">
<polygon points="0,63.75 127.5,191.25 255,63.75 " />
</g>
</g>
</svg>
</div>
</a>
</li>
</ul>
</section>
<section id="footer">
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fas fa-heart"></i></a> from <a href="https://getgrav.org">Grav</a> and <a href="https://gohugo.io/">Hugo</a></p>
</section>
</div>
</nav>
<section id="body">
<div id="overlay"></div>
<div class="padding highlightable">
<div>
<div id="top-bar">
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
<span id="sidebar-toggle-span">
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
<i class="fas fa-bars"></i>
</a>
</span>
<span id="toc-menu"><i class="fas fa-list-alt"></i></span>
<span class="links">
<a href='/easymacro/'></a> > Categories
</span>
</div>
<div class="progress">
<div class="wrapper">
</div>
</div>
</div>
</div>
<div id="head-tags">
</div>
<div id="body-inner">
<h1>
category ::
Categories
</h1>
<ul>
</ul>
<footer class=" footline" >
</footer>
</div>
</div>
<div id="navigation">
<a class="nav nav-next" href="/easymacro/installation/" title="Installation" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
</div>
</section>
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
</div>
<script src="/easymacro/js/clipboard.min.js?1661091037"></script>
<script src="/easymacro/js/perfect-scrollbar.min.js?1661091037"></script>
<script src="/easymacro/js/perfect-scrollbar.jquery.min.js?1661091037"></script>
<script src="/easymacro/js/jquery.sticky.js?1661091037"></script>
<script src="/easymacro/js/featherlight.min.js?1661091037"></script>
<script src="/easymacro/js/highlight.pack.js?1661091037"></script>
<script>hljs.initHighlightingOnLoad();</script>
<script src="/easymacro/js/modernizr.custom-3.6.0.js?1661091037"></script>
<script src="/easymacro/js/learn.js?1661091037"></script>
<script src="/easymacro/js/hugo-learn.js?1661091037"></script>
<script src="/easymacro/mermaid/mermaid.js?1661091037"></script>
<script>
mermaid.initialize({ startOnLoad: true });
</script>
</body>
</html>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Categories on EasyMacro&#39;s documentation</title>
<link>https://doc.cuates.net/easymacro/categories/</link>
<description>Recent content in Categories on EasyMacro&#39;s documentation</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language><atom:link href="https://doc.cuates.net/easymacro/categories/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@ -1,77 +0,0 @@
/*
Atom One Dark With support for ReasonML by Gidi Morris, based off work by Daniel Gamage
Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
line-height: 1.3em;
color: #abb2bf;
background: #282c34;
border-radius: 5px;
}
.hljs-keyword, .hljs-operator {
color: #F92672;
}
.hljs-pattern-match {
color: #F92672;
}
.hljs-pattern-match .hljs-constructor {
color: #61aeee;
}
.hljs-function {
color: #61aeee;
}
.hljs-function .hljs-params {
color: #A6E22E;
}
.hljs-function .hljs-params .hljs-typing {
color: #FD971F;
}
.hljs-module-access .hljs-module {
color: #7e57c2;
}
.hljs-constructor {
color: #e2b93d;
}
.hljs-constructor .hljs-string {
color: #9CCC65;
}
.hljs-comment, .hljs-quote {
color: #b18eb1;
font-style: italic;
}
.hljs-doctag, .hljs-formula {
color: #c678dd;
}
.hljs-section, .hljs-name, .hljs-selector-tag, .hljs-deletion, .hljs-subst {
color: #e06c75;
}
.hljs-literal {
color: #56b6c2;
}
.hljs-string, .hljs-regexp, .hljs-addition, .hljs-attribute, .hljs-meta-string {
color: #98c379;
}
.hljs-built_in, .hljs-class .hljs-title {
color: #e6c07b;
}
.hljs-attr, .hljs-variable, .hljs-template-variable, .hljs-type, .hljs-selector-class, .hljs-selector-attr, .hljs-selector-pseudo, .hljs-number {
color: #d19a66;
}
.hljs-symbol, .hljs-bullet, .hljs-link, .hljs-meta, .hljs-selector-id, .hljs-title {
color: #61aeee;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}
.hljs-link {
text-decoration: underline;
}

View File

@ -1,47 +0,0 @@
.autocomplete-suggestions {
text-align: left;
cursor: default;
border: 1px solid #ccc;
border-top: 0;
background: #fff;
box-shadow: -1px 1px 3px rgba(0,0,0,.1);
/* core styles should not be changed */
position: absolute;
display: none;
z-index: 9999;
max-height: 254px;
overflow: hidden;
overflow-y: auto;
box-sizing: border-box;
}
.autocomplete-suggestion {
position: relative;
cursor: pointer;
padding: 7px;
line-height: 23px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #333;
}
.autocomplete-suggestion b {
font-weight: normal;
color: #1f8dd6;
}
.autocomplete-suggestion.selected {
background: #333;
color: #fff;
}
.autocomplete-suggestion:hover {
background: #444;
color: #fff;
}
.autocomplete-suggestion > .context {
font-size: 12px;
}

View File

@ -1 +0,0 @@

View File

@ -1,8 +0,0 @@
/**
* Featherlight - ultra slim jQuery lightbox
* Version 1.7.13 - http://noelboss.github.io/featherlight/
*
* Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
* MIT Licensed.
**/
html.with-featherlight{overflow:hidden}.featherlight{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:2147483647;text-align:center;white-space:nowrap;cursor:pointer;background:#333;background:rgba(0,0,0,0)}.featherlight:last-of-type{background:rgba(0,0,0,.8)}.featherlight:before{content:'';display:inline-block;height:100%;vertical-align:middle}.featherlight .featherlight-content{position:relative;text-align:left;vertical-align:middle;display:inline-block;overflow:auto;padding:25px 25px 0;border-bottom:25px solid transparent;margin-left:5%;margin-right:5%;max-height:95%;background:#fff;cursor:auto;white-space:normal}.featherlight .featherlight-inner{display:block}.featherlight link.featherlight-inner,.featherlight script.featherlight-inner,.featherlight style.featherlight-inner{display:none}.featherlight .featherlight-close-icon{position:absolute;z-index:9999;top:0;right:0;line-height:25px;width:25px;cursor:pointer;text-align:center;font-family:Arial,sans-serif;background:#fff;background:rgba(255,255,255,.3);color:#000;border:0;padding:0}.featherlight .featherlight-close-icon::-moz-focus-inner{border:0;padding:0}.featherlight .featherlight-image{width:100%}.featherlight-iframe .featherlight-content{border-bottom:0;padding:0;-webkit-overflow-scrolling:touch}.featherlight iframe{border:0}.featherlight *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@media only screen and (max-width:1024px){.featherlight .featherlight-content{margin-left:0;margin-right:0;max-height:98%;padding:10px 10px 0;border-bottom:10px solid transparent}}@media print{html.with-featherlight>*>:not(.featherlight){display:none}}

File diff suppressed because one or more lines are too long

View File

@ -1,241 +0,0 @@
/* Insert here special css for hugo theme, on top of any other imported css */
/* Table of contents */
.progress ul {
list-style: none;
margin: 0;
padding: 0 15px;
}
#TableOfContents {
font-size: 13px !important;
max-height: 85vh;
overflow: auto;
padding: 15px 5px !important;
}
#TableOfContents > ul > li > a {
font-weight: bold;
}
body {
font-size: 16px !important;
color: #323232 !important;
}
#body a.highlight, #body a.highlight:hover, #body a.highlight:focus {
text-decoration: none;
outline: none;
outline: 0;
}
#body a.highlight {
line-height: 1.1;
display: inline-block;
}
#body a.highlight:after {
display: block;
content: "";
height: 1px;
width: 0%;
background-color: #0082a7; /*#CE3B2F*/
-webkit-transition: width 0.5s ease;
-moz-transition: width 0.5s ease;
-ms-transition: width 0.5s ease;
transition: width 0.5s ease;
}
#body a.highlight:hover:after, #body a.highlight:focus:after {
width: 100%;
}
.progress {
position:absolute;
background-color: rgba(246, 246, 246, 0.97);
width: auto;
border: thin solid #ECECEC;
display:none;
z-index:200;
}
#toc-menu {
border-right: thin solid #DAD8D8 !important;
padding-right: 1rem !important;
margin-right: 0.5rem !important;
}
#sidebar-toggle-span {
border-right: thin solid #DAD8D8 !important;
padding-right: 0.5rem !important;
margin-right: 1rem !important;
}
.btn {
display: inline-block !important;
padding: 6px 12px !important;
margin-bottom: 0 !important;
font-size: 14px !important;
font-weight: normal !important;
line-height: 1.42857143 !important;
text-align: center !important;
white-space: nowrap !important;
vertical-align: middle !important;
-ms-touch-action: manipulation !important;
touch-action: manipulation !important;
cursor: pointer !important;
-webkit-user-select: none !important;
-moz-user-select: none !important;
-ms-user-select: none !important;
user-select: none !important;
background-image: none !important;
border: 1px solid transparent !important;
border-radius: 4px !important;
-webkit-transition: all 0.15s !important;
-moz-transition: all 0.15s !important;
transition: all 0.15s !important;
}
.btn:focus {
/*outline: thin dotted;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;*/
outline: none !important;
}
.btn:hover,
.btn:focus {
color: #2b2b2b !important;
text-decoration: none !important;
}
.btn-default {
color: #333 !important;
background-color: #fff !important;
border-color: #ccc !important;
}
.btn-default:hover,
.btn-default:focus,
.btn-default:active {
color: #fff !important;
background-color: #9e9e9e !important;
border-color: #9e9e9e !important;
}
.btn-default:active {
background-image: none !important;
}
/* anchors */
.anchor {
color: #00bdf3;
font-size: 0.5em;
cursor:pointer;
visibility:hidden;
margin-left: 0.5em;
position: absolute;
margin-top:0.1em;
}
h2:hover .anchor, h3:hover .anchor, h4:hover .anchor, h5:hover .anchor, h6:hover .anchor {
visibility:visible;
}
/* Redfines headers style */
h2, h3, h4, h5, h6 {
font-weight: 400;
line-height: 1.1;
}
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
font-weight: inherit;
}
h2 {
font-size: 2.5rem;
line-height: 110% !important;
margin: 2.5rem 0 1.5rem 0;
}
h3 {
font-size: 2rem;
line-height: 110% !important;
margin: 2rem 0 1rem 0;
}
h4 {
font-size: 1.5rem;
line-height: 110% !important;
margin: 1.5rem 0 0.75rem 0;
}
h5 {
font-size: 1rem;
line-height: 110% !important;
margin: 1rem 0 0.2rem 0;
}
h6 {
font-size: 0.5rem;
line-height: 110% !important;
margin: 0.5rem 0 0.2rem 0;
}
p {
margin: 1rem 0;
}
figcaption h4 {
font-weight: 300 !important;
opacity: .85;
font-size: 1em;
text-align: center;
margin-top: -1.5em;
}
.select-style {
border: 0;
width: 150px;
border-radius: 0px;
overflow: hidden;
display: inline-flex;
}
.select-style svg {
fill: #ccc;
width: 14px;
height: 14px;
pointer-events: none;
margin: auto;
}
.select-style svg:hover {
fill: #e6e6e6;
}
.select-style select {
padding: 0;
width: 130%;
border: none;
box-shadow: none;
background: transparent;
background-image: none;
-webkit-appearance: none;
margin: auto;
margin-left: 0px;
margin-right: -20px;
}
.select-style select:focus {
outline: none;
}
.select-style :hover {
cursor: pointer;
}
@media only all and (max-width: 47.938em) {
#breadcrumbs .links, #top-github-link-text {
display: none;
}
}
.is-sticky #top-bar {
box-shadow: -1px 2px 5px 1px rgba(0, 0, 0, 0.1);
}

View File

@ -1,102 +0,0 @@
/*
vim-hybrid theme by w0ng (https://github.com/w0ng/vim-hybrid)
*/
/*background color*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
background: #1d1f21;
}
/*selection color*/
.hljs::selection,
.hljs span::selection {
background: #373b41;
}
.hljs::-moz-selection,
.hljs span::-moz-selection {
background: #373b41;
}
/*foreground color*/
.hljs {
color: #c5c8c6;
}
/*color: fg_yellow*/
.hljs-title,
.hljs-name {
color: #f0c674;
}
/*color: fg_comment*/
.hljs-comment,
.hljs-meta,
.hljs-meta .hljs-keyword {
color: #707880;
}
/*color: fg_red*/
.hljs-number,
.hljs-symbol,
.hljs-literal,
.hljs-deletion,
.hljs-link {
color: #cc6666
}
/*color: fg_green*/
.hljs-string,
.hljs-doctag,
.hljs-addition,
.hljs-regexp,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #b5bd68;
}
/*color: fg_purple*/
.hljs-attribute,
.hljs-code,
.hljs-selector-id {
color: #b294bb;
}
/*color: fg_blue*/
.hljs-keyword,
.hljs-selector-tag,
.hljs-bullet,
.hljs-tag {
color: #81a2be;
}
/*color: fg_aqua*/
.hljs-subst,
.hljs-variable,
.hljs-template-tag,
.hljs-template-variable {
color: #8abeb7;
}
/*color: fg_orange*/
.hljs-type,
.hljs-built_in,
.hljs-builtin-name,
.hljs-quote,
.hljs-section,
.hljs-selector-class {
color: #de935f;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

View File

@ -1,615 +0,0 @@
*, *::before, *::after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
@-webkit-viewport {
width: device-width; }
@-moz-viewport {
width: device-width; }
@-ms-viewport {
width: device-width; }
@-o-viewport {
width: device-width; }
@viewport {
width: device-width; }
html {
font-size: 100%;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%; }
body {
margin: 0; }
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section,
summary {
display: block; }
audio,
canvas,
progress,
video {
display: inline-block;
vertical-align: baseline; }
audio:not([controls]) {
display: none;
height: 0; }
[hidden],
template {
display: none; }
a {
background: transparent;
text-decoration: none; }
a:active,
a:hover {
outline: 0; }
abbr[title] {
border-bottom: 1px dotted; }
b,
strong {
font-weight: bold; }
dfn {
font-style: italic; }
mark {
background: #FFFF27;
color: #333; }
sub,
sup {
font-size: 0.8rem;
line-height: 0;
position: relative;
vertical-align: baseline; }
sup {
top: -0.5em; }
sub {
bottom: -0.25em; }
img {
border: 0;
max-width: 100%; }
svg:not(:root) {
overflow: hidden; }
figure {
margin: 1em 40px; }
hr {
height: 0; }
pre {
overflow: auto; }
button,
input,
optgroup,
select,
textarea {
color: inherit;
font: inherit;
margin: 0; }
button {
overflow: visible; }
button,
select {
text-transform: none; }
button,
html input[type="button"],
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button;
cursor: pointer; }
button[disabled],
html input[disabled] {
cursor: default; }
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0; }
input {
line-height: normal; }
input[type="checkbox"],
input[type="radio"] {
padding: 0; }
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto; }
input[type="search"] {
-webkit-appearance: textfield; }
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none; }
legend {
border: 0;
padding: 0; }
textarea {
overflow: auto; }
optgroup {
font-weight: bold; }
table {
border-collapse: collapse;
border-spacing: 0;
table-layout: fixed;
width: 100%; }
tr, td, th {
vertical-align: middle; }
th, td {
padding: 0.425rem 0; }
th {
text-align: left; }
.container {
width: 75em;
margin: 0 auto;
padding: 0; }
@media only all and (min-width: 60em) and (max-width: 74.938em) {
.container {
width: 60em; } }
@media only all and (min-width: 48em) and (max-width: 59.938em) {
.container {
width: 48em; } }
@media only all and (min-width: 30.063em) and (max-width: 47.938em) {
.container {
width: 30em; } }
@media only all and (max-width: 30em) {
.container {
width: 100%; } }
.grid {
display: -webkit-box;
display: -moz-box;
display: box;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-flow: row;
-moz-flex-flow: row;
flex-flow: row;
list-style: none;
margin: 0;
padding: 0; }
@media only all and (max-width: 47.938em) {
.grid {
-webkit-flex-flow: row wrap;
-moz-flex-flow: row wrap;
flex-flow: row wrap; } }
.block {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
-webkit-flex: 1;
-moz-flex: 1;
-ms-flex: 1;
flex: 1;
min-width: 0;
min-height: 0; }
@media only all and (max-width: 47.938em) {
.block {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 100%;
-moz-flex: 0 100%;
-ms-flex: 0 100%;
flex: 0 100%; } }
.content {
margin: 0.625rem;
padding: 0.938rem; }
@media only all and (max-width: 47.938em) {
body [class*="size-"] {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 100%;
-moz-flex: 0 100%;
-ms-flex: 0 100%;
flex: 0 100%; } }
.size-1-2 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 50%;
-moz-flex: 0 50%;
-ms-flex: 0 50%;
flex: 0 50%; }
.size-1-3 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 33.33333%;
-moz-flex: 0 33.33333%;
-ms-flex: 0 33.33333%;
flex: 0 33.33333%; }
.size-1-4 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 25%;
-moz-flex: 0 25%;
-ms-flex: 0 25%;
flex: 0 25%; }
.size-1-5 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 20%;
-moz-flex: 0 20%;
-ms-flex: 0 20%;
flex: 0 20%; }
.size-1-6 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 16.66667%;
-moz-flex: 0 16.66667%;
-ms-flex: 0 16.66667%;
flex: 0 16.66667%; }
.size-1-7 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 14.28571%;
-moz-flex: 0 14.28571%;
-ms-flex: 0 14.28571%;
flex: 0 14.28571%; }
.size-1-8 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 12.5%;
-moz-flex: 0 12.5%;
-ms-flex: 0 12.5%;
flex: 0 12.5%; }
.size-1-9 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 11.11111%;
-moz-flex: 0 11.11111%;
-ms-flex: 0 11.11111%;
flex: 0 11.11111%; }
.size-1-10 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 10%;
-moz-flex: 0 10%;
-ms-flex: 0 10%;
flex: 0 10%; }
.size-1-11 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 9.09091%;
-moz-flex: 0 9.09091%;
-ms-flex: 0 9.09091%;
flex: 0 9.09091%; }
.size-1-12 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 8.33333%;
-moz-flex: 0 8.33333%;
-ms-flex: 0 8.33333%;
flex: 0 8.33333%; }
@media only all and (min-width: 48em) and (max-width: 59.938em) {
.size-tablet-1-2 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 50%;
-moz-flex: 0 50%;
-ms-flex: 0 50%;
flex: 0 50%; }
.size-tablet-1-3 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 33.33333%;
-moz-flex: 0 33.33333%;
-ms-flex: 0 33.33333%;
flex: 0 33.33333%; }
.size-tablet-1-4 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 25%;
-moz-flex: 0 25%;
-ms-flex: 0 25%;
flex: 0 25%; }
.size-tablet-1-5 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 20%;
-moz-flex: 0 20%;
-ms-flex: 0 20%;
flex: 0 20%; }
.size-tablet-1-6 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 16.66667%;
-moz-flex: 0 16.66667%;
-ms-flex: 0 16.66667%;
flex: 0 16.66667%; }
.size-tablet-1-7 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 14.28571%;
-moz-flex: 0 14.28571%;
-ms-flex: 0 14.28571%;
flex: 0 14.28571%; }
.size-tablet-1-8 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 12.5%;
-moz-flex: 0 12.5%;
-ms-flex: 0 12.5%;
flex: 0 12.5%; }
.size-tablet-1-9 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 11.11111%;
-moz-flex: 0 11.11111%;
-ms-flex: 0 11.11111%;
flex: 0 11.11111%; }
.size-tablet-1-10 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 10%;
-moz-flex: 0 10%;
-ms-flex: 0 10%;
flex: 0 10%; }
.size-tablet-1-11 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 9.09091%;
-moz-flex: 0 9.09091%;
-ms-flex: 0 9.09091%;
flex: 0 9.09091%; }
.size-tablet-1-12 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
-webkit-flex: 0 8.33333%;
-moz-flex: 0 8.33333%;
-ms-flex: 0 8.33333%;
flex: 0 8.33333%; } }
@media only all and (max-width: 47.938em) {
@supports not (flex-wrap: wrap) {
.grid {
display: block;
-webkit-box-lines: inherit;
-moz-box-lines: inherit;
box-lines: inherit;
-webkit-flex-wrap: inherit;
-moz-flex-wrap: inherit;
-ms-flex-wrap: inherit;
flex-wrap: inherit; }
.block {
display: block;
-webkit-box-flex: inherit;
-moz-box-flex: inherit;
box-flex: inherit;
-webkit-flex: inherit;
-moz-flex: inherit;
-ms-flex: inherit;
flex: inherit; } } }
.first-block {
-webkit-box-ordinal-group: 0;
-webkit-order: -1;
-ms-flex-order: -1;
order: -1; }
.last-block {
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
-ms-flex-order: 1;
order: 1; }
.fixed-blocks {
-webkit-flex-flow: row wrap;
-moz-flex-flow: row wrap;
flex-flow: row wrap; }
.fixed-blocks .block {
-webkit-box-flex: inherit;
-moz-box-flex: inherit;
box-flex: inherit;
-webkit-flex: inherit;
-moz-flex: inherit;
-ms-flex: inherit;
flex: inherit;
width: 25%; }
@media only all and (min-width: 60em) and (max-width: 74.938em) {
.fixed-blocks .block {
width: 33.33333%; } }
@media only all and (min-width: 48em) and (max-width: 59.938em) {
.fixed-blocks .block {
width: 50%; } }
@media only all and (max-width: 47.938em) {
.fixed-blocks .block {
width: 100%; } }
body {
font-size: 1.05rem;
line-height: 1.7; }
h1, h2, h3, h4, h5, h6 {
margin: 0.85rem 0 1.7rem 0;
text-rendering: optimizeLegibility; }
h1 {
font-size: 3.25rem; }
h2 {
font-size: 2.55rem; }
h3 {
font-size: 2.15rem; }
h4 {
font-size: 1.8rem; }
h5 {
font-size: 1.4rem; }
h6 {
font-size: 0.9rem; }
p {
margin: 1.7rem 0; }
ul, ol {
margin-top: 1.7rem;
margin-bottom: 1.7rem; }
ul ul, ul ol, ol ul, ol ol {
margin-top: 0;
margin-bottom: 0; }
blockquote {
margin: 1.7rem 0;
padding-left: 0.85rem; }
cite {
display: block;
font-size: 0.925rem; }
cite:before {
content: "\2014 \0020"; }
pre {
margin: 1.7rem 0;
padding: 0.938rem; }
code {
vertical-align: bottom; }
small {
font-size: 0.925rem; }
hr {
border-left: none;
border-right: none;
border-top: none;
margin: 1.7rem 0; }
fieldset {
border: 0;
padding: 0.938rem;
margin: 0 0 1.7rem 0; }
input,
label,
select {
display: block; }
label {
margin-bottom: 0.425rem; }
label.required:after {
content: "*"; }
label abbr {
display: none; }
textarea, input[type="email"], input[type="number"], input[type="password"], input[type="search"], input[type="tel"], input[type="text"], input[type="url"], input[type="color"], input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="month"], input[type="time"], input[type="week"], select[multiple=multiple] {
-webkit-transition: border-color;
-moz-transition: border-color;
transition: border-color;
border-radius: 0.1875rem;
margin-bottom: 0.85rem;
padding: 0.425rem 0.425rem;
width: 100%; }
textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus {
outline: none; }
textarea {
resize: vertical; }
input[type="checkbox"], input[type="radio"] {
display: inline;
margin-right: 0.425rem; }
input[type="file"] {
width: 100%; }
select {
width: auto;
max-width: 100%;
margin-bottom: 1.7rem; }
button,
input[type="submit"] {
cursor: pointer;
user-select: none;
vertical-align: middle;
white-space: nowrap;
border: inherit; }

View File

@ -1,2 +0,0 @@
/* perfect-scrollbar v0.6.13 */
.ps-container{-ms-touch-action:auto;touch-action:auto;overflow:hidden !important;-ms-overflow-style:none}@supports (-ms-overflow-style: none){.ps-container{overflow:auto !important}}@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none){.ps-container{overflow:auto !important}}.ps-container.ps-active-x>.ps-scrollbar-x-rail,.ps-container.ps-active-y>.ps-scrollbar-y-rail{display:block;background-color:transparent}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:.9}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999;height:11px}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:.9}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999;width:11px}.ps-container>.ps-scrollbar-x-rail{display:none;position:absolute;opacity:0;-webkit-transition:background-color .2s linear, opacity .2s linear;-o-transition:background-color .2s linear, opacity .2s linear;-moz-transition:background-color .2s linear, opacity .2s linear;transition:background-color .2s linear, opacity .2s linear;bottom:0px;height:15px}.ps-container>.ps-scrollbar-x-rail>.ps-scrollbar-x{position:absolute;background-color:#aaa;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;-o-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;-moz-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;bottom:2px;height:6px}.ps-container>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x,.ps-container>.ps-scrollbar-x-rail:active>.ps-scrollbar-x{height:11px}.ps-container>.ps-scrollbar-y-rail{display:none;position:absolute;opacity:0;-webkit-transition:background-color .2s linear, opacity .2s linear;-o-transition:background-color .2s linear, opacity .2s linear;-moz-transition:background-color .2s linear, opacity .2s linear;transition:background-color .2s linear, opacity .2s linear;right:0;width:15px}.ps-container>.ps-scrollbar-y-rail>.ps-scrollbar-y{position:absolute;background-color:#aaa;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;-o-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;-moz-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;right:2px;width:6px}.ps-container>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y,.ps-container>.ps-scrollbar-y-rail:active>.ps-scrollbar-y{width:11px}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:.9}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999;height:11px}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:.9}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999;width:11px}.ps-container:hover>.ps-scrollbar-x-rail,.ps-container:hover>.ps-scrollbar-y-rail{opacity:.6}.ps-container:hover>.ps-scrollbar-x-rail:hover{background-color:#eee;opacity:.9}.ps-container:hover>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x{background-color:#999}.ps-container:hover>.ps-scrollbar-y-rail:hover{background-color:#eee;opacity:.9}.ps-container:hover>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y{background-color:#999}

View File

@ -1,43 +0,0 @@
#body .tab-nav-button {
border-width: 1px 1px 1px 1px !important;
border-color: #ccc !important;
border-radius: 4px 4px 0 0 !important;
background-color: #ddd !important;
float: left;
display: block;
position: relative;
margin-left: 4px;
bottom: -1px;
}
#body .tab-nav-button:first-child {
margin-left: 0px;
}
#body .tab-nav-button.active {
background-color: #fff !important;
border-bottom-color: #fff !important;
}
#body .tab-panel {
margin-top: 32px;
margin-bottom: 32px;
}
#body .tab-content {
display: block;
clear: both;
padding: 8px;
border-width: 1px;
border-style: solid;
border-color: #ccc;
}
#body .tab-content .tab-item{
display: none;
}
#body .tab-content .tab-item.active{
display: block;
}
#body .tab-item pre{
margin-bottom: 0;
margin-top: 0;
}

View File

@ -1,49 +0,0 @@
/* Tags */
#head-tags{
margin-left:1em;
margin-top:1em;
}
#body .tags a.tag-link {
display: inline-block;
line-height: 2em;
font-size: 0.8em;
position: relative;
margin: 0 16px 8px 0;
padding: 0 10px 0 12px;
background: #8451a1;
-webkit-border-bottom-right-radius: 3px;
border-bottom-right-radius: 3px;
-webkit-border-top-right-radius: 3px;
border-top-right-radius: 3px;
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.2);
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
color: #fff;
}
#body .tags a.tag-link:before {
content: "";
position: absolute;
top:0;
left: -1em;
width: 0;
height: 0;
border-color: transparent #8451a1 transparent transparent;
border-style: solid;
border-width: 1em 1em 1em 0;
}
#body .tags a.tag-link:after {
content: "";
position: absolute;
top: 10px;
left: 1px;
width: 5px;
height: 5px;
-webkit-border-radius: 50%;
border-radius: 100%;
background: #fff;
}

View File

@ -1,128 +0,0 @@
:root{
--MAIN-TEXT-color:#323232; /* Color of text by default */
--MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */
--MAIN-LINK-color:#1C90F3; /* Color of links */
--MAIN-LINK-HOVER-color:#167ad0; /* Color of hovered links */
--MAIN-ANCHOR-color: #1C90F3; /* color of anchors on titles */
--MENU-HOME-LINK-color: #323232; /* Color of the home button text */
--MENU-HOME-LINK-HOVER-color: #5e5e5e; /* Color of the hovered home button text */
--MENU-HEADER-BG-color:#1C90F3; /* Background color of menu header */
--MENU-HEADER-BORDER-color:#33a1ff; /*Color of menu header border */
--MENU-SEARCH-BG-color:#167ad0; /* Search field background color (by default borders + icons) */
--MENU-SEARCH-BOX-color: #33a1ff; /* Override search field border color */
--MENU-SEARCH-BOX-ICONS-color: #a1d2fd; /* Override search field icons color */
--MENU-SECTIONS-ACTIVE-BG-color:#20272b; /* Background color of the active section and its childs */
--MENU-SECTIONS-BG-color:#252c31; /* Background color of other sections */
--MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */
--MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */
--MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */
--MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */
--MENU-VISITED-color: #33a1ff; /* Color of 'page visited' icons in menu */
--MENU-SECTION-HR-color: #20272b; /* Color of <hr> separator in menu */
}
body {
color: var(--MAIN-TEXT-color) !important;
}
textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus {
border-color: none;
box-shadow: none;
}
h2, h3, h4, h5 {
color: var(--MAIN-TITLES-TEXT-color) !important;
}
a {
color: var(--MAIN-LINK-color);
}
.anchor {
color: var(--MAIN-ANCHOR-color);
}
a:hover {
color: var(--MAIN-LINK-HOVER-color);
}
#sidebar ul li.visited > a .read-icon {
color: var(--MENU-VISITED-color);
}
#body a.highlight:after {
display: block;
content: "";
height: 1px;
width: 0%;
-webkit-transition: width 0.5s ease;
-moz-transition: width 0.5s ease;
-ms-transition: width 0.5s ease;
transition: width 0.5s ease;
background-color: var(--MAIN-LINK-HOVER-color);
}
#sidebar {
background-color: var(--MENU-SECTIONS-BG-color);
}
#sidebar #header-wrapper {
background: var(--MENU-HEADER-BG-color);
color: var(--MENU-SEARCH-BOX-color);
border-color: var(--MENU-HEADER-BORDER-color);
}
#sidebar .searchbox {
border-color: var(--MENU-SEARCH-BOX-color);
background: var(--MENU-SEARCH-BG-color);
}
#sidebar ul.topics > li.parent, #sidebar ul.topics > li.active {
background: var(--MENU-SECTIONS-ACTIVE-BG-color);
}
#sidebar .searchbox * {
color: var(--MENU-SEARCH-BOX-ICONS-color);
}
#sidebar a {
color: var(--MENU-SECTIONS-LINK-color);
}
#sidebar a:hover {
color: var(--MENU-SECTIONS-LINK-HOVER-color);
}
#sidebar ul li.active > a {
background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color);
color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important;
}
#sidebar hr {
border-color: var(--MENU-SECTION-HR-color);
}
#body .tags a.tag-link {
background-color: var(--MENU-HEADER-BG-color);
}
#body .tags a.tag-link:before {
border-right-color: var(--MENU-HEADER-BG-color);
}
#homelinks {
background: var(--MENU-HEADER-BG-color);
background-color: var(--MENU-HEADER-BORDER-color);
border-bottom-color: var(--MENU-HEADER-BORDER-color);
}
#homelinks a {
color: var(--MENU-HOME-LINK-color);
}
#homelinks a:hover {
color: var(--MENU-HOME-LINK-HOVERED-color);
}

View File

@ -1,128 +0,0 @@
:root{
--MAIN-TEXT-color:#323232; /* Color of text by default */
--MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */
--MAIN-LINK-color:#599a3e; /* Color of links */
--MAIN-LINK-HOVER-color:#3f6d2c; /* Color of hovered links */
--MAIN-ANCHOR-color: #599a3e; /* color of anchors on titles */
--MENU-HOME-LINK-color: #323232; /* Color of the home button text */
--MENU-HOME-LINK-HOVER-color: #5e5e5e; /* Color of the hovered home button text */
--MENU-HEADER-BG-color:#74b559; /* Background color of menu header */
--MENU-HEADER-BORDER-color:#9cd484; /*Color of menu header border */
--MENU-SEARCH-BG-color:#599a3e; /* Search field background color (by default borders + icons) */
--MENU-SEARCH-BOX-color: #84c767; /* Override search field border color */
--MENU-SEARCH-BOX-ICONS-color: #c7f7c4; /* Override search field icons color */
--MENU-SECTIONS-ACTIVE-BG-color:#1b211c; /* Background color of the active section and its childs */
--MENU-SECTIONS-BG-color:#222723; /* Background color of other sections */
--MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */
--MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */
--MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */
--MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */
--MENU-VISITED-color: #599a3e; /* Color of 'page visited' icons in menu */
--MENU-SECTION-HR-color: #18211c; /* Color of <hr> separator in menu */
}
body {
color: var(--MAIN-TEXT-color) !important;
}
textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus {
border-color: none;
box-shadow: none;
}
h2, h3, h4, h5 {
color: var(--MAIN-TITLES-TEXT-color) !important;
}
a {
color: var(--MAIN-LINK-color);
}
.anchor {
color: var(--MAIN-ANCHOR-color);
}
a:hover {
color: var(--MAIN-LINK-HOVER-color);
}
#sidebar ul li.visited > a .read-icon {
color: var(--MENU-VISITED-color);
}
#body a.highlight:after {
display: block;
content: "";
height: 1px;
width: 0%;
-webkit-transition: width 0.5s ease;
-moz-transition: width 0.5s ease;
-ms-transition: width 0.5s ease;
transition: width 0.5s ease;
background-color: var(--MAIN-LINK-HOVER-color);
}
#sidebar {
background-color: var(--MENU-SECTIONS-BG-color);
}
#sidebar #header-wrapper {
background: var(--MENU-HEADER-BG-color);
color: var(--MENU-SEARCH-BOX-color);
border-color: var(--MENU-HEADER-BORDER-color);
}
#sidebar .searchbox {
border-color: var(--MENU-SEARCH-BOX-color);
background: var(--MENU-SEARCH-BG-color);
}
#sidebar ul.topics > li.parent, #sidebar ul.topics > li.active {
background: var(--MENU-SECTIONS-ACTIVE-BG-color);
}
#sidebar .searchbox * {
color: var(--MENU-SEARCH-BOX-ICONS-color);
}
#sidebar a {
color: var(--MENU-SECTIONS-LINK-color);
}
#sidebar a:hover {
color: var(--MENU-SECTIONS-LINK-HOVER-color);
}
#sidebar ul li.active > a {
background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color);
color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important;
}
#sidebar hr {
border-color: var(--MENU-SECTION-HR-color);
}
#body .tags a.tag-link {
background-color: var(--MENU-HEADER-BG-color);
}
#body .tags a.tag-link:before {
border-right-color: var(--MENU-HEADER-BG-color);
}
#homelinks {
background: var(--MENU-HEADER-BG-color);
background-color: var(--MENU-HEADER-BORDER-color);
border-bottom-color: var(--MENU-HEADER-BORDER-color);
}
#homelinks a {
color: var(--MENU-HOME-LINK-color);
}
#homelinks a:hover {
color: var(--MENU-HOME-LINK-HOVERED-color);
}

View File

@ -1,128 +0,0 @@
:root{
--MAIN-TEXT-color:#323232; /* Color of text by default */
--MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */
--MAIN-LINK-color:#f31c1c; /* Color of links */
--MAIN-LINK-HOVER-color:#d01616; /* Color of hovered links */
--MAIN-ANCHOR-color: #f31c1c; /* color of anchors on titles */
--MENU-HOME-LINK-color: #ccc; /* Color of the home button text */
--MENU-HOME-LINK-HOVER-color: #e6e6e6; /* Color of the hovered home button text */
--MENU-HEADER-BG-color:#dc1010; /* Background color of menu header */
--MENU-HEADER-BORDER-color:#e23131; /*Color of menu header border */
--MENU-SEARCH-BG-color:#b90000; /* Search field background color (by default borders + icons) */
--MENU-SEARCH-BOX-color: #ef2020; /* Override search field border color */
--MENU-SEARCH-BOX-ICONS-color: #fda1a1; /* Override search field icons color */
--MENU-SECTIONS-ACTIVE-BG-color:#2b2020; /* Background color of the active section and its childs */
--MENU-SECTIONS-BG-color:#312525; /* Background color of other sections */
--MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */
--MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */
--MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */
--MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */
--MENU-VISITED-color: #ff3333; /* Color of 'page visited' icons in menu */
--MENU-SECTION-HR-color: #2b2020; /* Color of <hr> separator in menu */
}
body {
color: var(--MAIN-TEXT-color) !important;
}
textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus {
border-color: none;
box-shadow: none;
}
h2, h3, h4, h5 {
color: var(--MAIN-TITLES-TEXT-color) !important;
}
a {
color: var(--MAIN-LINK-color);
}
.anchor {
color: var(--MAIN-ANCHOR-color);
}
a:hover {
color: var(--MAIN-LINK-HOVER-color);
}
#sidebar ul li.visited > a .read-icon {
color: var(--MENU-VISITED-color);
}
#body a.highlight:after {
display: block;
content: "";
height: 1px;
width: 0%;
-webkit-transition: width 0.5s ease;
-moz-transition: width 0.5s ease;
-ms-transition: width 0.5s ease;
transition: width 0.5s ease;
background-color: var(--MAIN-LINK-HOVER-color);
}
#sidebar {
background-color: var(--MENU-SECTIONS-BG-color);
}
#sidebar #header-wrapper {
background: var(--MENU-HEADER-BG-color);
color: var(--MENU-SEARCH-BOX-color);
border-color: var(--MENU-HEADER-BORDER-color);
}
#sidebar .searchbox {
border-color: var(--MENU-SEARCH-BOX-color);
background: var(--MENU-SEARCH-BG-color);
}
#sidebar ul.topics > li.parent, #sidebar ul.topics > li.active {
background: var(--MENU-SECTIONS-ACTIVE-BG-color);
}
#sidebar .searchbox * {
color: var(--MENU-SEARCH-BOX-ICONS-color);
}
#sidebar a {
color: var(--MENU-SECTIONS-LINK-color);
}
#sidebar a:hover {
color: var(--MENU-SECTIONS-LINK-HOVER-color);
}
#sidebar ul li.active > a {
background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color);
color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important;
}
#sidebar hr {
border-color: var(--MENU-SECTION-HR-color);
}
#body .tags a.tag-link {
background-color: var(--MENU-HEADER-BG-color);
}
#body .tags a.tag-link:before {
border-right-color: var(--MENU-HEADER-BG-color);
}
#homelinks {
background: var(--MENU-HEADER-BG-color);
background-color: var(--MENU-HEADER-BORDER-color);
border-bottom-color: var(--MENU-HEADER-BORDER-color);
}
#homelinks a {
color: var(--MENU-HOME-LINK-color);
}
#homelinks a:hover {
color: var(--MENU-HOME-LINK-HOVERED-color);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<title>https://doc.cuates.net/easymacro</title>
<link rel="canonical" href="https://doc.cuates.net/easymacro">
<meta name="robots" content="noindex">
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=https://doc.cuates.net/easymacro">
</head>
</html>

View File

@ -1,101 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://doc.cuates.net/easymacro/installation/</loc>
<xhtml:link
rel="alternate"
hreflang="es"
href="https://doc.cuates.net/easymacro/es/installation/"
/>
<xhtml:link
rel="alternate"
hreflang="pt"
href="https://doc.cuates.net/easymacro/pt/installation/"
/>
<xhtml:link
rel="alternate"
hreflang="en"
href="https://doc.cuates.net/easymacro/installation/"
/>
</url><url>
<loc>https://doc.cuates.net/easymacro/tools_debug/</loc>
<xhtml:link
rel="alternate"
hreflang="es"
href="https://doc.cuates.net/easymacro/es/tools_debug/"
/>
<xhtml:link
rel="alternate"
hreflang="en"
href="https://doc.cuates.net/easymacro/tools_debug/"
/>
</url><url>
<loc>https://doc.cuates.net/easymacro/</loc>
<priority>0</priority>
<xhtml:link
rel="alternate"
hreflang="es"
href="https://doc.cuates.net/easymacro/es/"
/>
<xhtml:link
rel="alternate"
hreflang="pt"
href="https://doc.cuates.net/easymacro/pt/"
/>
<xhtml:link
rel="alternate"
hreflang="fr"
href="https://doc.cuates.net/easymacro/fr/"
/>
<xhtml:link
rel="alternate"
hreflang="en"
href="https://doc.cuates.net/easymacro/"
/>
</url><url>
<loc>https://doc.cuates.net/easymacro/categories/</loc>
<xhtml:link
rel="alternate"
hreflang="es"
href="https://doc.cuates.net/easymacro/es/categories/"
/>
<xhtml:link
rel="alternate"
hreflang="pt"
href="https://doc.cuates.net/easymacro/pt/categories/"
/>
<xhtml:link
rel="alternate"
hreflang="fr"
href="https://doc.cuates.net/easymacro/fr/categories/"
/>
<xhtml:link
rel="alternate"
hreflang="en"
href="https://doc.cuates.net/easymacro/categories/"
/>
</url><url>
<loc>https://doc.cuates.net/easymacro/tags/</loc>
<xhtml:link
rel="alternate"
hreflang="es"
href="https://doc.cuates.net/easymacro/es/tags/"
/>
<xhtml:link
rel="alternate"
hreflang="pt"
href="https://doc.cuates.net/easymacro/pt/tags/"
/>
<xhtml:link
rel="alternate"
hreflang="fr"
href="https://doc.cuates.net/easymacro/fr/tags/"
/>
<xhtml:link
rel="alternate"
hreflang="en"
href="https://doc.cuates.net/easymacro/tags/"
/>
</url>
</urlset>

View File

@ -1,59 +0,0 @@
<!DOCTYPE html>
<html lang="es" class="js csstransforms3d">
<head>
<meta charset="utf-8"> <meta name="description" content="">
<link rel="icon" href="/easymacro/images/favicon.png" type="image/png">
<title>404 Page not found</title>
<link href="/easymacro/css/nucleus.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/fontawesome-all.min.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/hybrid.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/featherlight.min.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/perfect-scrollbar.min.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/theme.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/hugo-theme.css?1661091037" rel="stylesheet">
<link href="/easymacro/css/theme-blue.css?1661091037" rel="stylesheet">
<style>
:root #header + #content > #left > #rlblock_left {
display: none !important;
}
p,
li,
ul {
text-align: center
}
ul {
list-style-type: none;
}
</style>
</head>
<body class="" data-url="/">
<section id="body" style="margin-left:0px;">
<div id="overlay"></div>
<div id="chapter">
<div id="body-inner">
<h1>Error</h1>
<p>
</p>
<p>Ups. Parece que la página no existe ¯\_(ツ)_/¯.</p>
<p></p>
<p><a href='/easymacro/es'>Ir al inicio</a></p>
<p><img src='/images/gopher-404.jpg' style="width:50%" alt="Page not found!"></p>
</div>
</div>
</section>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>LibreOffice on Documentación para EasyMacro</title>
<link>https://doc.cuates.net/easymacro/es/application/</link>
<description>Recent content in LibreOffice on Documentación para EasyMacro</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language><atom:link href="https://doc.cuates.net/easymacro/es/application/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Menús on Documentación para EasyMacro</title>
<link>https://doc.cuates.net/easymacro/es/application/menus/</link>
<description>Recent content in Menús on Documentación para EasyMacro</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language><atom:link href="https://doc.cuates.net/easymacro/es/application/menus/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Accesos directos on Documentación para EasyMacro</title>
<link>https://doc.cuates.net/easymacro/es/application/shortcuts/</link>
<description>Recent content in Accesos directos on Documentación para EasyMacro</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language><atom:link href="https://doc.cuates.net/easymacro/es/application/shortcuts/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Celdas y rangos on Documentación para EasyMacro</title>
<link>https://doc.cuates.net/easymacro/es/calc/cells/</link>
<description>Recent content in Celdas y rangos on Documentación para EasyMacro</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language><atom:link href="https://doc.cuates.net/easymacro/es/calc/cells/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Métodos on Documentación para EasyMacro</title>
<link>https://doc.cuates.net/easymacro/es/calc/cells/methods/</link>
<description>Recent content in Métodos on Documentación para EasyMacro</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language><atom:link href="https://doc.cuates.net/easymacro/es/calc/cells/methods/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Propiedades on Documentación para EasyMacro</title>
<link>https://doc.cuates.net/easymacro/es/calc/cells/properties/</link>
<description>Recent content in Propiedades on Documentación para EasyMacro</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language><atom:link href="https://doc.cuates.net/easymacro/es/calc/cells/properties/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Calc on Documentación para EasyMacro</title>
<link>https://doc.cuates.net/easymacro/es/calc/</link>
<description>Recent content in Calc on Documentación para EasyMacro</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language><atom:link href="https://doc.cuates.net/easymacro/es/calc/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Conjuntos de Rangos on Documentación para EasyMacro</title>
<link>https://doc.cuates.net/easymacro/es/calc/ranges/</link>
<description>Recent content in Conjuntos de Rangos on Documentación para EasyMacro</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language><atom:link href="https://doc.cuates.net/easymacro/es/calc/ranges/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More