Compare commits
13 Commits
Author | SHA1 | Date |
---|---|---|
El Mau | 2069ac0ba8 | |
El Mau | 0b116337c4 | |
El Mau | d337678d4e | |
El Mau | 12c6c5deaf | |
El Mau | 74a781044c | |
El Mau | 5a02f50cc6 | |
El Mau | d0c5f3a8ed | |
El Mau | 3aaec4df56 | |
Mauricio | 3313dddae2 | |
Mauricio | cbf560abef | |
Mauricio | 70654bf40f | |
Mauricio | b8954d7ade | |
Mauricio | 70e1933537 |
|
@ -5,3 +5,4 @@ build/
|
|||
*.lock
|
||||
bk/
|
||||
site/
|
||||
update.sh
|
||||
|
|
15
CHANGELOG.md
|
@ -1,6 +1,19 @@
|
|||
v 0.6.0 [17-Dec-2023]
|
||||
---------------------
|
||||
- Add control styles.
|
||||
|
||||
v 0.5.0 [07-Dec-2023]
|
||||
---------------------
|
||||
- Add acctions to controls.
|
||||
- Refactorize documetation.
|
||||
|
||||
v 0.4.0 [20-Sep-2023]
|
||||
---------------------
|
||||
- Add control layout manager.
|
||||
|
||||
v 0.3.0 [23-Apr-2023]
|
||||
---------------------
|
||||
- Add method post
|
||||
- Add method post.
|
||||
|
||||
v 0.2.0 [23-Sep-2022]
|
||||
---------------------
|
||||
|
|
|
@ -14,11 +14,11 @@ This library have a cost of maintenance of 1 euro every year.
|
|||
|
||||
In order of preferred.
|
||||
|
||||
* G1: `A5DdXxCKPw3QKWVdDVs7CzkNugNUW1sHu5zDJFWxCU2h`
|
||||
|
||||
Mauricio Baeza
|
||||
```
|
||||
Euros
|
||||
IBAN: BE60 9671 0556 5870
|
||||
SWIFT / BIC: TRWIBEB1XXX
|
||||
```
|
||||
|
||||
* G1: `A5DdXxCKPw3QKWVdDVs7CzkNugNUW1sHu5zDJFWxCU2h`
|
||||
```
|
|
@ -0,0 +1,198 @@
|
|||
## Tools for debug
|
||||
|
||||
<br>
|
||||
|
||||
### **INFO_DEBUG**
|
||||
|
||||
Show debugging information in a message box.
|
||||
|
||||
If you have any problems in your code during the development of your macros, you can [open a ticket][1] support in the system ticket of this project. Always copy the debugging information shown in your issue.
|
||||
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
def info():
|
||||
app.msgbox(app.INFO_DEBUG)
|
||||
return
|
||||
```
|
||||
|
||||
![Info debug](img/install_01.png)
|
||||
|
||||
|
||||
### **debug**
|
||||
|
||||
Show information at the terminal.
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
def test_debug():
|
||||
msg = 'Verify this information...'
|
||||
app.debug(msg)
|
||||
return
|
||||
```
|
||||
|
||||
To view this message, you need to start LibreOffice from the command line:
|
||||
```
|
||||
soffice --calc
|
||||
```
|
||||
|
||||
After executing the previous macro, you should see:
|
||||
```
|
||||
21/04/2023 17:04:49 - DEBUG - Verify this information...
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **info**
|
||||
|
||||
Show information messages at the terminal.
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
def test_info():
|
||||
msg = 'Starting process...'
|
||||
app.info(msg)
|
||||
return
|
||||
```
|
||||
|
||||
```
|
||||
11/08/2022 18:23:53 - INFO - Starting process...
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **error**
|
||||
|
||||
Show error messages at the terminal.
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
def test_error():
|
||||
msg = 'Error 505'
|
||||
app.error(msg)
|
||||
return
|
||||
```
|
||||
|
||||
```
|
||||
11/08/2022 18:27:34 - ERROR - Error 505
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **save_log**
|
||||
|
||||
Save log in file, automatically add date and time.
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
def test_save_log():
|
||||
|
||||
app.save_log('/home/mau/log.txt', 'PyUNO')
|
||||
app.save_log('/home/mau/log.txt', 'World Damn')
|
||||
|
||||
return
|
||||
```
|
||||
|
||||
```
|
||||
cat ~/log.txt
|
||||
2022-08-11 18:30:11 - 'PyUNO'
|
||||
2022-08-11 18:30:11 - 'World Damn'
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **msgbox**
|
||||
|
||||
Show any information in a message box.
|
||||
```python
|
||||
import easymacro as app
|
||||
|
||||
def message():
|
||||
|
||||
msg = 'Please, consume less.'
|
||||
app.msgbox(msg)
|
||||
|
||||
msg = ('one', 2, 'three')
|
||||
app.msgbox(msg)
|
||||
|
||||
msg = {'name': 'Teresa'}
|
||||
app.msgbox(msg)
|
||||
|
||||
app.msgbox(app)
|
||||
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **catch_exception**
|
||||
|
||||
Capture any error that occurs when running a macro.
|
||||
|
||||
!!! warning inline end "Caution"
|
||||
|
||||
Use this method only in development time. **Do not use it in production**.
|
||||
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
@app.catch_exception
|
||||
def test_capture_error():
|
||||
r = 1 / 0
|
||||
return
|
||||
```
|
||||
|
||||
```
|
||||
11/08/2022 18:44:36 - ERROR - test_capture_error
|
||||
Traceback (most recent call last):
|
||||
File "/home/mau/.config/libreoffice/4/user/Scripts/python/pythonpath/easymacro/easytools.py", line 115, in func
|
||||
return f(*args, **kwargs)
|
||||
File "/home/mau/.config/libreoffice/4/user/Scripts/python/test.py", line 18, in test_capturar_error
|
||||
r = 1 / 0
|
||||
ZeroDivisionError: division by zero
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **mri**
|
||||
|
||||
[MRI][2] is the best extension to inspect any UNO LibreOffice object. You need to install it first so you can use it.
|
||||
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
def inspect_object():
|
||||
obj = app.active
|
||||
app.mri(obj)
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **inspect**
|
||||
|
||||
Inspect an object.
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
def inspect_object():
|
||||
doc = app.active
|
||||
data = app.inspect(doc)
|
||||
for p in data.properties:
|
||||
app.debug(p)
|
||||
for m in data.methods:
|
||||
app.debug(m)
|
||||
return
|
||||
```
|
||||
|
||||
Send information of the object to worksheet.
|
||||
```python
|
||||
def inspect_object():
|
||||
doc = app.active
|
||||
app.inspect(doc, True)
|
||||
return
|
||||
```
|
||||
|
||||
|
||||
[1]: https://git.cuates.net/elmau/easymacro/issues
|
||||
[2]: https://github.com/hanya/MRI
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 380 B After Width: | Height: | Size: 380 B |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 10 KiB |
|
@ -0,0 +1,29 @@
|
|||
# Welcome to EasyMacro's documentation
|
||||
|
||||
**Free Software, not gratis software**
|
||||
|
||||
<br>
|
||||
|
||||
**easymacro** is a library to develop more easily macros in LibreOffice with Python. It is an abstraction layer between the extensive and complex UNO LibreOffice API and your code.
|
||||
|
||||
You will probably be happier if you use it :)
|
||||
|
||||
You can use **easymacro** with any extension or directly on your macros.
|
||||
|
||||
<br>
|
||||
|
||||
- Symily or related projects in 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)
|
||||
- Symily or related projects in other languages:
|
||||
* [Java LibreOffice Programming](https://flywire.github.io/lo-p/)
|
||||
|
||||
<br>
|
||||
|
||||
Contributions:
|
||||
|
||||
- Moneda Libre Ğ1 (Junas):<br>
|
||||
`A5DdXxCKPw3QKWVdDVs7CzkNugNUW1sHu5zDJFWxCU2h`
|
||||
|
||||
<br>
|
|
@ -0,0 +1,47 @@
|
|||
## Clone repository
|
||||
|
||||
Clone the repository in your favorite project directory.
|
||||
```
|
||||
git clone https://git.cuates.net/elmau/easymacro
|
||||
```
|
||||
|
||||
Move into the directory
|
||||
```
|
||||
cd easymacro/source
|
||||
```
|
||||
|
||||
copy the `easymacro` folder into the **pythonpath** folder in the Python macro folder within your user profile. Replace **USER** by your real user.
|
||||
```
|
||||
/home/USER/.config/libreoffice/4/user/Scripts/python/pythonpath
|
||||
```
|
||||
|
||||
or use a symbolic link (recommended). Replace **PATH** by the absolute route where **easymacro** is located in your file system and **USER** by your username.
|
||||
```
|
||||
ln -s PATH/easymacro/source/easymacro /home/USER/.config/libreoffice/4/user/Scripts/python/pythonpath/
|
||||
```
|
||||
|
||||
|
||||
## Test
|
||||
|
||||
In your favorite macros file, for example **mymacros.py**. Use your favorite plain text editor or IDE. Remember, replace **USER** by your real user.
|
||||
```
|
||||
geany /home/USER/.config/libreoffice/4/user/Scripts/python/mymacros.py
|
||||
```
|
||||
|
||||
Copy the following code:
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
def main():
|
||||
app.msgbox(app.INFO_DEBUG)
|
||||
return
|
||||
```
|
||||
|
||||
Run the **main** macro in LibreOffice, if you see a message box with information similar to the following!
|
||||
|
||||
![Test install](img/install_01.png)
|
||||
|
||||
It is all ready to start developing macros with **easymacro**.
|
||||
|
||||
|
||||
Happy programming!
|
|
@ -0,0 +1,178 @@
|
|||
|
||||
!!! tip "Attention"
|
||||
|
||||
Start date in Calc and Python are different.
|
||||
|
||||
<br>
|
||||
|
||||
### **today**
|
||||
|
||||
Get current date.
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
app.msgbox(d.today)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **now**
|
||||
|
||||
Get current date and time.
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
app.msgbox(d.now)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **time**
|
||||
|
||||
Get current time.
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
app.msgbox(d.now.time())
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **epoch**
|
||||
|
||||
Get [Unix time][1]
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
app.msgbox(d.epoch)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **date**
|
||||
|
||||
Get a date.
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
|
||||
date = d.date(1974, 1, 15)
|
||||
app.msgbox(date)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **time**
|
||||
|
||||
Get a time.
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
|
||||
time = d.time(10, 20, 15)
|
||||
app.msgbox(time)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **datetime**
|
||||
|
||||
Get date and time.
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
|
||||
dt = d.datetime(1974, 1, 15, 10, 11, 12)
|
||||
app.msgbox(dt)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **str_to_date**
|
||||
|
||||
|
||||
String to date. Look this [excellent info][2]
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
|
||||
str_date = '1974-01-15'
|
||||
template = '%Y-%m-%d'
|
||||
obj_date = d.str_to_date(str_date, template)
|
||||
app.msgbox(obj_date)
|
||||
app.msgbox(type(obj_date))
|
||||
```
|
||||
|
||||
Get a valid date for insert in a Calc cell.
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
|
||||
str_date = '1974-01-15'
|
||||
template = '%Y-%m-%d'
|
||||
obj_date = d.str_to_date(str_date, template, True)
|
||||
app.msgbox(obj_date)
|
||||
app.msgbox(type(obj_date))
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **calc_to_date**
|
||||
|
||||
Converts a value to Python date, for example, the initial date set in Calc.
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
|
||||
value = 0
|
||||
obj_date = d.calc_to_date(value)
|
||||
app.msgbox(obj_date)
|
||||
app.msgbox(type(obj_date))
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **sleep**
|
||||
|
||||
Pause execution for X seconds.
|
||||
|
||||
!!! tip inline end "Attention"
|
||||
|
||||
The pause is blocking.
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
|
||||
app.sleep(3)
|
||||
app.msgbox('End')
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **start** and **end**
|
||||
|
||||
Measure time in seconds.
|
||||
|
||||
```py
|
||||
d = app.dates
|
||||
|
||||
d.start()
|
||||
app.sleep(5)
|
||||
seconds = d.end()
|
||||
app.msgbox(seconds)
|
||||
```
|
||||
|
||||
Get timedelta instead of seconds
|
||||
|
||||
```py
|
||||
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
|
|
@ -0,0 +1,123 @@
|
|||
---
|
||||
title: Information
|
||||
---
|
||||
|
||||
Remember, import first the library.
|
||||
|
||||
```py
|
||||
import easymacro as app
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## About PC
|
||||
|
||||
<br>
|
||||
|
||||
### **OS**
|
||||
|
||||
Get Operate System.
|
||||
```py
|
||||
app.msgbox(app.OS)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **DESKTOP**
|
||||
|
||||
Get desktop type, only GNU/Linux.
|
||||
```py
|
||||
app.msgbox(app.DESKTOP)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **PC**
|
||||
|
||||
Get PC name.
|
||||
```py
|
||||
app.msgbox(app.PC)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **USER**
|
||||
|
||||
Get user name.
|
||||
```py
|
||||
app.msgbox(app.USER)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **IS_WIN**
|
||||
|
||||
If OS is Windows.
|
||||
```py
|
||||
app.msgbox(app.IS_WIN)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **IS_MAC**
|
||||
|
||||
IF OS is MAC
|
||||
```py
|
||||
app.msgbox(app.IS_MAC)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## About LibreOffice
|
||||
|
||||
### **NAME**
|
||||
|
||||
Application name.
|
||||
```py
|
||||
app.msgbox(app.NAME)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **VERSION**
|
||||
|
||||
Version.
|
||||
```py
|
||||
app.msgbox(app.VERSION)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **LANG**
|
||||
|
||||
Language
|
||||
```py
|
||||
app.msgbox(app.LANG)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **LANGUAGE**
|
||||
|
||||
Language with variant.
|
||||
```py
|
||||
app.msgbox(app.LANGUAGE)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **IS_APPIMAGE**
|
||||
|
||||
If LibreOffice use by AppImage.
|
||||
```py
|
||||
app.msgbox(app.IS_APPIMAGE)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **IS_FLATPAK**
|
||||
|
||||
If LibreOffice is use by FlatPak.
|
||||
```py
|
||||
app.msgbox(app.IS_FLATPAK)
|
||||
```
|
|
@ -0,0 +1,75 @@
|
|||
## Message Box
|
||||
|
||||
### **msgbox**
|
||||
|
||||
Show standard message.
|
||||
```py
|
||||
message = 'Fucking World'
|
||||
title = 'My Macro'
|
||||
app.msgbox(message, title)
|
||||
```
|
||||
|
||||
![msgbox](../img/tools_msg_01.png)
|
||||
|
||||
<br>
|
||||
|
||||
### **warning**
|
||||
|
||||
Show message with warning icon.
|
||||
```py
|
||||
message = 'Caution, this action is dangerous'
|
||||
title = 'My Macro'
|
||||
app.warning(message, title)
|
||||
```
|
||||
|
||||
![warning](../img/tools_msg_02.png)
|
||||
|
||||
<br>
|
||||
|
||||
### **errorbox**
|
||||
|
||||
Show message with error icon.
|
||||
```py
|
||||
message = 'ERROR: contact support'
|
||||
title = 'My Macro'
|
||||
app.errorbox(message, title)
|
||||
```
|
||||
|
||||
![error](../img/tools_msg_03.png)
|
||||
|
||||
<br>
|
||||
|
||||
### **question**
|
||||
|
||||
Ask a question by showing the interrogation icon and displaying the command buttons `Yes` and `No`. The answer is always True if user select `yes` and False otherwise.
|
||||
```py
|
||||
message = 'Python is easy?'
|
||||
title = 'My Macro'
|
||||
result = app.question(message, title)
|
||||
app.msgbox(result)
|
||||
```
|
||||
|
||||
![question](../img/tools_msg_04.png)
|
||||
|
||||
<br>
|
||||
|
||||
### **inputbox**
|
||||
|
||||
Shows a message to user, allowing to capture an answer.
|
||||
```py
|
||||
message = 'Capture your name'
|
||||
name = app.inputbox(message)
|
||||
app.msgbox(name)
|
||||
```
|
||||
|
||||
![inputbox](../img/tools_msg_05.png)
|
||||
|
||||
To hide on screen what the user typing, util for request passwords.
|
||||
```py
|
||||
message = 'Type your password'
|
||||
echochar = '*'
|
||||
password = app.inputbox(message, echochar=echochar)
|
||||
app.msgbox(password)
|
||||
```
|
||||
|
||||
![inputbox](../img/tools_msg_06.png)
|
|
@ -0,0 +1,44 @@
|
|||
site_name: EasyMacro for LibreOffice
|
||||
site_url: https://doc.cuates.net/easymacro/
|
||||
repo_url: https://git.cuates.net/elmau/easymacro/
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Install: install.md
|
||||
- Debug: debug.md
|
||||
- Tools:
|
||||
- tools/index.md
|
||||
- Messages: tools/messages.md
|
||||
- Dates and time: tools/datetime.md
|
||||
theme:
|
||||
name: material
|
||||
locale: en
|
||||
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.tabbed:
|
||||
alternate_style: true
|
||||
- tables
|
||||
- pymdownx.keys
|
||||
extra:
|
||||
alternate:
|
||||
- name: English
|
||||
link: /easymacro
|
||||
lang: en
|
||||
- name: Español
|
||||
link: /easymacro/langs/es
|
||||
lang: es
|
|
@ -0,0 +1,601 @@
|
|||
|
||||
## Trabajar con celdas y rangos
|
||||
|
||||
---
|
||||
|
||||
### **address**
|
||||
|
||||
Referencia por dirección.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
rango = hoja['C10:D15']
|
||||
|
||||
app.debug(celda)
|
||||
app.debug(rango)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **doc**
|
||||
|
||||
Devuelve el documento padre.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
rango = hoja['A1:C5']
|
||||
|
||||
doc = rango.doc
|
||||
app.debug(doc)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **in**
|
||||
|
||||
Verificar si un rango esta dentro de otro.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
celda = hoja['C5']
|
||||
rango = hoja['A1:E10']
|
||||
|
||||
resultado = celda in rango
|
||||
app.debug(resultado)
|
||||
|
||||
celda = hoja['C50']
|
||||
resultado = celda in rango
|
||||
app.debug(resultado)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **iter**
|
||||
|
||||
Iterar cada celda de un rango.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
rango = hoja['B10:C15']
|
||||
|
||||
for celda in rango:
|
||||
app.debug(celda)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **position**
|
||||
|
||||
Referencia por posición.
|
||||
|
||||
Para celdas: `HOJA[fila,columna]`
|
||||
|
||||
Para rangos: `HOJA[fila_inicial:fila_final, columna_inicial:columna_final]`
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
# ~ Cell A10
|
||||
celda = hoja[9,0]
|
||||
|
||||
# ~ Range A1:C10
|
||||
rango = hoja[0:10,0:3]
|
||||
```
|
||||
|
||||
!!! tip "Atención"
|
||||
|
||||
Recuerde que las filas y columnas empiezan en cero, por lo que `fila_final` y la `columna_final` deben de ser la fila y columna deseada más 1.
|
||||
|
||||
<br>
|
||||
|
||||
### **selection**
|
||||
|
||||
Referencia por selección actual.
|
||||
|
||||
```py
|
||||
seleccion = app.active.selection
|
||||
app.debug(seleccion)
|
||||
```
|
||||
|
||||
!!! tip "Atención"
|
||||
|
||||
Recuerde que la selección actual pueden ser varias cosas diferentes.
|
||||
|
||||
<br>
|
||||
|
||||
## Propiedades
|
||||
|
||||
---
|
||||
|
||||
### **address**
|
||||
|
||||
Devuelve la dirección de la celda como una estructura: `com.sun.star.table.CellAddress`
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
celda = hoja['A1']
|
||||
if celda.is_cell:
|
||||
app.debug(celda.address)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **back_color**
|
||||
|
||||
Devuelve o aplica el color de fondo del rango.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
rango = hoja['A1:E10']
|
||||
rango.back_color = 'red'
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **current_region**
|
||||
|
||||
Devuelve la región actual.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
celda = hoja['A1']
|
||||
rango = celda.current_region
|
||||
app.debug(rango)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **data**
|
||||
|
||||
Alias de `data_array` al obtener los datos. Al establecer los datos, si es un rango se comporta como `data_array`, pero si es una celda, se autoajusta al tamaño de los datos.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
datos = (
|
||||
(1, 'Uno'),
|
||||
(2, 'Dos'),
|
||||
(3, 'Tres'),
|
||||
)
|
||||
|
||||
celda.data = datos
|
||||
app.debug(celda.current_region.data)
|
||||
```
|
||||
|
||||
!!! warning "Cuidado"
|
||||
|
||||
Siempre valide que haya suficientes celdas libres para los datos para evitar sobreescribirlos.
|
||||
|
||||
<br>
|
||||
|
||||
### **data_array**
|
||||
|
||||
Devuelve o establece los datos de un rango. Es un alias de `DataArray`.
|
||||
|
||||
```py
|
||||
rango = app.active.selection
|
||||
|
||||
datos = rango.data_array
|
||||
app.debug(datos)
|
||||
rango.data_array = datos
|
||||
```
|
||||
|
||||
!!! warning "Cuidado"
|
||||
|
||||
El tamaño de los datos, debe ser **exactamente** del tamaño del rango destino. De lo contrario obtendrá un error.
|
||||
|
||||
<br>
|
||||
|
||||
### **date**
|
||||
|
||||
Devuelve o establece el contenido de la celda como fecha.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
celda.date = app.dates.date(1974, 1, 15)
|
||||
app.debug(type(celda.date), celda.date)
|
||||
```
|
||||
|
||||
```
|
||||
20/08/2022 18:38:53 - DEBUG - <class 'datetime.date'> 1974-01-15
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **datetime**
|
||||
|
||||
Devuelve o establece el contenido de la celda como fecha y tiempo.
|
||||
|
||||
```python
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
celda.datetime = app.dates.datetime(1974, 1, 15, 10, 11, 12)
|
||||
app.debug(type(celda.datetime), celda.datetime)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **dict**
|
||||
|
||||
Devuelve o establece los datos como diccionarios. Automáticamente ajusta el rango al tamaño de los datos.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
|
||||
datos = (
|
||||
{'No': 1, 'Nombre': 'Ingrid'},
|
||||
{'No': 2, 'Nombre': 'Sophia'},
|
||||
{'No': 3, 'Nombre': 'Scarlette'},
|
||||
)
|
||||
|
||||
celda.dict = datos
|
||||
app.debug(celda.current_region.dict)
|
||||
```
|
||||
|
||||
!!! warning "Consejo"
|
||||
|
||||
Siempre valide que haya suficientes celdas libres para los datos para evitar sobreescribirlos, a menos que eso sea lo que realmente quiera.
|
||||
|
||||
<br>
|
||||
|
||||
### **error**
|
||||
|
||||
Si la celda tiene una formula con error, devuelve el número de error.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
celda.value = '=RAND()/0'
|
||||
app.debug(celda.error)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **float**
|
||||
|
||||
Devuelve o establece el contenido de la celda como valor.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
celda.float = 12345
|
||||
app.debug(celda.type, celda.float)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **formula**
|
||||
|
||||
Devuelve o establece la formula de la celda.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
celda.formula = '=RAND()'
|
||||
app.debug(celda.type, celda.formula)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **formula_array**
|
||||
|
||||
Devuelve o establece los datos de un rango. Es un alias de `FormulaArray`.
|
||||
|
||||
```py
|
||||
rango = app.active.selection
|
||||
|
||||
datos = rango.data_array
|
||||
app.debug(datos)
|
||||
datos = rango.formula_array
|
||||
app.debug(datos)
|
||||
rango.formula_array = datos
|
||||
```
|
||||
|
||||
!!! tip "Consejo"
|
||||
|
||||
**data_array** devolverá los resultados de las celdas con formulas. **formula_array** devolverá las formulas en dichas celdas.
|
||||
|
||||
<br>
|
||||
|
||||
### **is_cell**
|
||||
|
||||
Verdadero (True) si el objeto es de una celda.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
celda = hoja['A1']
|
||||
app.debug(celda.is_cell)
|
||||
|
||||
rango = hoja['A1:C5']
|
||||
app.debug(rango.is_cell)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **is_range**
|
||||
|
||||
Verdadero (True) si el objeto es de un rango.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
celda = hoja['A1']
|
||||
app.debug(celda.is_range)
|
||||
|
||||
rango = hoja['A1:C5']
|
||||
app.debug(rango.is_range)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **len**
|
||||
|
||||
Devolver el tamaño del rango en filas y columnas.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
rango = hoja['A1:E100']
|
||||
filas = len(rango)
|
||||
columnas = rango.len_columns
|
||||
app.debug(filas, columnas)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **name**
|
||||
|
||||
Devuelve la dirección de la celda o rango como texto.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
celda = hoja['A1']
|
||||
app.debug(celda.name)
|
||||
|
||||
rango = hoja['A1:C5']
|
||||
app.debug(rango.name)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **next_free**
|
||||
|
||||
Devuelve la siguiente celda libre después de la región actual.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
|
||||
celda_libre = celda.next_free
|
||||
app.debug(celda_libre)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **range_address**
|
||||
|
||||
Devuelve la dirección del rango como una estructura: `com.sun.star.table.CellRangeAddress`
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
rango = hoja['A1:C5']
|
||||
if rango.is_range:
|
||||
app.debug(rango.range_address)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **range_data**
|
||||
|
||||
Devuelve la región actual del rango excepto la primer fila.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
celda = hoja['A1']
|
||||
rango = celda.range_data
|
||||
app.debug(rango)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **sheet**
|
||||
|
||||
Devuelve la hoja padre.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
rango = hoja['A1:C5']
|
||||
|
||||
hoja = rango.sheet
|
||||
app.debug(hoja)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **string**
|
||||
|
||||
Devuelve o establece el contenido de la celda como texto.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
celda = hoja['A1']
|
||||
celda.string = 'Maldito Mundo'
|
||||
app.debug(celda.type, celda.string)
|
||||
|
||||
celda = hoja['A2']
|
||||
celda.string = 12345
|
||||
app.debug(celda.type, celda.string)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **style**
|
||||
|
||||
Devuelve o aplica el estilo de celda.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
rango = hoja['A1:C5']
|
||||
rango.style = 'Good'
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **time**
|
||||
|
||||
Devuelve o establece el contenido de la celda como tiempo.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
celda.time = app.dates.time(10, 11, 12)
|
||||
app.debug(type(celda.time), celda.time)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **type**
|
||||
|
||||
Devuelve el tipo de contenido de la celda: texto, número o formula.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
celda = hoja['A1']
|
||||
app.debug(celda.type)
|
||||
```
|
||||
|
||||
!!! tip "Consejo"
|
||||
|
||||
Asegurese de que la selección siempre sea una sola celda.
|
||||
|
||||
<br>
|
||||
|
||||
### **value**
|
||||
|
||||
Devuelve o establece el valor de la celda, estableciendo el tipo de dato automáticamente.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
celda = hoja['A1']
|
||||
celda.value = 'Soy Texto'
|
||||
app.debug(celda.type, celda.value)
|
||||
|
||||
celda = hoja['A2']
|
||||
celda.value = 12345
|
||||
app.debug(celda.type, celda.value)
|
||||
|
||||
celda = hoja['A3']
|
||||
celda.value = '=RAND()'
|
||||
app.debug(celda.type, celda.value)
|
||||
|
||||
celda = hoja['A4']
|
||||
celda.value = app.dates.date(1974, 1, 15)
|
||||
app.debug(celda.type, celda.value)
|
||||
```
|
||||
|
||||
```sh
|
||||
23/04/2023 19:49:05 - DEBUG - <Enum instance com.sun.star.table.CellContentType ('TEXT')> Soy Texto
|
||||
23/04/2023 19:49:05 - DEBUG - <Enum instance com.sun.star.table.CellContentType ('VALUE')> 12345.0
|
||||
23/04/2023 19:49:05 - DEBUG - <Enum instance com.sun.star.table.CellContentType ('FORMULA')> =RAND()
|
||||
23/04/2023 19:49:05 - DEBUG - <Enum instance com.sun.star.table.CellContentType ('VALUE')> 27044.0
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
### **clear**
|
||||
|
||||
Limpia el rango. Por default solo borra datos. Mire [API CellFlags][1] para más información.
|
||||
|
||||
```python
|
||||
rango.clear()
|
||||
```
|
||||
|
||||
Para borrar todo.
|
||||
```python
|
||||
rango.clear(app.ALL)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **len**
|
||||
|
||||
Devuelve el tamaño en filas y columnas del rango.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
rango = hoja['A1:C100']
|
||||
filas, columnas = rango.len()
|
||||
app.debug(filas, columnas)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **offset**
|
||||
|
||||
Devuelve la celda inmediata a la derecha en la misma fila.
|
||||
|
||||
```py
|
||||
cell = app.active.active['A1']
|
||||
app.debug(cell)
|
||||
cell = cell.offset()
|
||||
app.debug(cell)
|
||||
```
|
||||
|
||||
```
|
||||
23/04/2023 21:22:15 - DEBUG - Cell: $Sheet1.$A$1
|
||||
23/04/2023 21:22:15 - DEBUG - Cell: $Sheet1.$B$1
|
||||
```
|
||||
|
||||
Se puede establecer la distancia a la celda a devolver en filas y columnas.
|
||||
|
||||
```py
|
||||
cell = app.active.active['A1']
|
||||
app.debug(cell)
|
||||
cell = cell.offset(4,2)
|
||||
app.debug(cell)
|
||||
```
|
||||
|
||||
```
|
||||
23/04/2023 21:24:59 - DEBUG - Cell: $Sheet1.$A$1
|
||||
23/04/2023 21:24:59 - DEBUG - Cell: $Sheet1.$C$5
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **to_size**
|
||||
|
||||
Espande el tamaño del rango actual tantas filas y columnas se pasen como argumentos.
|
||||
|
||||
```py
|
||||
cell = app.active.active['A1']
|
||||
app.debug(cell)
|
||||
cell = cell.to_size(10,5)
|
||||
app.debug(cell)
|
||||
```
|
||||
|
||||
```
|
||||
23/04/2023 21:30:56 - DEBUG - Cell: $Sheet1.$A$1
|
||||
23/04/2023 21:30:56 - DEBUG - Range: $Sheet1.$A$1:$E$10
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
[1]: https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1sheet_1_1CellFlags.html
|
|
@ -0,0 +1,394 @@
|
|||
---
|
||||
title: Documento
|
||||
---
|
||||
|
||||
Devolver el documento activo.
|
||||
|
||||
### **active**
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Propiedades
|
||||
|
||||
---
|
||||
|
||||
### **active**
|
||||
|
||||
Devuelve la hoja activa.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc.active
|
||||
app.debug(hoja)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **headers**
|
||||
|
||||
Mostrar u ocultar encabezados de filas y columnas.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
app.msgbox(doc.headers)
|
||||
doc.headers = not doc.headers
|
||||
app.msgbox(doc.headers)
|
||||
doc.headers = not doc.headers
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **names**
|
||||
|
||||
Devolver una tupla con los nombres de todas las hojas.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
nombres = doc.names
|
||||
app.debug(nombres)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **selection**
|
||||
|
||||
Devolver la selección activa.
|
||||
|
||||
!!! warning inline end "Cuidado"
|
||||
|
||||
La selección actual pueden ser muchas cosas diferentes.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
seleccion = doc.selection
|
||||
app.debug(seleccion)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **tabs**
|
||||
|
||||
Mostrar u ocultar las pestañas de las hojas.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
app.msgbox(doc.tabs)
|
||||
doc.tabs = not doc.tabs
|
||||
app.msgbox(doc.tabs)
|
||||
doc.tabs = not doc.tabs
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
### **activate**
|
||||
|
||||
Activar hoja, argumento como objeto.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc[-1]
|
||||
doc.activate(hoja)
|
||||
```
|
||||
|
||||
Activar hoja por nombre.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
doc.activate('Hoja3')
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **copy**
|
||||
|
||||
Copiar hoja dentro del mismo documento.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc[0]
|
||||
|
||||
doc.copy_sheet(hoja, 'Otra hoja')
|
||||
```
|
||||
|
||||
Por nombre.
|
||||
|
||||
```py
|
||||
doc.copy_sheet('Hoja1', 'Nueva Hoja')
|
||||
```
|
||||
|
||||
Si no se establece el nuevo nombre, se generá de forma automática: `nombre + índice`.
|
||||
|
||||
```py
|
||||
doc.copy_sheet(hoja)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **copy_from**
|
||||
|
||||
Copiar hojas de otro documento. Copiar con el mismo nombre.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
documento_origen = app.docs['Contactos.ods']
|
||||
nombre_origen = 'Nombres'
|
||||
|
||||
doc.copy_from(documento_origen, nombre_origen)
|
||||
```
|
||||
|
||||
Copiar con un nuevo nombre.
|
||||
|
||||
```py
|
||||
doc.copy_from(documento_origen, nombre_origen, 'NuevoNombre')
|
||||
```
|
||||
|
||||
Si solo se establece el documento origen, se copian todas las hojas.
|
||||
|
||||
|
||||
```py
|
||||
doc.copy_from(documento_origen)
|
||||
```
|
||||
|
||||
!!! info "Información"
|
||||
|
||||
Si algún nombre de hoja en el origen existe en el destino, se copiará con un nuevo índice concatenado el nombre origen.
|
||||
|
||||
<br>
|
||||
|
||||
### **insert**
|
||||
|
||||
Inserta una nueva hoja, se devuelve la hoja insertada.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc.insert('HojaInsertada')
|
||||
```
|
||||
|
||||
Insertar varias hojas. Devolverá la última insertada.
|
||||
|
||||
```py
|
||||
nombres = ('Enero', 'Febrero', 'Marzo')
|
||||
hoja = doc.insert(nombres)
|
||||
app.debug(hoja)
|
||||
```
|
||||
|
||||
Creando una nueva instancia y asignandola.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
doc['NuevaHoja'] = doc.new_sheet()
|
||||
```
|
||||
|
||||
!!! warning "Cuidado"
|
||||
|
||||
Si la hoja existe, obtendrá un error, verifique siempre que no exista primero.
|
||||
|
||||
<br>
|
||||
|
||||
### **move**
|
||||
|
||||
Mover hojas.
|
||||
|
||||
Pasar la hoja como objeto, de forma predetermianda se mueve a la última posición.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc[0]
|
||||
doc.move(hoja)
|
||||
```
|
||||
|
||||
!!! info "Información"
|
||||
|
||||
Al mover una hoja, cambian sus índices.
|
||||
|
||||
Pasar la hoja por nombre.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
doc.move('Hoja1')
|
||||
```
|
||||
|
||||
Especificar la posición destino.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc[0]
|
||||
doc.move(hoja, 2)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **remove**
|
||||
|
||||
!!! warning "Cuidado"
|
||||
|
||||
Siempre debe haber al menos una hoja en un documento.
|
||||
|
||||
Eliminar hoja por índice.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
sheet = doc[0]
|
||||
|
||||
doc.remove(sheet)
|
||||
```
|
||||
|
||||
Eliminar por nombre.
|
||||
|
||||
```py
|
||||
doc.remove('Hoja2')
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **start_range_selection**
|
||||
|
||||
Permitir al usuario seleccionar un rango. Es necesario pasarle una clase con el nombre que prefiera (`Eventos` es recomendable) con dos métodos para procesar la captura como en el siguiente ejemplo:
|
||||
|
||||
```py
|
||||
class Eventos():
|
||||
|
||||
def __init__(self, doc):
|
||||
self.doc = doc
|
||||
|
||||
def range_selection_done(self, range_selection):
|
||||
if range_selection:
|
||||
app.debug(range_selection)
|
||||
self.doc.remove_range_selection_listener()
|
||||
return
|
||||
|
||||
def range_selection_aborted(self):
|
||||
self.doc.remove_range_selection_listener()
|
||||
return
|
||||
|
||||
|
||||
def main():
|
||||
doc = app.active
|
||||
doc.start_range_selection(Eventos)
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **select**
|
||||
|
||||
Seleccionar una celda o rango.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
cell = doc[0]['A1']
|
||||
doc.select(cell)
|
||||
```
|
||||
|
||||
!!! tip "Consejo"
|
||||
|
||||
**No es necesario** seleccionar celdas o rangos para manipularlos.
|
||||
|
||||
<br>
|
||||
|
||||
### **sort**
|
||||
|
||||
Ordenar hojas en orden alfabetico.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
doc.sort()
|
||||
```
|
||||
|
||||
Ordenar de forma inversa.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
doc.sort(True)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Eventos
|
||||
|
||||
---
|
||||
|
||||
Obtener una tupla con los eventos soportados por el documento.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
nombres = doc.events.names
|
||||
for nombre in nombres:
|
||||
app.debug(nombre)
|
||||
```
|
||||
|
||||
```sh
|
||||
23/04/2023 13:54:10 - DEBUG - OnStartApp
|
||||
23/04/2023 13:54:10 - DEBUG - OnCloseApp
|
||||
23/04/2023 13:54:10 - DEBUG - OnCreate
|
||||
23/04/2023 13:54:10 - DEBUG - OnNew
|
||||
23/04/2023 13:54:10 - DEBUG - OnLoadFinished
|
||||
23/04/2023 13:54:10 - DEBUG - OnLoad
|
||||
23/04/2023 13:54:10 - DEBUG - OnPrepareUnload
|
||||
23/04/2023 13:54:10 - DEBUG - OnUnload
|
||||
23/04/2023 13:54:10 - DEBUG - OnSave
|
||||
23/04/2023 13:54:10 - DEBUG - OnSaveDone
|
||||
23/04/2023 13:54:10 - DEBUG - OnSaveFailed
|
||||
23/04/2023 13:54:10 - DEBUG - OnSaveAs
|
||||
23/04/2023 13:54:10 - DEBUG - OnSaveAsDone
|
||||
23/04/2023 13:54:10 - DEBUG - OnSaveAsFailed
|
||||
23/04/2023 13:54:10 - DEBUG - OnCopyTo
|
||||
23/04/2023 13:54:10 - DEBUG - OnCopyToDone
|
||||
23/04/2023 13:54:10 - DEBUG - OnCopyToFailed
|
||||
23/04/2023 13:54:10 - DEBUG - OnFocus
|
||||
23/04/2023 13:54:10 - DEBUG - OnUnfocus
|
||||
23/04/2023 13:54:10 - DEBUG - OnPrint
|
||||
23/04/2023 13:54:10 - DEBUG - OnViewCreated
|
||||
23/04/2023 13:54:10 - DEBUG - OnPrepareViewClosing
|
||||
23/04/2023 13:54:10 - DEBUG - OnViewClosed
|
||||
23/04/2023 13:54:10 - DEBUG - OnModifyChanged
|
||||
23/04/2023 13:54:10 - DEBUG - OnTitleChanged
|
||||
23/04/2023 13:54:10 - DEBUG - OnVisAreaChanged
|
||||
23/04/2023 13:54:10 - DEBUG - OnModeChanged
|
||||
23/04/2023 13:54:10 - DEBUG - OnStorageChanged
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### Asignar una macro a un evento.
|
||||
|
||||
```py
|
||||
def doc_on_focus(event):
|
||||
app.debug('Documento activado...')
|
||||
return
|
||||
|
||||
|
||||
def main():
|
||||
doc = app.active
|
||||
events = doc.events
|
||||
if 'OnFocus' in events:
|
||||
macro = {'library': 'test', 'name': 'doc_on_focus'}
|
||||
events['OnFocus'] = macro
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### Eliminar la asignación del evento.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
doc.events['OnFocus'] = {}
|
||||
```
|
||||
|
||||
O
|
||||
|
||||
```python
|
||||
doc = app.active
|
||||
doc.events.remove('OnFocus')
|
||||
```
|
||||
|
||||
<br>
|
|
@ -0,0 +1,175 @@
|
|||
## Trabajar con conjuntos de rangos
|
||||
|
||||
---
|
||||
|
||||
### **address**
|
||||
|
||||
Referencia a un rango por su dirección.
|
||||
|
||||
```py
|
||||
rango = rangos['Hoja1.A1:B5']
|
||||
app.debug(rango)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **in**
|
||||
|
||||
Verificar si un rango esta en la colección.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc.active
|
||||
rangos = doc.selection
|
||||
|
||||
resultado = hoja['D5:F10'] in rangos
|
||||
app.debug(resultado)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **index**
|
||||
|
||||
Referencia a un rango por índice.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
rangos = doc.selection
|
||||
|
||||
rango = rangos[1]
|
||||
app.debug(rango)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **iter**
|
||||
|
||||
Iterar entre los rangos.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
for rango in doc.selection:
|
||||
app.debug(rango)
|
||||
```
|
||||
|
||||
```sh
|
||||
20/08/2022 13:27:03 - DEBUG - Range: $Sheet1.$B$4:$D$7
|
||||
20/08/2022 13:27:03 - DEBUG - Range: $Sheet1.$G$10:$H$14
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **len**
|
||||
|
||||
Contar los rangos en la colección.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
contar = len(doc.selection)
|
||||
app.debug(contar)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **selection**
|
||||
|
||||
Obtener una referencia desde la selección actual. Deben de estar seleccionados más de un rango de celdas.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
seleccion = doc.selection
|
||||
app.debug(seleccion)
|
||||
```
|
||||
|
||||
```sh
|
||||
20/08/2022 13:21:17 - DEBUG - Ranges: ('Sheet1.A5:C8', 'Sheet1.E11:F14')
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Propiedades
|
||||
|
||||
---
|
||||
|
||||
### **data**
|
||||
|
||||
Devolver y establecer datos.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
rangos = doc.selection
|
||||
|
||||
datos = rangos.data
|
||||
app.debug(datos)
|
||||
rangos.data = datos
|
||||
```
|
||||
|
||||
!!! warning "Cuidado"
|
||||
|
||||
Al asignar esta propiedad, cada matriz de datos debe tener exactamente el mismo tamaño del rango destino.
|
||||
|
||||
<br>
|
||||
|
||||
### **names**
|
||||
|
||||
Devolver las direcciones de los rangos.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
rangos = doc.selection
|
||||
|
||||
nombres = rangos.names
|
||||
app.debug(nombres)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **style**
|
||||
|
||||
Establecer el estilo de todos los rangos de la colección.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
rangos = doc.selection
|
||||
rangos.style = 'Good'
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
### **add**
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc.active
|
||||
|
||||
rangos = doc.ranges()
|
||||
rangos.add(hoja['A1:B2'])
|
||||
rangos.add(hoja['D5:F10'])
|
||||
app.debug(rangos)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **ranges**
|
||||
|
||||
Crear un nuevo contender de rangos vacío.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
rangos = doc.ranges()
|
||||
app.debug(rangos)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **remove**
|
||||
|
||||
```py
|
||||
rangos.remove(hoja['A1:B2'])
|
||||
```
|
||||
|
||||
<br>
|
|
@ -0,0 +1,354 @@
|
|||
---
|
||||
title: Hojas
|
||||
---
|
||||
|
||||
## Trabajar con hojas
|
||||
|
||||
---
|
||||
|
||||
### Referencia por **índice**
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc[0]
|
||||
app.debug(hoja.name)
|
||||
```
|
||||
|
||||
|
||||
### Referencia por **nombre**
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc['datos']
|
||||
app.debug(hoja.name)
|
||||
```
|
||||
|
||||
### **in**
|
||||
|
||||
Verificar por nombre si una hoja existe.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
existe = 'Hoja2' in doc
|
||||
app.debug(existe)
|
||||
```
|
||||
|
||||
### **len**
|
||||
|
||||
Contar la cantidad de hojas en el documento.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
contar = len(doc)
|
||||
app.debug(contar)
|
||||
```
|
||||
|
||||
### **iter**
|
||||
|
||||
Recorrer todas las hojas.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
for hoja in doc:
|
||||
app.debug(hoja)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Propiedades
|
||||
|
||||
---
|
||||
|
||||
### **code_name**
|
||||
|
||||
Nombre editable y accesible solo por código.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
app.msgbox(hoja.code_name)
|
||||
hoja.code_name = 'datos'
|
||||
app.msgbox(hoja.code_name)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **color**
|
||||
|
||||
Color de la pestaña.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
app.msgbox(hoja.color)
|
||||
|
||||
hoja.color = 'red'
|
||||
app.msgbox(hoja.color)
|
||||
|
||||
# RGB
|
||||
hoja.color = (125, 200, 10)
|
||||
app.msgbox(hoja.color)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **doc**
|
||||
|
||||
Devuelve al documento Calc donde esta la hoja.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
doc = hoja.doc
|
||||
app.debug(doc.title)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **is_protected**
|
||||
|
||||
Devuelve verdadero (True) si la hoja esta protegida
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
esta_protegida = hoja.is_protected
|
||||
app.debug(esta_protegida)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **name**
|
||||
|
||||
Nombre visible y editable por el usuario.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
app.debug(hoja.name)
|
||||
hoja.name = 'Nuevo Nombre'
|
||||
app.debug(hoja.name)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **password**
|
||||
|
||||
Establecer una contraseña.
|
||||
|
||||
!!! tip "Consejo"
|
||||
|
||||
Si la hoja ya esta protegida, aún sin contraseña, este método no tendrá ningún efecto.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
hoja.password = 'siscaloburropanzon'
|
||||
app.debug(hoja.is_protected)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **used_area**
|
||||
|
||||
Referencia al área de usuario actual.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
rango = hoja.used_area
|
||||
app.debug(rango)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **visible**
|
||||
|
||||
Muestra u oculta la hoja
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
app.msgbox(hoja.visible)
|
||||
hoja.visible = not hoja.visible
|
||||
app.msgbox(hoja.visible)
|
||||
hoja.visible = not hoja.visible
|
||||
```
|
||||
|
||||
!!! tip "Cuidado"
|
||||
|
||||
Solo funcionará con dos o más hojas, por que debe haber al menos una visible. Siempre puedes trabajar con todo el documento oculto.
|
||||
|
||||
<br>
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
### **activate**
|
||||
|
||||
Pasar el foco a la hoja.
|
||||
|
||||
!!! tip inline end "Recuerde"
|
||||
|
||||
No es necesario activar una hoja para manipularse.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc[-1]
|
||||
hoja.activate()
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **copy**
|
||||
|
||||
!!! tip "Consejo"
|
||||
|
||||
Siempre valide que no exista el nuevo nombre.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc[0]
|
||||
|
||||
nuevo_nombre = f'{hoja.name}_2'
|
||||
if not nuevo_nombre in doc:
|
||||
hoja.copy(nuevo_nombre)
|
||||
```
|
||||
|
||||
Si no se establece el nuevo nombre, se generá de forma automática: `nombre + índice`.
|
||||
|
||||
```py
|
||||
hoja.copy()
|
||||
```
|
||||
|
||||
### **copy_to**
|
||||
|
||||
Copiar la hoja a otro documento. Se usa el mismo nombre.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc.active
|
||||
|
||||
documento_nuevo = app.docs.new()
|
||||
hoja.copy_to(documento_nuevo)
|
||||
```
|
||||
|
||||
Usar un nuevo nombre.
|
||||
|
||||
```python
|
||||
hoja.copy_to(documento_nuevo, 'Nuevo nombre')
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **move**
|
||||
|
||||
Mover a la última posición.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc[0]
|
||||
hoja.move()
|
||||
```
|
||||
|
||||
Mover a una posición especifica.
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
hoja = doc[0]
|
||||
hoja.move(3)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **remove**
|
||||
|
||||
Remover hoja.
|
||||
|
||||
```py
|
||||
sheet = app.active.active
|
||||
sheet.remove()
|
||||
```
|
||||
|
||||
!!! warning "Cuidado"
|
||||
|
||||
Siempre debe existir al menos una hoja.
|
||||
|
||||
<br>
|
||||
|
||||
### **unprotect**
|
||||
|
||||
Quitar contraseña.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
hoja.password = 'siscaloburropanzon'
|
||||
app.msgbox(hoja.is_protected)
|
||||
|
||||
hoja.unprotect('siscaloburropanzon')
|
||||
app.msgbox(hoja.is_protected)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Eventos
|
||||
|
||||
---
|
||||
|
||||
### **names**
|
||||
|
||||
Obtener una tupla con los eventos soportados por la hoja.
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
|
||||
for nombre in hoja.events.names:
|
||||
app.debug(nombre)
|
||||
```
|
||||
|
||||
```sh
|
||||
23/04/2023 16:59:26 - DEBUG - OnFocus
|
||||
23/04/2023 16:59:26 - DEBUG - OnUnfocus
|
||||
23/04/2023 16:59:26 - DEBUG - OnSelect
|
||||
23/04/2023 16:59:26 - DEBUG - OnDoubleClick
|
||||
23/04/2023 16:59:26 - DEBUG - OnRightClick
|
||||
23/04/2023 16:59:26 - DEBUG - OnChange
|
||||
23/04/2023 16:59:26 - DEBUG - OnCalculate
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### Asignar una macro a un evento.
|
||||
|
||||
```py
|
||||
def on_select(source):
|
||||
app.debug(source.AbsoluteName)
|
||||
return
|
||||
|
||||
|
||||
def main():
|
||||
doc = app.active
|
||||
hoja = doc.active
|
||||
|
||||
if 'OnSelect' in hoja.events:
|
||||
macro = {'library': 'test', 'name': 'on_select'}
|
||||
hoja.events['OnSelect'] = macro
|
||||
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### Eliminar la asignación del evento.
|
||||
|
||||
```py
|
||||
hoja.events['OnSelect'] = {}
|
||||
```
|
||||
|
||||
O
|
||||
|
||||
```py
|
||||
hoja.events.remove('OnFocus')
|
||||
```
|
||||
|
||||
<br>
|
|
@ -0,0 +1,132 @@
|
|||
# Botón de comando (button)
|
||||
|
||||
---
|
||||
|
||||
## Propiedades
|
||||
|
||||
---
|
||||
|
||||
### **type**
|
||||
|
||||
Devuelve el tipo de control.
|
||||
|
||||
```py
|
||||
app.debug(button.type)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **value**
|
||||
|
||||
Devuelve o establece la etiqueta del control.
|
||||
|
||||
```py
|
||||
button.value = 'Cerrar'
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
## Eventos
|
||||
|
||||
---
|
||||
|
||||
### **action**
|
||||
|
||||
Se ejecuta al dar click con el botón primario del ratón y con las teclas ++enter++ y ++"Barra Espaciadora"++ cuando el botón de comando tiene el foco.
|
||||
|
||||
```py
|
||||
def button_action(self, event):
|
||||
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **click**
|
||||
|
||||
Se ejecuta al dar click con cualquier botón del ratón.
|
||||
|
||||
```py
|
||||
def button_click(self, event):
|
||||
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **double_click**
|
||||
|
||||
Se ejecuta al dar doble click con cualquier botón del ratón.
|
||||
|
||||
```py
|
||||
def button_double_click(self, event):
|
||||
|
||||
return
|
||||
```
|
||||
|
||||
## Propiedades pyUNO
|
||||
|
||||
| Nombre | Descripción |
|
||||
| ------ | ----------- |
|
||||
| Align | |
|
||||
| BackgroundColor | |
|
||||
| ContextWritingMode | |
|
||||
| DefaultButton | |
|
||||
| DefaultControl | |
|
||||
| EnableVisible | |
|
||||
| Enabled | |
|
||||
| FocusOnClick | |
|
||||
| FontCharWidth | |
|
||||
| FontCharset | |
|
||||
| FontDescriptor | |
|
||||
| FontEmphasisMark | |
|
||||
| FontFamily | |
|
||||
| FontHeight | |
|
||||
| FontKerning | |
|
||||
| FontName | |
|
||||
| FontOrientation | |
|
||||
| FontPitch | |
|
||||
| FontRelief | |
|
||||
| FontSlant | |
|
||||
| FontStrikeout | |
|
||||
| FontStyleName | |
|
||||
| FontType | |
|
||||
| FontUnderline | |
|
||||
| FontWeight | |
|
||||
| FontWidth | |
|
||||
| FontWordLineMode | |
|
||||
| Graphic | |
|
||||
| Height | |
|
||||
| HelpText | |
|
||||
| HelpURL | |
|
||||
| ImageAlign | |
|
||||
| ImagePosition | |
|
||||
| ImageURL | |
|
||||
| Label | |
|
||||
| MultiLine | |
|
||||
| Name | |
|
||||
| PositionX | |
|
||||
| PositionY | |
|
||||
| Printable | |
|
||||
| PushButtonType | |
|
||||
| ReferenceDevice | |
|
||||
| Repeat | |
|
||||
| RepeatDelay | |
|
||||
| ResourceResolver | |
|
||||
| State | |
|
||||
| Step | |
|
||||
| TabIndex | |
|
||||
| Tabstop | |
|
||||
| Tag | |
|
||||
| TextColor | |
|
||||
| TextLineColor | |
|
||||
| Toggle | |
|
||||
| VerticalAlign | |
|
||||
| Width | |
|
||||
| WritingMode | |
|
||||
|
||||
<br>
|
|
@ -0,0 +1,47 @@
|
|||
# Imagen (image)
|
||||
|
||||
---
|
||||
|
||||
## Propiedades
|
||||
|
||||
---
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
## Eventos
|
||||
|
||||
---
|
||||
|
||||
## Propiedades pyUNO
|
||||
|
||||
| Nombre | Descripción |
|
||||
| ------ | ----------- |
|
||||
| BackgroundColor | |
|
||||
| Border | |
|
||||
| BorderColor | |
|
||||
| ContextWritingMode | |
|
||||
| DefaultControl | |
|
||||
| EnableVisible | |
|
||||
| Enabled | |
|
||||
| Graphic | |
|
||||
| Height | |
|
||||
| HelpText | |
|
||||
| HelpURL | |
|
||||
| ImageURL | |
|
||||
| Name | |
|
||||
| PositionX | |
|
||||
| PositionY | |
|
||||
| Printable | |
|
||||
| ResourceResolver | |
|
||||
| ScaleImage | |
|
||||
| ScaleMode | |
|
||||
| Step | |
|
||||
| TabIndex | |
|
||||
| Tabstop | |
|
||||
| Tag | |
|
||||
| Width | |
|
||||
| WritingMode | |
|
||||
|
||||
<br>
|
|
@ -0,0 +1,267 @@
|
|||
|
||||
# Crear cuadros de diálogo
|
||||
|
||||
### **create**
|
||||
|
||||
---
|
||||
|
||||
#### Desde "Mis Macros"
|
||||
|
||||
Si el cuadro de diálogo esta en la librería `Standard`.
|
||||
|
||||
```py
|
||||
def crear_cuadro_de_dialogo1():
|
||||
propiedades = {
|
||||
'Location': 'user',
|
||||
'Name': 'Dialog1',
|
||||
}
|
||||
dialog = app.dialog.create(propiedades)
|
||||
dialog.open()
|
||||
return
|
||||
```
|
||||
|
||||
Si el cuadro de diálogo esta en otra librería.
|
||||
|
||||
```py
|
||||
def crear_cuadro_de_dialogo2():
|
||||
propiedades = {
|
||||
'Location': 'user',
|
||||
'Library': 'MiAplicacion',
|
||||
'Name': 'Dialog1',
|
||||
}
|
||||
dialog = app.dialog.create(propiedades)
|
||||
dialog.open()
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
#### Dentro de un archivo
|
||||
|
||||
Si el cuadro de diálogo esta en el documento activo en la librería `Standard`.
|
||||
|
||||
```py
|
||||
def crear_cuadro_de_dialogo3():
|
||||
propiedades = {
|
||||
'Location': 'document',
|
||||
'Name': 'Dialog1',
|
||||
}
|
||||
dialog = app.dialog.create(propiedades)
|
||||
dialog.open()
|
||||
return
|
||||
```
|
||||
|
||||
Si el cuadro de diálogo esta en otro documento en la librería `Standard`.
|
||||
|
||||
```py
|
||||
def crear_cuadro_de_dialogo4():
|
||||
documento = app.docs['OtroArchivo.ods']
|
||||
propiedades = {
|
||||
'Location': 'document',
|
||||
'Document': documento,
|
||||
'Name': 'Dialog1',
|
||||
}
|
||||
dialog = app.dialog.create(propiedades)
|
||||
dialog.open()
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
#### 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.
|
||||
|
||||
```py
|
||||
def crear_cuadro_de_dialogo():
|
||||
path = '/home/elmau/Desktop/mi_dialogo.xdl'
|
||||
propiedades = {'Path': path}
|
||||
|
||||
dialog = app.dialog.create(propiedades)
|
||||
dialog.open()
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
#### Crear dinámicamente
|
||||
|
||||
Crear un cuadro de diálogo vacío.
|
||||
|
||||
```py
|
||||
def crear_cuadro_de_dialogo():
|
||||
dialog = app.dialog.create()
|
||||
dialog.open()
|
||||
return
|
||||
```
|
||||
|
||||
Cambiar las propiedades iniciales.
|
||||
|
||||
```py
|
||||
propiedades = dict(
|
||||
Name = 'MiDialogo',
|
||||
Title = 'Maldito Mundo',
|
||||
Width = 200,
|
||||
Height = 100,
|
||||
)
|
||||
|
||||
dialog = app.dialog.create(propiedades)
|
||||
dialog.open()
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
!!! tip Importante
|
||||
|
||||
Cualquier propiedad usada al crear el cuadro de diálogo, debe ser la original del control pyUNO.
|
||||
|
||||
#### Propiedades
|
||||
|
||||
| Nombre | Descripción |
|
||||
| ------ | ----------- |
|
||||
| AllDialogChildren | |
|
||||
| BackgroundColor | Color de fondo |
|
||||
| Closeable | Permite cerrar el cuadro de diálogo con el icono `X` |
|
||||
| Decoration |
|
||||
| DefaultControl |
|
||||
| DesktopAsParent |
|
||||
| DialogSourceURL |
|
||||
| Enabled |
|
||||
| FontCharWidth |
|
||||
| FontCharset |
|
||||
| FontDescriptor |
|
||||
| FontEmphasisMark |
|
||||
| FontFamily |
|
||||
| FontHeight |
|
||||
| FontKerning |
|
||||
| FontName |
|
||||
| FontOrientation |
|
||||
| FontPitch |
|
||||
| FontRelief |
|
||||
| FontSlant |
|
||||
| FontStrikeout |
|
||||
| FontStyleName |
|
||||
| FontType |
|
||||
| FontUnderline |
|
||||
| FontWeight |
|
||||
| FontWidth |
|
||||
| FontWordLineMode |
|
||||
| Graphic |
|
||||
| HScroll |
|
||||
| Height | Altura del control |
|
||||
| HelpText |
|
||||
| HelpURL |
|
||||
| ImageURL |
|
||||
| Moveable |
|
||||
| Name | Nombre del control |
|
||||
| PositionX | Posición en el eje X |
|
||||
| PositionY | Posición en el eje Y |
|
||||
| ResourceResolver |
|
||||
| ScrollHeight |
|
||||
| ScrollLeft |
|
||||
| ScrollTop |
|
||||
| ScrollWidth |
|
||||
| Sizeable | Si el control cambia de tamaño |
|
||||
| Step |
|
||||
| TabIndex |
|
||||
| Tag |
|
||||
| TextColor |
|
||||
| TextLineColor |
|
||||
| Title | Título del cuadro de diálogo |
|
||||
| VScroll | Mostrar barra de desplazamiento vertial |
|
||||
| Width | Ancho del control |
|
||||
|
||||
<br>
|
||||
|
||||
### **add_control**
|
||||
|
||||
---
|
||||
|
||||
Agrega un control al cuadro de diálogo.
|
||||
|
||||
```py
|
||||
propiedades = {
|
||||
'Type': 'label',
|
||||
'Name': 'lbl_info',
|
||||
'Label': 'Esta es una etiqueta.',
|
||||
'Width': 100,
|
||||
'Height': 15,
|
||||
'Border': 1,
|
||||
'X': 5,
|
||||
'Y': 5,
|
||||
}
|
||||
dialog.add_control(propiedades)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Eventos
|
||||
|
||||
---
|
||||
|
||||
Todos los eventos de todos los controles de un cuadro de diálogo se controlan por medio de una clase Python que se pasa a la propiedad `events` del cuadro de diálogo.
|
||||
|
||||
Cada método de esta clase que tenga en su nombre la estructura que corresponde al nombre del control más el nombre del evento, responderá a dicho evento de dicho control.
|
||||
|
||||
`NOMBRE_CONTROL_NOMBRE_EVENTO`
|
||||
|
||||
Ejemplo:
|
||||
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
class Eventos():
|
||||
|
||||
def __init__(self, dialog):
|
||||
self.d = dialog
|
||||
|
||||
def cmd_cerrar_action(self, event):
|
||||
self.d.close(1)
|
||||
return
|
||||
|
||||
def main():
|
||||
propiedades = dict(
|
||||
Name = 'MiDialogo',
|
||||
Title = 'Maldito Mundo',
|
||||
Width = 200,
|
||||
Height = 100,
|
||||
)
|
||||
|
||||
dialog = app.dialog.create(propiedades)
|
||||
dialog.events = Eventos
|
||||
|
||||
propiedades = {
|
||||
'Type': 'button',
|
||||
'Name': 'cmd_cerrar',
|
||||
'Label': 'Cerrar',
|
||||
'Width': 40,
|
||||
'Height': 15,
|
||||
}
|
||||
dialog.add_control(propiedades)
|
||||
dialog.open()
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
Cada control agregado al cuadro de diálogo es instanciado como una propiedad del mismo cuadro de diálogo. En el ejemplo anterior, el botón de comando `cmd_cerrar` es accesible desde cualquier variable que apunte al cuadro de diálogo, en el mismo ejemplo anterior en:
|
||||
|
||||
```py
|
||||
dialog.cmd_cerrar
|
||||
```
|
||||
|
||||
Como en la clase `Eventos` en:
|
||||
```py
|
||||
self.d.cmd_cerrar
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Controles
|
||||
|
||||
---
|
||||
|
||||
#### [Etiqueta (label)](label/)
|
||||
#### [Botón de comando (button)](cmd/)
|
||||
|
||||
<br>
|
|
@ -0,0 +1,101 @@
|
|||
# Etiqueta (label)
|
||||
|
||||
---
|
||||
|
||||
## Propiedades
|
||||
|
||||
---
|
||||
|
||||
### **type**
|
||||
|
||||
Devuelve el tipo de control.
|
||||
|
||||
```py
|
||||
app.debug(label.type)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **value**
|
||||
|
||||
Devuelve o establece la etiqueta del control.
|
||||
|
||||
```py
|
||||
label.value = 'Mi etiqueta'
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
## Eventos
|
||||
|
||||
---
|
||||
|
||||
### **click**
|
||||
|
||||
Se ejecuta al dar click con cualquier botón del ratón.
|
||||
|
||||
```py
|
||||
def label_click(self, event):
|
||||
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Propiedades pyUNO
|
||||
|
||||
|
||||
| Nombre | Descripción |
|
||||
| ------ | ----------- |
|
||||
| Align | |
|
||||
| BackgroundColor | |
|
||||
| Border | |
|
||||
| BorderColor | |
|
||||
| ContextWritingMode | |
|
||||
| DefaultControl | |
|
||||
| EnableVisible | |
|
||||
| Enabled | |
|
||||
| FontCharWidth | |
|
||||
| FontCharset | |
|
||||
| FontDescriptor | |
|
||||
| FontEmphasisMark | |
|
||||
| FontFamily | |
|
||||
| FontHeight | |
|
||||
| FontKerning | |
|
||||
| FontName | |
|
||||
| FontOrientation | |
|
||||
| FontPitch | |
|
||||
| FontRelief | |
|
||||
| FontSlant | |
|
||||
| FontStrikeout | |
|
||||
| FontStyleName | |
|
||||
| FontType | |
|
||||
| FontUnderline | |
|
||||
| FontWeight | |
|
||||
| FontWidth | |
|
||||
| FontWordLineMode | |
|
||||
| Height | |
|
||||
| HelpText | |
|
||||
| HelpURL | |
|
||||
| Label | |
|
||||
| MultiLine | |
|
||||
| Name | |
|
||||
| NoLabel | |
|
||||
| PositionX | |
|
||||
| PositionY | |
|
||||
| Printable | |
|
||||
| ReferenceDevice | |
|
||||
| ResourceResolver | |
|
||||
| Step | |
|
||||
| TabIndex | |
|
||||
| Tabstop | |
|
||||
| Tag | |
|
||||
| TextColor | |
|
||||
| TextLineColor | |
|
||||
| VerticalAlign | |
|
||||
| Width | |
|
||||
| WritingMode | |
|
|
@ -0,0 +1,88 @@
|
|||
# Hipervínculo (link)
|
||||
|
||||
---
|
||||
|
||||
## Propiedades
|
||||
|
||||
### **label**
|
||||
|
||||
Devuelve o establece la etiqueta.
|
||||
|
||||
<br>
|
||||
|
||||
### **url**
|
||||
|
||||
Devuelve o establece el vínculo web.
|
||||
|
||||
<br>
|
||||
|
||||
### **value**
|
||||
|
||||
Devuelve o establece el vínculo web y la etiqueta.
|
||||
|
||||
<br>
|
||||
|
||||
---
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
## Eventos
|
||||
|
||||
---
|
||||
|
||||
## Propiedades pyUNO
|
||||
|
||||
| Nombre | Descripción |
|
||||
| ------ | ----------- |
|
||||
| Align | |
|
||||
| BackgroundColor | |
|
||||
| Border | |
|
||||
| BorderColor | |
|
||||
| ContextWritingMode | |
|
||||
| DefaultControl | |
|
||||
| EnableVisible | |
|
||||
| Enabled | |
|
||||
| FontCharWidth | |
|
||||
| FontCharset | |
|
||||
| FontDescriptor | |
|
||||
| FontEmphasisMark | |
|
||||
| FontFamily | |
|
||||
| FontHeight | |
|
||||
| FontKerning | |
|
||||
| FontName | |
|
||||
| FontOrientation | |
|
||||
| FontPitch | |
|
||||
| FontRelief | |
|
||||
| FontSlant | |
|
||||
| FontStrikeout | |
|
||||
| FontStyleName | |
|
||||
| FontType | |
|
||||
| FontUnderline | |
|
||||
| FontWeight | |
|
||||
| FontWidth | |
|
||||
| FontWordLineMode | |
|
||||
| Height | |
|
||||
| HelpText | |
|
||||
| HelpURL | |
|
||||
| Label | |
|
||||
| MultiLine | |
|
||||
| Name | |
|
||||
| NoLabel | |
|
||||
| PositionX | |
|
||||
| PositionY | |
|
||||
| Printable | |
|
||||
| ResourceResolver | |
|
||||
| Step | |
|
||||
| TabIndex | |
|
||||
| Tabstop | |
|
||||
| Tag | |
|
||||
| TextColor | |
|
||||
| TextLineColor | |
|
||||
| URL | |
|
||||
| VerticalAlign | |
|
||||
| Width | |
|
||||
| WritingMode | |
|
||||
|
||||
<br>
|
|
@ -0,0 +1,17 @@
|
|||
# Control (label)
|
||||
|
||||
---
|
||||
|
||||
## Propiedades
|
||||
|
||||
---
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
## Eventos
|
||||
|
||||
---
|
||||
|
||||
## Propiedades pyUNO
|
|
@ -0,0 +1,112 @@
|
|||
# Cuadro de texto (text)
|
||||
|
||||
---
|
||||
|
||||
## Propiedades
|
||||
|
||||
---
|
||||
|
||||
### **value**
|
||||
|
||||
Establece o recupera el valor del control.
|
||||
|
||||
```py
|
||||
app.debug(text.value)
|
||||
```
|
||||
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
### **set_focus**
|
||||
|
||||
Envía el foco al control.
|
||||
|
||||
<br>
|
||||
|
||||
## Eventos
|
||||
|
||||
---
|
||||
|
||||
### **focus_gained**
|
||||
|
||||
Se produce al recibir el foco.
|
||||
|
||||
<br>
|
||||
|
||||
### **focus_lost**
|
||||
|
||||
Se produce al perder el foco.
|
||||
|
||||
<br>
|
||||
|
||||
### **text_changed**
|
||||
|
||||
Se produce al cambiar el contenido del control.
|
||||
|
||||
<br>
|
||||
|
||||
## Propiedades pyUNO
|
||||
|
||||
| Nombre | Descripción |
|
||||
| ------ | ----------- |
|
||||
| Align | |
|
||||
| AutoHScroll | |
|
||||
| AutoVScroll | |
|
||||
| BackgroundColor | |
|
||||
| Border | |
|
||||
| BorderColor | |
|
||||
| ContextWritingMode | |
|
||||
| DefaultControl | |
|
||||
| EchoChar | |
|
||||
| EnableVisible | |
|
||||
| Enabled | |
|
||||
| FontCharWidth | |
|
||||
| FontCharset | |
|
||||
| FontDescriptor | |
|
||||
| FontEmphasisMark | |
|
||||
| FontFamily | |
|
||||
| FontHeight | |
|
||||
| FontKerning | |
|
||||
| FontName | |
|
||||
| FontOrientation | |
|
||||
| FontPitch | |
|
||||
| FontRelief | |
|
||||
| FontSlant | |
|
||||
| FontStrikeout | |
|
||||
| FontStyleName | |
|
||||
| FontType | |
|
||||
| FontUnderline | |
|
||||
| FontWeight | |
|
||||
| FontWidth | |
|
||||
| FontWordLineMode | |
|
||||
| HScroll | |
|
||||
| HardLineBreaks | |
|
||||
| Height | |
|
||||
| HelpText | |
|
||||
| HelpURL | |
|
||||
| HideInactiveSelection | |
|
||||
| LineEndFormat | |
|
||||
| MaxTextLen | |
|
||||
| MultiLine | |
|
||||
| Name | |
|
||||
| PaintTransparent | |
|
||||
| PositionX | |
|
||||
| PositionY | |
|
||||
| Printable | |
|
||||
| ReadOnly | |
|
||||
| ResourceResolver | |
|
||||
| Step | |
|
||||
| TabIndex | |
|
||||
| Tabstop | |
|
||||
| Tag | |
|
||||
| Text | |
|
||||
| TextColor | |
|
||||
| TextLineColor | |
|
||||
| VScroll | |
|
||||
| VerticalAlign | |
|
||||
| Width | |
|
||||
| WritingMode | |
|
||||
|
||||
<br>
|
|
@ -0,0 +1,123 @@
|
|||
---
|
||||
title: DrawPage
|
||||
---
|
||||
|
||||
La página de dibujo es la capa gráfica donde se agregan las formas y las imágenes en los documentos. La forma de acceder es la misma, solo cambia el tipo de documento.
|
||||
|
||||
## Hoja de Calc
|
||||
|
||||
### **draw_page**
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
pagina_dibujo = hoja.draw_page
|
||||
```
|
||||
|
||||
### **dp**
|
||||
|
||||
Alias de `draw_page`
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
pagina_dibujo = hoja.dp
|
||||
```
|
||||
|
||||
### **shapes**
|
||||
|
||||
Alias de `draw_page`
|
||||
|
||||
```py
|
||||
hoja = app.active.active
|
||||
pagina_dibujo = hoja.shapes
|
||||
```
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
Una vez referenciada, sus métodos y propiedades son las mismas.
|
||||
|
||||
---
|
||||
|
||||
<br>
|
||||
|
||||
## Formas
|
||||
|
||||
---
|
||||
|
||||
### **index**
|
||||
|
||||
Acceso por índice
|
||||
|
||||
```py
|
||||
forma = formas[0]
|
||||
app.debug(forma)
|
||||
```
|
||||
|
||||
Acceso por nombre
|
||||
|
||||
```py
|
||||
forma = formas['Rectangulo1']
|
||||
app.debug(forma)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **in**
|
||||
|
||||
Verificar si una forma esta en la colección por nombre.
|
||||
|
||||
```py
|
||||
app.debug('Shape 1' in formas)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **iter**
|
||||
|
||||
Iterar los elementos gráficos de la página de dibujo.
|
||||
|
||||
```py
|
||||
for f in formas:
|
||||
app.debug(f)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **len**
|
||||
|
||||
Contar los elementos gráficos en la página de dibujo.
|
||||
|
||||
```py
|
||||
app.debug(len(formas))
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
### **add**
|
||||
|
||||
Agrega una nueva forma (un rectángulo) y la devuelve.
|
||||
|
||||
```py
|
||||
forma = formas.add('Rectangle')
|
||||
app.debug(forma)
|
||||
```
|
||||
|
||||
De forma predeterminada la posición será a 1 cm en Y y X y de 3 cm de ancho y alto. Estos valores se pueden modificar al crear la forma. Todas las unidades en milésimas de centímetro.
|
||||
|
||||
```py
|
||||
opciones = dict(
|
||||
Name = 'mi_rectangulo_1',
|
||||
Width = 5000,
|
||||
Height = 2000,
|
||||
X = 3000,
|
||||
Y = 1000,
|
||||
)
|
||||
|
||||
forma = formas.add('Rectangle', opciones)
|
||||
```
|
||||
|
||||
<br>
|
|
@ -0,0 +1,202 @@
|
|||
## Propiedades
|
||||
|
||||
Todas las unidades en milésimas de centímetro.
|
||||
|
||||
---
|
||||
|
||||
### **anchor**
|
||||
|
||||
Anclaje de la forma, por default se agrega a la página.
|
||||
|
||||
#### Anclaje a una celda
|
||||
|
||||
```py
|
||||
celda = hoja['A1']
|
||||
forma.anchor = celda
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **height**
|
||||
|
||||
Alto de la forma.
|
||||
|
||||
```py
|
||||
forma.height = 2000
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **name**
|
||||
|
||||
Devuelve o establece el nombre de la forma.
|
||||
|
||||
```py
|
||||
app.debug(forma.name)
|
||||
forma.name = 'otro_rectangulo'
|
||||
app.debug(forma.name)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **obj**
|
||||
|
||||
**Solo lectura.** Devuelve el objeto original pyUNO.
|
||||
|
||||
```py
|
||||
objeto = forma.obj
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **possize**
|
||||
|
||||
Devuelve o establece la posición y el tamaño de la forma.
|
||||
|
||||
```py
|
||||
posicion_y_tamaño = dict(
|
||||
Width = 5000,
|
||||
Height = 2000,
|
||||
X = 3000,
|
||||
Y = 1000,
|
||||
)
|
||||
forma.possize = posicion_y_tamaño
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **properties**
|
||||
|
||||
Devuelve un diccionario con todas las propiedades de la forma.
|
||||
|
||||
```py
|
||||
for p, v in forma.properties.items():
|
||||
app.debug(f'{p} = {v}')
|
||||
```
|
||||
|
||||
Al establecer solo aplica las que se pasen en un diccionario.
|
||||
|
||||
```py
|
||||
propiedades = dict(
|
||||
LineColor = app.color('red'),
|
||||
LineWidth = 100,
|
||||
)
|
||||
forma.properties = propiedades
|
||||
```
|
||||
|
||||
!!! tip "Atención"
|
||||
|
||||
Aquí hay que usar los nombres "originales" de las propiedades de la forma en el API de LibreOffice.
|
||||
|
||||
<br>
|
||||
|
||||
### **resize_with_cell**
|
||||
|
||||
Si el tamaño de la forma cambia con la celda, solo cuando el anclaje es a una celda.
|
||||
|
||||
```py
|
||||
forma.resize_with_cell = True
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **shape_type**
|
||||
|
||||
**Solo lectura**. Devuelve el tipo de forma.
|
||||
|
||||
```py
|
||||
app.debug(forma.shape_type)
|
||||
```
|
||||
|
||||
```
|
||||
24/04/2023 13:55:32 - DEBUG - com.sun.star.drawing.RectangleShape
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **width**
|
||||
|
||||
Ancho de la forma.
|
||||
|
||||
```py
|
||||
forma.width = 6000
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **x**
|
||||
|
||||
Posición en el eje X.
|
||||
|
||||
```py
|
||||
forma.x = 5000
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **y**
|
||||
|
||||
Posición en el eje Y.
|
||||
|
||||
```py
|
||||
forma.y = 1000
|
||||
```
|
||||
|
||||
## Métodos
|
||||
|
||||
---
|
||||
|
||||
### **clone**
|
||||
|
||||
Clona la imagen en la misma hoja.
|
||||
|
||||
```py
|
||||
imagen.clone()
|
||||
```
|
||||
|
||||
Clona la imagen en otra hoja.
|
||||
|
||||
```py
|
||||
imagen.clone(doc['Hoja5'].draw_page)
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **remove**
|
||||
|
||||
Eliminar la forma.
|
||||
|
||||
```py
|
||||
forma.remove()
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### **save**
|
||||
|
||||
Guarda la imagen en disco. Si no se pasa ningún argumento, toma la ruta del documento y el nombre de la imagen.
|
||||
|
||||
!!! tip inline end "Atención"
|
||||
|
||||
El documento ya debe estar guardado
|
||||
|
||||
```py
|
||||
imagen.save()
|
||||
```
|
||||
|
||||
Podemos pasar una ruta diferente, seguira tomando el nombre de la imagen.
|
||||
|
||||
```py
|
||||
ruta = '/home/elmau/imagenes'
|
||||
imagen.save(ruta)
|
||||
```
|
||||
|
||||
Podemos cambiar el nombre.
|
||||
|
||||
```py
|
||||
ruta = '/home/elmau/imagenes'
|
||||
name = f'{hoja.name}_nuevo_nombre'
|
||||
imagen.save(path, name)
|
||||
```
|
||||
|
||||
<br>
|
|
@ -0,0 +1,155 @@
|
|||
---
|
||||
title: Índice
|
||||
---
|
||||
|
||||
# Ejemplos reales de uso
|
||||
|
||||
---
|
||||
|
||||
## Calc
|
||||
|
||||
---
|
||||
|
||||
### Solicitar precios
|
||||
|
||||
Consultar datos en json a una página web y vaciarlos en una hoja.
|
||||
|
||||
=== "EasyMacro"
|
||||
|
||||
```py
|
||||
import easymacro as app
|
||||
|
||||
def obtener_precios():
|
||||
URL = 'https://api.binance.com/api/v3/ticker/price'
|
||||
respuesta = app.url.get(URL)
|
||||
if respuesta.status_code == 200:
|
||||
datos = respuesta.json()
|
||||
app.active.active['A1'].dict = datos
|
||||
return
|
||||
```
|
||||
|
||||
=== "Sin EasyMacro"
|
||||
|
||||
```py
|
||||
import uno
|
||||
import json
|
||||
from urllib import request
|
||||
|
||||
def obtener_precios():
|
||||
URL = 'https://api.binance.com/api/v3/ticker/price'
|
||||
data = json.loads(request.urlopen(URL).read().decode())
|
||||
|
||||
doc = XSCRIPTCONTEXT.getDocument()
|
||||
sheet = doc.CurrentController.ActiveSheet
|
||||
|
||||
sheet[0,0].String = 'symbol'
|
||||
sheet[0,1].String = 'price'
|
||||
|
||||
for i, row in enumerate(data):
|
||||
sheet[i + 1,0].String = row['symbol']
|
||||
sheet[i + 1,1].Value = float(row['price'])
|
||||
|
||||
return
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### Clonar imagenes
|
||||
|
||||
Clonar todas las imagenes de una hoja a otra.
|
||||
|
||||
=== "EasyMacro"
|
||||
|
||||
```py
|
||||
doc = app.active
|
||||
for image in doc[0].dp:
|
||||
if image.is_image:
|
||||
image.clone(doc[1].dp)
|
||||
```
|
||||
|
||||
=== "Sin EasyMacro"
|
||||
|
||||
```py
|
||||
import uno
|
||||
import io
|
||||
import unohelper
|
||||
from com.sun.star.io import IOException, XOutputStream
|
||||
from com.sun.star.beans import PropertyValue
|
||||
|
||||
|
||||
CTX = uno.getComponentContext()
|
||||
SM = CTX.getServiceManager()
|
||||
|
||||
|
||||
class LOShape():
|
||||
|
||||
def __init__(self, shape):
|
||||
self._shape = shape
|
||||
|
||||
class OutputStream(unohelper.Base, XOutputStream):
|
||||
|
||||
def __init__(self):
|
||||
self._buffer = b''
|
||||
self.closed = 0
|
||||
|
||||
@property
|
||||
def buffer(self):
|
||||
return self._buffer
|
||||
|
||||
def closeOutput(self):
|
||||
self.closed = 1
|
||||
|
||||
def writeBytes(self, seq):
|
||||
if seq.value:
|
||||
self._buffer = seq.value
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def clone_image(self, doc, to_sheet):
|
||||
stream = self._shape.GraphicStream
|
||||
buffer = self.OutputStream()
|
||||
size, data = stream.readBytes(buffer, stream.available())
|
||||
|
||||
stream = SM.createInstanceWithContext('com.sun.star.io.SequenceInputStream', CTX)
|
||||
stream.initialize((data,))
|
||||
|
||||
image = doc.createInstance('com.sun.star.drawing.GraphicObjectShape')
|
||||
gp = SM.createInstance('com.sun.star.graphic.GraphicProvider')
|
||||
properties = (PropertyValue(Name='InputStream', Value=stream),)
|
||||
image.Graphic = gp.queryGraphic(properties)
|
||||
to_sheet.DrawPage.add(image)
|
||||
image.Size = self._shape.Size
|
||||
image.Position = self._shape.Position
|
||||
return
|
||||
|
||||
def clone_shape(self, doc, to_sheet):
|
||||
for p in self._shape.CustomShapeGeometry:
|
||||
if p.Name == 'Type':
|
||||
type_shape = p.Value.title()
|
||||
|
||||
service = f'com.sun.star.drawing.{type_shape}Shape'
|
||||
shape = doc.createInstance(service)
|
||||
shape.Size = self._shape.Size
|
||||
shape.Position = self._shape.Position
|
||||
to_sheet.DrawPage.add(shape)
|
||||
return
|
||||
|
||||
|
||||
def main():
|
||||
IMAGE = 'com.sun.star.drawing.GraphicObjectShape'
|
||||
SHAPE = 'com.sun.star.drawing.CustomShape'
|
||||
|
||||
doc = XSCRIPTCONTEXT.getDocument()
|
||||
source = doc.CurrentController.ActiveSheet
|
||||
target = doc.Sheets[1]
|
||||
|
||||
for shape in source.DrawPage:
|
||||
s = LOShape(shape)
|
||||
if shape.ShapeType == IMAGE:
|
||||
s.clone_image(doc, target)
|
||||
elif shape.ShapeType == SHAPE:
|
||||
s.clone_shape(doc, tar
|
||||
```
|
||||
|
||||
<br>
|
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 380 B |
|
@ -24,9 +24,26 @@ nav:
|
|||
- docs/index.md
|
||||
- Propiedades: docs/properties.md
|
||||
- Métodos: docs/methods.md
|
||||
- Calc:
|
||||
- calc/index.md
|
||||
- Hojas: calc/sheets.md
|
||||
- Rangos: calc/ranges.md
|
||||
- Celdas: calc/cells.md
|
||||
- Página de dibujo:
|
||||
- dp/drawpage.md
|
||||
- Formas: dp/shapes.md
|
||||
- Cuadros de diálogo:
|
||||
- dialogs/index.md
|
||||
- Etiqueta: dialogs/label.md
|
||||
- Botón de comando: dialogs/cmd.md
|
||||
- Cuadro de texto: dialogs/text.md
|
||||
- Hipervínculo: dialogs/link.md
|
||||
- Imagen: dialogs/image.md
|
||||
- Ejemplos de uso:
|
||||
- examples/index.md
|
||||
theme:
|
||||
name: material
|
||||
locale: es
|
||||
locale: en
|
||||
font: false
|
||||
highlightjs: true
|
||||
palette:
|
||||
|
@ -45,12 +62,15 @@ markdown_extensions:
|
|||
pygments_lang_class: true
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.snippets
|
||||
- pymdownx.superfences
|
||||
#~ extra:
|
||||
#~ alternate:
|
||||
#~ - name: Español
|
||||
#~ link: /
|
||||
#~ lang: es
|
||||
#~ - name: English
|
||||
#~ link: /en/
|
||||
#~ lang: en
|
||||
- pymdownx.tabbed:
|
||||
alternate_style: true
|
||||
- tables
|
||||
- pymdownx.keys
|
||||
extra:
|
||||
alternate:
|
||||
- name: English
|
||||
link: /easymacro
|
||||
lang: en
|
||||
- name: Español
|
||||
link: /easymacro/langs/es
|
||||
lang: es
|
|
@ -1,13 +1,35 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# ~ easymacro - for easily develop macros in LibreOffice
|
||||
# ~ Copyright (C) 2020-2023 Mauricio Baeza (elmau)
|
||||
|
||||
# ~ This program is free software: you can redistribute it and/or modify it
|
||||
# ~ under the terms of the GNU General Public License as published by the
|
||||
# ~ Free Software Foundation, either version 3 of the License, or (at your
|
||||
# ~ option) any later version.
|
||||
|
||||
# ~ This program is distributed in the hope that it will be useful, but
|
||||
# ~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# ~ for more details.
|
||||
|
||||
# ~ You should have received a copy of the GNU General Public License along
|
||||
# ~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .easymain import *
|
||||
from .easydialog import *
|
||||
from .easytools import *
|
||||
from .constants import *
|
||||
from .easydocs import LODocuments
|
||||
|
||||
from .easydrawpage import LOGalleries
|
||||
|
||||
|
||||
__version__ = '0.5.0'
|
||||
__author__ = 'Mauricio Baeza (elMau)'
|
||||
|
||||
|
||||
def __getattr__(name):
|
||||
classes = {
|
||||
'active': LODocuments().active,
|
||||
|
@ -29,7 +51,6 @@ def __getattr__(name):
|
|||
'menus': LOMenus(),
|
||||
'paths': Paths,
|
||||
'url': URL,
|
||||
'selection': LODocuments().active.selection,
|
||||
'set_config': set_app_config,
|
||||
'shell': Shell,
|
||||
'shortcuts': LOShortCuts(),
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# ~ Is de sum of:
|
||||
# ~ https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1sheet_1_1CellFlags.html
|
||||
|
||||
from com.sun.star.sheet import CellFlags
|
||||
from .easyuno import BitmapMode, CellContentType, FillStyle, LineStyle
|
||||
|
||||
|
||||
__all__ = [
|
||||
'ALL',
|
||||
'ONLY_DATA',
|
||||
'BitmapMode',
|
||||
'CellContentType',
|
||||
'FillStyle',
|
||||
'LineStyle',
|
||||
]
|
||||
|
||||
# ~ VALUE, DATETIME, STRING, ANNOTATION, FORMULA
|
||||
ONLY_DATA = 31
|
||||
|
||||
ALL = 1023
|
||||
|
||||
SECONDS_DAY = 86400
|
|
@ -1,6 +1,61 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from .easydoc import LODocument
|
||||
from .easymain import BaseObject
|
||||
|
||||
|
||||
class LOBaseSource(BaseObject):
|
||||
_type = 'Base Source'
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self._type}:'
|
||||
|
||||
|
||||
# ~ main_form = frm_container.component.getDrawPage.getforms.getbyindex(0)
|
||||
class LOBaseForm(BaseObject):
|
||||
_type = 'Base Form'
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self._type}: {self.name}'
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.obj.Name
|
||||
|
||||
def open(self):
|
||||
self.obj.open()
|
||||
return
|
||||
|
||||
def close(self):
|
||||
return self.obj.close()
|
||||
|
||||
|
||||
class LOBaseForms(BaseObject):
|
||||
_type = 'Base Forms'
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return f'Base Forms'
|
||||
|
||||
def __len__(self):
|
||||
"""Count forms"""
|
||||
return self.obj.Count
|
||||
|
||||
def __contains__(self, item):
|
||||
"""Contains"""
|
||||
return item in self.obj
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Index access"""
|
||||
return LOBaseForm(self.obj[index])
|
||||
|
||||
|
||||
class LOBase(LODocument):
|
||||
|
@ -8,3 +63,10 @@ class LOBase(LODocument):
|
|||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return f'Base: {self.title}'
|
||||
|
||||
@property
|
||||
def forms(self):
|
||||
return LOBaseForms(self.obj.FormDocuments)
|
|
@ -4,11 +4,8 @@ import datetime
|
|||
from decimal import Decimal
|
||||
from typing import Any, Union
|
||||
|
||||
from com.sun.star.sheet import CellFlags
|
||||
from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA
|
||||
|
||||
from .easymain import (log, DATE_OFFSET,
|
||||
BaseObject, Color,
|
||||
BaseObject, Color, LOMain,
|
||||
dict_to_property, run_in_thread, set_properties
|
||||
)
|
||||
from .easydoc import LODocument
|
||||
|
@ -16,83 +13,16 @@ from .easyevents import EventsRangeSelectionListener, LOEvents
|
|||
from .easyshape import LOShapes, LOShape
|
||||
from .easydrawpage import LODrawPage
|
||||
from .easyforms import LOForms
|
||||
from .easystyles import LOStyleFamilies
|
||||
from .constants import ONLY_DATA, SECONDS_DAY, CellContentType
|
||||
|
||||
|
||||
SECONDS_DAY = 60 * 60 * 24
|
||||
ONLY_VALUES = CellFlags.VALUE + CellFlags.DATETIME + CellFlags.STRING
|
||||
|
||||
|
||||
class LOCellStyle():
|
||||
|
||||
def __init__(self, obj):
|
||||
self._obj = obj
|
||||
|
||||
def __str__(self):
|
||||
return f'CellStyle: {self.name}'
|
||||
|
||||
@property
|
||||
def obj(self):
|
||||
return self._obj
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.obj.Name
|
||||
|
||||
@property
|
||||
def properties(self):
|
||||
properties = self.obj.PropertySetInfo.Properties
|
||||
data = {p.Name: getattr(self.obj, p.Name) for p in properties}
|
||||
return data
|
||||
@properties.setter
|
||||
def properties(self, values):
|
||||
set_properties(self.obj, values)
|
||||
|
||||
|
||||
class LOCellStyles():
|
||||
|
||||
def __init__(self, obj, doc):
|
||||
self._obj = obj
|
||||
self._doc = doc
|
||||
|
||||
def __len__(self):
|
||||
return len(self.obj)
|
||||
|
||||
def __getitem__(self, index):
|
||||
return LOCellStyle(self.obj[index])
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.obj[key] = value
|
||||
|
||||
def __delitem__(self, key):
|
||||
if not isinstance(key, str):
|
||||
key = key.Name
|
||||
del self.obj[key]
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self.obj
|
||||
|
||||
@property
|
||||
def obj(self):
|
||||
return self._obj
|
||||
|
||||
@property
|
||||
def names(self):
|
||||
return self.obj.ElementNames
|
||||
|
||||
def new(self, name: str):
|
||||
obj = self._doc.create_instance('com.sun.star.style.CellStyle')
|
||||
self.obj[name] = obj
|
||||
return LOCellStyle(obj)
|
||||
|
||||
|
||||
# ~ IsFiltered,
|
||||
# ~ IsManualPageBreak,
|
||||
# ~ IsStartOfNewPage
|
||||
class LOSheetRows():
|
||||
|
||||
def __init__(self, sheet, obj):
|
||||
def __init__(self, sheet, obj, range_address):
|
||||
self._sheet = sheet
|
||||
self._obj = obj
|
||||
self._ra = range_address
|
||||
|
||||
def __getitem__(self, index):
|
||||
if isinstance(index, int):
|
||||
|
@ -106,7 +36,8 @@ class LOSheetRows():
|
|||
return self.obj.Count
|
||||
|
||||
def __str__(self):
|
||||
return self.obj.Name
|
||||
name = f'Rows: {self._ra.StartRow} to {self._ra.EndRow}'
|
||||
return name
|
||||
|
||||
@property
|
||||
def obj(self):
|
||||
|
@ -119,6 +50,27 @@ class LOSheetRows():
|
|||
def visible(self, value):
|
||||
self._obj.IsVisible = value
|
||||
|
||||
@property
|
||||
def is_filtered(self):
|
||||
return self._obj.IsFiltered
|
||||
@is_filtered.setter
|
||||
def is_filtered(self, value):
|
||||
self._obj.IsFiltered = value
|
||||
|
||||
@property
|
||||
def is_manual_page_break(self):
|
||||
return self._obj.IsManualPageBreak
|
||||
@is_manual_page_break.setter
|
||||
def is_manual_page_break(self, value):
|
||||
self._obj.IsManualPageBreak = value
|
||||
|
||||
@property
|
||||
def is_start_of_new_page(self):
|
||||
return self._obj.IsStartOfNewPage
|
||||
@is_start_of_new_page.setter
|
||||
def is_start_of_new_page(self, value):
|
||||
self._obj.IsStartOfNewPage = value
|
||||
|
||||
@property
|
||||
def color(self):
|
||||
return self.obj.CellBackColor
|
||||
|
@ -239,6 +191,7 @@ class LOCalcRange():
|
|||
def __init__(self, obj):
|
||||
self._obj = obj
|
||||
self._is_cell = obj.ImplementationName == self.CELL
|
||||
self._shape = None
|
||||
|
||||
def __contains__(self, rango):
|
||||
if isinstance(rango, LOCalcRange):
|
||||
|
@ -274,9 +227,7 @@ class LOCalcRange():
|
|||
pass
|
||||
|
||||
def __len__(self):
|
||||
ra = self.range_address
|
||||
rows = ra.EndRow - ra.StartRow + 1
|
||||
return rows
|
||||
return self.obj.Rows.Count
|
||||
|
||||
def __str__(self):
|
||||
s = f'Range: {self.name}'
|
||||
|
@ -303,6 +254,7 @@ class LOCalcRange():
|
|||
|
||||
@property
|
||||
def is_range(self):
|
||||
"""True if range is not cell"""
|
||||
return not self._is_cell
|
||||
|
||||
@property
|
||||
|
@ -433,11 +385,11 @@ class LOCalcRange():
|
|||
def value(self):
|
||||
"""Get or set value, automatically get type data"""
|
||||
v = None
|
||||
if self.type == VALUE:
|
||||
if self.type == CellContentType.VALUE:
|
||||
v = self.float
|
||||
elif self.type == TEXT:
|
||||
elif self.type == CellContentType.TEXT:
|
||||
v = self.string
|
||||
elif self.type == FORMULA:
|
||||
elif self.type == CellContentType.FORMULA:
|
||||
v = self.formula
|
||||
return v
|
||||
@value.setter
|
||||
|
@ -523,6 +475,17 @@ class LOCalcRange():
|
|||
col2 = ra.EndColumn + 1
|
||||
return LOCalcRange(self.sheet[row1:row2, col1:col2].obj)
|
||||
|
||||
@property
|
||||
def shape(self):
|
||||
return self._shape
|
||||
@shape.setter
|
||||
def shape(self, shape):
|
||||
shape.anchor = self
|
||||
shape.resize_with_cell = True
|
||||
shape.possize = self.possize
|
||||
return
|
||||
|
||||
# ~ Fix
|
||||
@property
|
||||
def array_formula(self):
|
||||
return self.obj.ArrayFormula
|
||||
|
@ -535,12 +498,10 @@ class LOCalcRange():
|
|||
cursor = self.obj.Spreadsheet.createCursorByRange(self.obj)
|
||||
return cursor
|
||||
|
||||
# ~ To doc
|
||||
@property
|
||||
def position(self):
|
||||
return self.obj.Position
|
||||
|
||||
# ~ To doc
|
||||
@property
|
||||
def size(self):
|
||||
return self.obj.Size
|
||||
|
@ -561,20 +522,19 @@ class LOCalcRange():
|
|||
def y(self):
|
||||
return self.obj.Position.Y
|
||||
|
||||
# ~ To doc
|
||||
@property
|
||||
def possize(self):
|
||||
data = {
|
||||
'Width': self.size.Width,
|
||||
'Height': self.size.Height,
|
||||
'X': self.position.X,
|
||||
'Y': self.position.Y,
|
||||
'Width': self.width,
|
||||
'Height': self.height,
|
||||
'X': self.x,
|
||||
'Y': self.y,
|
||||
}
|
||||
return data
|
||||
|
||||
@property
|
||||
def rows(self):
|
||||
return LOSheetRows(self.sheet, self.obj.Rows)
|
||||
return LOSheetRows(self.sheet, self.obj.Rows, self.range_address)
|
||||
|
||||
@property
|
||||
def row(self):
|
||||
|
@ -585,24 +545,47 @@ class LOCalcRange():
|
|||
c2 = ra.EndColumn + 1
|
||||
return LOCalcRange(self.sheet[r1:r2, c1:c2].obj)
|
||||
|
||||
def clear(self, what: int=ONLY_VALUES):
|
||||
def clear(self, what: int=ONLY_DATA):
|
||||
"""Clear contents"""
|
||||
# ~ http://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1sheet_1_1CellFlags.html
|
||||
self.obj.clearContents(what)
|
||||
return
|
||||
|
||||
def offset(self, rows=0, cols=1):
|
||||
"""Get cell offset"""
|
||||
ra = self.range_address
|
||||
col = ra.EndColumn + cols
|
||||
row = ra.EndRow + rows
|
||||
return LOCalcRange(self.sheet[row, col].obj)
|
||||
|
||||
def to_size(self, cols: int, rows: int):
|
||||
"""Expande range to size"""
|
||||
cursor = self.cursor
|
||||
cursor.collapseToSize(cols, rows)
|
||||
rango = self.obj.Spreadsheet[cursor.AbsoluteName]
|
||||
return LOCalcRange(rango)
|
||||
|
||||
def len(self):
|
||||
"""Get size of range in rows and columns"""
|
||||
ra = self.range_address
|
||||
rows = ra.EndRow - ra.StartRow + 1
|
||||
cols = ra.EndColumn - ra.StartColumn + 1
|
||||
return rows, cols
|
||||
|
||||
def select(self):
|
||||
""" """
|
||||
self.doc.select(self.obj)
|
||||
return
|
||||
|
||||
def to_image(self):
|
||||
""" """
|
||||
self.select()
|
||||
self.doc.copy()
|
||||
args = {'SelectedFormat': 141}
|
||||
url = 'ClipboardFormatItems'
|
||||
LOMain.dispatch(self.doc.frame, url, args)
|
||||
return self.sheet.shapes[-1]
|
||||
|
||||
|
||||
class LOCalcSheet(BaseObject):
|
||||
|
||||
|
@ -623,10 +606,12 @@ class LOCalcSheet(BaseObject):
|
|||
|
||||
@property
|
||||
def doc(self):
|
||||
"""Get parent doc"""
|
||||
return LOCalc(self.obj.DrawPage.Forms.Parent)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Get name sheet"""
|
||||
return self._obj.Name
|
||||
@name.setter
|
||||
def name(self, value):
|
||||
|
@ -634,6 +619,7 @@ class LOCalcSheet(BaseObject):
|
|||
|
||||
@property
|
||||
def code_name(self):
|
||||
"""Get code name"""
|
||||
return self._obj.CodeName
|
||||
@code_name.setter
|
||||
def code_name(self, value):
|
||||
|
@ -641,6 +627,7 @@ class LOCalcSheet(BaseObject):
|
|||
|
||||
@property
|
||||
def visible(self):
|
||||
"""Get visible"""
|
||||
return self._obj.IsVisible
|
||||
@visible.setter
|
||||
def visible(self, value):
|
||||
|
@ -648,6 +635,7 @@ class LOCalcSheet(BaseObject):
|
|||
|
||||
@property
|
||||
def color(self):
|
||||
"""Get color tab"""
|
||||
return self._obj.TabColor
|
||||
@color.setter
|
||||
def color(self, value):
|
||||
|
@ -655,12 +643,14 @@ class LOCalcSheet(BaseObject):
|
|||
|
||||
@property
|
||||
def used_area(self):
|
||||
"""Get used area"""
|
||||
cursor = self.create_cursor()
|
||||
cursor.gotoEndOfUsedArea(True)
|
||||
return self[cursor.AbsoluteName]
|
||||
|
||||
@property
|
||||
def is_protected(self):
|
||||
"""Get is protected"""
|
||||
return self._obj.isProtected()
|
||||
|
||||
@property
|
||||
|
@ -668,10 +658,12 @@ class LOCalcSheet(BaseObject):
|
|||
return ''
|
||||
@password.setter
|
||||
def password(self, value):
|
||||
"""Set password protect"""
|
||||
self.obj.protect(value)
|
||||
|
||||
@property
|
||||
def draw_page(self):
|
||||
"""Get draw page"""
|
||||
return LODrawPage(self.obj.DrawPage)
|
||||
@property
|
||||
def dp(self):
|
||||
|
@ -686,6 +678,7 @@ class LOCalcSheet(BaseObject):
|
|||
|
||||
@property
|
||||
def events(self):
|
||||
"""Get events"""
|
||||
return LOEvents(self.obj.Events)
|
||||
|
||||
@property
|
||||
|
@ -701,6 +694,7 @@ class LOCalcSheet(BaseObject):
|
|||
return
|
||||
|
||||
def unprotect(self, value):
|
||||
"""Unproyect sheet"""
|
||||
try:
|
||||
self.obj.unprotect(value)
|
||||
return True
|
||||
|
@ -709,6 +703,7 @@ class LOCalcSheet(BaseObject):
|
|||
return False
|
||||
|
||||
def move(self, pos: int=-1):
|
||||
"""Move sheet"""
|
||||
index = pos
|
||||
if pos < 0:
|
||||
index = len(self.doc)
|
||||
|
@ -716,10 +711,12 @@ class LOCalcSheet(BaseObject):
|
|||
return
|
||||
|
||||
def remove(self):
|
||||
"""Auto remove"""
|
||||
self.doc.remove(self.name)
|
||||
return
|
||||
|
||||
def copy(self, new_name: str='', pos: int=-1):
|
||||
"""Copy sheet"""
|
||||
index = pos
|
||||
if pos < 0:
|
||||
index = len(self.doc)
|
||||
|
@ -727,8 +724,7 @@ class LOCalcSheet(BaseObject):
|
|||
return new_sheet
|
||||
|
||||
def copy_to(self, doc: Any, target: str='', pos: int=-1):
|
||||
"""Copy sheet to other document.
|
||||
"""
|
||||
"""Copy sheet to other document."""
|
||||
index = pos
|
||||
if pos < 0:
|
||||
index = len(doc)
|
||||
|
@ -808,6 +804,10 @@ class LOCalc(LODocument):
|
|||
"""Insert new sheet"""
|
||||
self._sheets[key] = value
|
||||
|
||||
def __delitem__(self, key):
|
||||
sheet = self._sheets[key]
|
||||
self._sheets.removeByName(sheet.Name)
|
||||
|
||||
def __len__(self):
|
||||
"""Count sheets"""
|
||||
return self._sheets.Count
|
||||
|
@ -891,6 +891,11 @@ class LOCalc(LODocument):
|
|||
"""Get class events"""
|
||||
return LOEvents(self.obj.Events)
|
||||
|
||||
@property
|
||||
def styles(self):
|
||||
ci = self.obj.createInstance
|
||||
return LOStyleFamilies(self.obj.StyleFamilies, ci)
|
||||
|
||||
def ranges(self):
|
||||
"""Create ranges container"""
|
||||
obj = self._create_instance('com.sun.star.sheet.SheetCellRanges')
|
||||
|
@ -909,7 +914,6 @@ class LOCalc(LODocument):
|
|||
self._cc.select(obj)
|
||||
return
|
||||
|
||||
@run_in_thread
|
||||
def start_range_selection(self, controllers: Any, args: dict={}):
|
||||
"""Start select range selection by user
|
||||
|
||||
|
@ -1064,5 +1068,4 @@ class LOCalc(LODocument):
|
|||
return self.cell_styles
|
||||
@property
|
||||
def cell_styles(self):
|
||||
obj = self.obj.StyleFamilies['CellStyles']
|
||||
return LOCellStyles(obj, self)
|
||||
return self.styles['CellStyles']
|
||||
|
|
|
@ -9,7 +9,7 @@ from .easydocs import LODocuments
|
|||
from .easymain import (log, TITLE,
|
||||
BaseObject, Color,
|
||||
create_instance, set_properties)
|
||||
from .easytools import _, LOInspect, Paths, Services
|
||||
from .easytools import _, LOInspect, Paths, Services, debug, mri
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
@ -18,16 +18,18 @@ __all__ = [
|
|||
]
|
||||
|
||||
|
||||
COLOR_ON_FOCUS = Color()('LightYellow')
|
||||
# ~ COLOR_ON_FOCUS = Color()('LightYellow')
|
||||
SEPARATION = 5
|
||||
MODELS = {
|
||||
'label': 'com.sun.star.awt.UnoControlFixedTextModel',
|
||||
'text': 'com.sun.star.awt.UnoControlEditModel',
|
||||
'button': 'com.sun.star.awt.UnoControlButtonModel',
|
||||
'link': 'com.sun.star.awt.UnoControlFixedHyperlinkModel',
|
||||
'image': 'com.sun.star.awt.UnoControlImageControlModel',
|
||||
'pattern': 'com.sun.star.awt.UnoControlPatternFieldModel',
|
||||
# ~ ToDo
|
||||
'radio': 'com.sun.star.awt.UnoControlRadioButtonModel',
|
||||
'checkbox': 'com.sun.star.awt.UnoControlCheckBoxModel',
|
||||
'image': 'com.sun.star.awt.UnoControlImageControlModel',
|
||||
'listbox': 'com.sun.star.awt.UnoControlListBoxModel',
|
||||
'roadmap': 'com.sun.star.awt.UnoControlRoadmapModel',
|
||||
'tree': 'com.sun.star.awt.tree.TreeControlModel',
|
||||
|
@ -43,6 +45,7 @@ TYPE_CONTROL = {
|
|||
'stardiv.Toolkit.UnoFixedTextControl': 'label',
|
||||
'stardiv.Toolkit.UnoEditControl': 'text',
|
||||
'stardiv.Toolkit.UnoButtonControl': 'button',
|
||||
'stardiv.Toolkit.UnoImageControlControl': 'image',
|
||||
}
|
||||
|
||||
IMPLEMENTATIONS = {
|
||||
|
@ -50,6 +53,7 @@ IMPLEMENTATIONS = {
|
|||
'link': 'stardiv.Toolkit.UnoFixedHyperlinkControl',
|
||||
'roadmap': 'stardiv.Toolkit.UnoRoadmapControl',
|
||||
'pages': 'stardiv.Toolkit.UnoMultiPageControl',
|
||||
'text': 'stardiv.Toolkit.UnoEditControl',
|
||||
}
|
||||
|
||||
|
||||
|
@ -57,8 +61,9 @@ def add_listeners(events, control):
|
|||
name = control.Model.Name
|
||||
listeners = {
|
||||
'addActionListener': EventsButton,
|
||||
# ~ 'addMouseListener': EventsMouse,
|
||||
# ~ 'addFocusListener': EventsFocus,
|
||||
'addMouseListener': EventsMouse,
|
||||
'addFocusListener': EventsFocus,
|
||||
'addTextListener': EventsText,
|
||||
# ~ 'addItemListener': EventsItem,
|
||||
# ~ 'addKeyListener': EventsKey,
|
||||
# ~ 'addTabListener': EventsTab,
|
||||
|
@ -72,6 +77,9 @@ def add_listeners(events, control):
|
|||
is_roadmap = control.ImplementationName == IMPLEMENTATIONS['roadmap']
|
||||
is_pages = control.ImplementationName == IMPLEMENTATIONS['pages']
|
||||
|
||||
# ~ if control.ImplementationName == IMPLEMENTATIONS['text']:
|
||||
# ~ mri(control)
|
||||
|
||||
for key, value in listeners.items():
|
||||
if hasattr(control, key):
|
||||
if is_grid and key == 'addMouseListener':
|
||||
|
@ -84,7 +92,7 @@ def add_listeners(events, control):
|
|||
control.addItemListener(EventsItemRoadmap(events, name))
|
||||
continue
|
||||
|
||||
getattr(control, key)(listeners[key](events, name))
|
||||
getattr(control, key)(value(events, name))
|
||||
|
||||
if is_grid:
|
||||
controllers = EventsGrid(events, name)
|
||||
|
@ -93,6 +101,37 @@ def add_listeners(events, control):
|
|||
return
|
||||
|
||||
|
||||
# ~ getAccessibleActionKeyBinding
|
||||
class UnoActions():
|
||||
ACTIONS = {
|
||||
'press': 0,
|
||||
'activate': 0,
|
||||
}
|
||||
|
||||
def __init__(self, obj: Any):
|
||||
self._obj = obj
|
||||
self._ac = obj.AccessibleContext
|
||||
self._actions = hasattr(self._ac, 'AccessibleActionCount')
|
||||
|
||||
def __str__(self):
|
||||
return ', '.join(self.get())
|
||||
|
||||
def get(self):
|
||||
actions = ()
|
||||
if self._actions:
|
||||
actions = [self._ac.getAccessibleActionDescription(i) for i in
|
||||
range(self._ac.AccessibleActionCount)]
|
||||
return actions
|
||||
|
||||
def press(self):
|
||||
result = self._ac.doAccessibleAction(self.ACTIONS['press'])
|
||||
return result
|
||||
|
||||
def activate(self):
|
||||
result = self._ac.doAccessibleAction(self.ACTIONS['activate'])
|
||||
return result
|
||||
|
||||
|
||||
class UnoBaseObject(object):
|
||||
|
||||
def __init__(self, obj: Any):
|
||||
|
@ -118,7 +157,8 @@ class UnoBaseObject(object):
|
|||
|
||||
@property
|
||||
def properties(self):
|
||||
data = LOInspect(self.obj).properties
|
||||
properties = self.model.PropertySetInfo.Properties
|
||||
data = {p.Name: getattr(self.model, p.Name) for p in properties}
|
||||
return data
|
||||
@properties.setter
|
||||
def properties(self, properties: dict):
|
||||
|
@ -308,6 +348,10 @@ class UnoBaseObject(object):
|
|||
def ps(self, ps):
|
||||
self.obj.setPosSize(ps.X, ps.Y, ps.Width, ps.Height, POSSIZE)
|
||||
|
||||
@property
|
||||
def actions(self):
|
||||
return UnoActions(self.obj)
|
||||
|
||||
def set_focus(self):
|
||||
self.obj.setFocus()
|
||||
return
|
||||
|
@ -363,6 +407,41 @@ class UnoLabel(UnoBaseObject):
|
|||
self.model.Label = value
|
||||
|
||||
|
||||
class UnoLabelLink(UnoLabel):
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return 'link'
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
"""Get link"""
|
||||
return self.model.URL
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
self.model.Label = value
|
||||
self.model.URL = value
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
"""Get link"""
|
||||
return self.model.URL
|
||||
@url.setter
|
||||
def url(self, value):
|
||||
self.model.URL = value
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
"""Get label"""
|
||||
return self.model.Label
|
||||
@label.setter
|
||||
def label(self, value):
|
||||
self.model.Label = value
|
||||
|
||||
|
||||
# ~ https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1awt_1_1UnoControlEditModel.html
|
||||
class UnoText(UnoBaseObject):
|
||||
|
||||
|
@ -418,14 +497,73 @@ class UnoButton(UnoBaseObject):
|
|||
self.model.ImageURL = Paths.to_url(value)
|
||||
|
||||
|
||||
class UnoImage(UnoBaseObject):
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return 'image'
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self.model.ImageURL
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
if isinstance(value, str):
|
||||
self.model.ImageURL = value
|
||||
else:
|
||||
self.model.Graphic = value._get_graphic()
|
||||
|
||||
|
||||
class UnoPattern(UnoBaseObject):
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return 'pattern'
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self.model.Text
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
self.model.Text = value
|
||||
|
||||
@property
|
||||
def edit_mask(self):
|
||||
return self.model.EditMask
|
||||
@edit_mask.setter
|
||||
def edit_mask(self, value):
|
||||
self.model.EditMask = value
|
||||
|
||||
@property
|
||||
def literal_mask(self):
|
||||
return self.model.LiteralMask
|
||||
@literal_mask.setter
|
||||
def literal_mask(self, value):
|
||||
self.model.LiteralMask = value
|
||||
|
||||
@property
|
||||
def strict_format(self):
|
||||
return self.model.StrictFormat
|
||||
@strict_format.setter
|
||||
def strict_format(self, value):
|
||||
self.model.StrictFormat = value
|
||||
|
||||
|
||||
UNO_CLASSES = {
|
||||
'label': UnoLabel,
|
||||
'text': UnoText,
|
||||
'button': UnoButton,
|
||||
# ~ 'link': UnoLabelLink,
|
||||
'text': UnoText,
|
||||
'link': UnoLabelLink,
|
||||
'image': UnoImage,
|
||||
'pattern': UnoPattern,
|
||||
# ~ 'radio': UnoRadio,
|
||||
# ~ 'checkbox': UnoCheckBox,
|
||||
# ~ 'image': UnoImage,
|
||||
# ~ 'listbox': UnoListBox,
|
||||
# ~ 'roadmap': UnoRoadmap,
|
||||
# ~ 'tree': UnoTree,
|
||||
|
@ -441,10 +579,11 @@ class DialogBox(BaseObject):
|
|||
SERVICE_DIALOG = 'com.sun.star.awt.UnoControlDialog'
|
||||
|
||||
def __init__(self, properties: dict={}):
|
||||
self._controls = {}
|
||||
obj = self._create(properties)
|
||||
super().__init__(obj)
|
||||
self._init_controls()
|
||||
self._events = None
|
||||
self._modal = False
|
||||
|
||||
def _create_from_path(self, path: str):
|
||||
dp = create_instance(self.SERVICE, True)
|
||||
|
@ -458,13 +597,16 @@ class DialogBox(BaseObject):
|
|||
name = properties['Name']
|
||||
library = properties.get('Library', 'Standard')
|
||||
location = properties.get('Location', 'application').lower()
|
||||
|
||||
if location == 'user':
|
||||
location = 'application'
|
||||
|
||||
url = f'vnd.sun.star.script:{library}.{name}?location={location}'
|
||||
|
||||
if location == 'document':
|
||||
doc = LODocuments().active.obj
|
||||
doc = properties.get('Document', LODocuments().active)
|
||||
if hasattr(doc, 'obj'):
|
||||
doc = doc.obj
|
||||
dp = create_instance(self.SERVICE, arguments=doc)
|
||||
else:
|
||||
dp = create_instance(self.SERVICE, True)
|
||||
|
@ -500,39 +642,30 @@ class DialogBox(BaseObject):
|
|||
tipo = control.ImplementationName
|
||||
name = control.Model.Name
|
||||
if not tipo in TYPE_CONTROL:
|
||||
log.debug(f'Type control: {tipo}')
|
||||
debug(f'Type control: {tipo}')
|
||||
raise AttributeError(f"Has no class '{tipo}'")
|
||||
control = UNO_CLASSES[TYPE_CONTROL[tipo]](control)
|
||||
setattr(self, name, control)
|
||||
self._controls[name] = control
|
||||
return
|
||||
|
||||
def execute(self):
|
||||
return self.obj.execute()
|
||||
|
||||
def open(self):
|
||||
def open(self, modal=False):
|
||||
self._modal = modal
|
||||
if modal:
|
||||
self.visible = True
|
||||
return
|
||||
return self.execute()
|
||||
|
||||
def close(self, value=0):
|
||||
value = self.obj.endDialog(value)
|
||||
if self._modal:
|
||||
self.visible = False
|
||||
self.obj.dispose()
|
||||
else:
|
||||
value = self.obj.endDialog(value)
|
||||
return value
|
||||
|
||||
# ~ def close(self, value=0):
|
||||
# ~ if self._modal:
|
||||
# ~ value = self.obj.endDialog(value)
|
||||
# ~ else:
|
||||
# ~ self.visible = False
|
||||
# ~ self.obj.dispose()
|
||||
# ~ return value
|
||||
|
||||
# ~ def show(self, modal=True):
|
||||
# ~ self._modal = modal
|
||||
# ~ if modal:
|
||||
# ~ return self.obj.execute()
|
||||
# ~ else:
|
||||
# ~ self.visible = True
|
||||
# ~ return
|
||||
|
||||
@property
|
||||
def model(self):
|
||||
return self.obj.Model
|
||||
|
@ -576,6 +709,17 @@ class DialogBox(BaseObject):
|
|||
def color_on_focus(self, value):
|
||||
self._color_on_focus = get_color(value)
|
||||
|
||||
@property
|
||||
def properties(self):
|
||||
properties = self.model.PropertySetInfo.Properties
|
||||
data = {}
|
||||
for p in properties:
|
||||
try:
|
||||
data[p.Name] = getattr(self.model, p.Name)
|
||||
except:
|
||||
continue
|
||||
return data
|
||||
|
||||
@property
|
||||
def events(self):
|
||||
return self._events
|
||||
|
@ -597,13 +741,18 @@ class DialogBox(BaseObject):
|
|||
return Paths.to_url(path)
|
||||
|
||||
def _special_properties(self, tipo, properties):
|
||||
if tipo == 'link' and not 'Label' in properties:
|
||||
if tipo == 'link' and 'URL' in properties and not 'Label' in properties:
|
||||
properties['Label'] = properties['URL']
|
||||
return properties
|
||||
|
||||
if tipo == 'label':
|
||||
properties['VerticalAlign'] = properties.get('VerticalAlign', 1)
|
||||
return properties
|
||||
|
||||
if tipo == 'button':
|
||||
if 'ImageURL' in properties:
|
||||
properties['ImageURL'] = self._set_image_url(properties['ImageURL'])
|
||||
properties['ImageAlign'] = properties.get('ImageAlign', 0)
|
||||
properties['FocusOnClick'] = properties.get('FocusOnClick', False)
|
||||
return properties
|
||||
|
||||
|
@ -659,7 +808,7 @@ class DialogBox(BaseObject):
|
|||
control.events = self.events
|
||||
|
||||
setattr(self, name, control)
|
||||
self._controls[name] = control
|
||||
|
||||
return control
|
||||
|
||||
|
||||
|
|
|
@ -1,51 +1,54 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import uno
|
||||
import unohelper
|
||||
from com.sun.star.io import IOException, XOutputStream
|
||||
from .easymain import (log,
|
||||
BaseObject, LOMain, Paths,
|
||||
dict_to_property, create_instance
|
||||
)
|
||||
from .easyuno import IOStream
|
||||
from .easyshape import LOShapes, LOShape
|
||||
|
||||
|
||||
class IOStream(object):
|
||||
"""Classe for input/output stream"""
|
||||
class LOLayoutManager(BaseObject):
|
||||
PR = 'private:resource/'
|
||||
|
||||
class OutputStream(unohelper.Base, XOutputStream):
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __init__(self):
|
||||
self._buffer = b''
|
||||
self.closed = 0
|
||||
def __getitem__(self, index):
|
||||
""" """
|
||||
name = index
|
||||
if not name.startswith(self.PR):
|
||||
name = self.PR + name
|
||||
return self.obj.getElement(name)
|
||||
|
||||
@property
|
||||
def buffer(self):
|
||||
return self._buffer
|
||||
@property
|
||||
def visible(self):
|
||||
""" """
|
||||
return self.obj.isVisible()
|
||||
@visible.setter
|
||||
def visible(self, value):
|
||||
self.obj.Visible = value
|
||||
|
||||
def closeOutput(self):
|
||||
self.closed = 1
|
||||
@property
|
||||
def elements(self):
|
||||
""" """
|
||||
return [e.ResourceURL[17:] for e in self.obj.Elements]
|
||||
|
||||
def writeBytes(self, seq):
|
||||
if seq.value:
|
||||
self._buffer = seq.value
|
||||
def show(self, name):
|
||||
if not name.startswith(self.PR):
|
||||
name = self.PR + name
|
||||
self.obj.showElement(name)
|
||||
return
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
def hide(self, name):
|
||||
if not name.startswith(self.PR):
|
||||
name = self.PR + name
|
||||
self.obj.hideElement(name)
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def buffer(cls):
|
||||
return io.BytesIO()
|
||||
|
||||
@classmethod
|
||||
def input(cls, buffer):
|
||||
service = 'com.sun.star.io.SequenceInputStream'
|
||||
stream = create_instance(service, True)
|
||||
stream.initialize((uno.ByteSequence(buffer.getvalue()),))
|
||||
return stream
|
||||
|
||||
@classmethod
|
||||
def output(cls):
|
||||
return cls.OutputStream()
|
||||
# ~ def create(self, name):
|
||||
# ~ return self.obj.createElement(name)
|
||||
|
||||
|
||||
class LODocument(BaseObject):
|
||||
|
@ -53,6 +56,7 @@ class LODocument(BaseObject):
|
|||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
self._cc = obj.getCurrentController()
|
||||
self._layout_manager = LOLayoutManager(self._cc.Frame.LayoutManager)
|
||||
self._undo = True
|
||||
|
||||
def __enter__(self):
|
||||
|
@ -149,6 +153,11 @@ class LODocument(BaseObject):
|
|||
"""Get frame document"""
|
||||
return self._cc.getFrame()
|
||||
|
||||
@property
|
||||
def layout_manager(self):
|
||||
""" """
|
||||
return self._layout_manager
|
||||
|
||||
def _create_instance(self, name):
|
||||
obj = self.obj.createInstance(name)
|
||||
return obj
|
||||
|
@ -233,6 +242,8 @@ class LODocument(BaseObject):
|
|||
:type args: dict
|
||||
:return: None if path or stream in memory
|
||||
:rtype: bytes or None
|
||||
|
||||
https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1document_1_1MediaDescriptor.html
|
||||
"""
|
||||
FILTERS = {
|
||||
'xlsx': 'Calc MS Excel 2007 XML',
|
||||
|
@ -244,8 +255,11 @@ class LODocument(BaseObject):
|
|||
|
||||
stream = None
|
||||
path_target = 'private:stream'
|
||||
if filter_name == 'svg':
|
||||
filter_name = f'{self.type}_svg_Export'
|
||||
else:
|
||||
filter_name = FILTERS.get(filter_name, filter_name)
|
||||
|
||||
filter_name = FILTERS.get(filter_name, filter_name)
|
||||
filter_data = dict_to_property(args, True)
|
||||
filters = {
|
||||
'FilterName': filter_name,
|
||||
|
@ -261,7 +275,7 @@ class LODocument(BaseObject):
|
|||
try:
|
||||
self.obj.storeToURL(path_target, opt)
|
||||
except Exception as e:
|
||||
error(e)
|
||||
log.error(e)
|
||||
|
||||
if not stream is None:
|
||||
stream = stream.buffer
|
||||
|
@ -279,6 +293,11 @@ class LODocument(BaseObject):
|
|||
LOMain.dispatch(self.frame, 'Copy')
|
||||
return
|
||||
|
||||
def cut(self):
|
||||
"""Copy current selection"""
|
||||
LOMain.dispatch(self.frame, 'Cut')
|
||||
return
|
||||
|
||||
def paste(self):
|
||||
"""Paste current content in clipboard"""
|
||||
sc = create_instance('com.sun.star.datatransfer.clipboard.SystemClipboard')
|
||||
|
@ -309,8 +328,25 @@ class LODocument(BaseObject):
|
|||
self.obj.getUndoManager().clear()
|
||||
return
|
||||
|
||||
def replace_ext(self, new_ext):
|
||||
return Paths.with_suffix(self.path, new_ext)
|
||||
|
||||
def deselect(self):
|
||||
LOMain.dispatch(self.frame, 'Deselect')
|
||||
return
|
||||
|
||||
|
||||
class LODrawImpress(LODocument):
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
@property
|
||||
def selection(self):
|
||||
"""Get current selecction"""
|
||||
sel = self.obj.CurrentSelection
|
||||
if sel.Count == 1:
|
||||
sel = LOShape(sel[0])
|
||||
else:
|
||||
sel = LOShapes(sel)
|
||||
return sel
|
|
@ -7,10 +7,13 @@ from .easywriter import LOWriter
|
|||
from .easydraw import LODraw
|
||||
from .easyimpress import LOImpress
|
||||
from .easymath import LOMath
|
||||
from .easybase import LOBase
|
||||
from .easybase import LOBase, LOBaseSource
|
||||
from .easyide import LOBasicIDE
|
||||
|
||||
|
||||
DESKTOP = create_instance('com.sun.star.frame.Desktop', True)
|
||||
|
||||
|
||||
class LODocuments():
|
||||
"""Class for documents
|
||||
"""
|
||||
|
@ -37,7 +40,7 @@ class LODocuments():
|
|||
# ~ BASE: 'com.sun.star.sdb.DocumentDataSource',
|
||||
|
||||
def __init__(self):
|
||||
self._desktop = create_instance('com.sun.star.frame.Desktop', True)
|
||||
self._desktop = DESKTOP
|
||||
|
||||
def __len__(self):
|
||||
# ~ len(self._desktop.Components)
|
||||
|
@ -88,10 +91,36 @@ class LODocuments():
|
|||
@property
|
||||
def active(self):
|
||||
"""Get active doc"""
|
||||
doc = self._desktop.getCurrentComponent()
|
||||
obj = self._get_class_doc(doc)
|
||||
active = self._desktop.getCurrentComponent()
|
||||
obj = self._get_class_doc(active)
|
||||
return obj
|
||||
|
||||
def is_registered(self, name):
|
||||
dbc = create_instance('com.sun.star.sdb.DatabaseContext')
|
||||
return dbc.hasRegisteredDatabase(name)
|
||||
|
||||
def _new_db(self, args: dict):
|
||||
FIREBIRD = 'sdbc:embedded:firebird'
|
||||
|
||||
path = Paths(args.pop('Path'))
|
||||
register = args.pop('Register', True)
|
||||
name = args.pop('Name', '')
|
||||
open_db = args.pop('Open', False)
|
||||
if register and not name:
|
||||
name = path.name
|
||||
|
||||
dbc = create_instance('com.sun.star.sdb.DatabaseContext')
|
||||
db = dbc.createInstance()
|
||||
db.URL = FIREBIRD
|
||||
db.DatabaseDocument.storeAsURL(path.url, ())
|
||||
if register:
|
||||
dbc.registerDatabaseLocation(name, path.url)
|
||||
|
||||
if open_db:
|
||||
return self.open(path.url, args)
|
||||
|
||||
return LOBaseSource(db)
|
||||
|
||||
def new(self, type_doc: str='calc', args: dict={}):
|
||||
"""Create new document
|
||||
|
||||
|
@ -102,6 +131,9 @@ class LODocuments():
|
|||
:return: New document
|
||||
:rtype: Custom class
|
||||
"""
|
||||
if type_doc == 'base':
|
||||
return self._new_db(args)
|
||||
|
||||
url = f'private:factory/s{type_doc}'
|
||||
opt = dict_to_property(args)
|
||||
doc = self._desktop.loadComponentFromURL(url, '_default', 0, opt)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from .easydoc import LODrawImpress
|
||||
from .easydrawpage import LODrawPage
|
||||
from .easymain import LOMain
|
||||
|
||||
|
||||
class LODraw(LODrawImpress):
|
||||
|
@ -17,3 +18,13 @@ class LODraw(LODrawImpress):
|
|||
page = self.obj.DrawPages.getByName(index)
|
||||
return LODrawPage(page)
|
||||
|
||||
@property
|
||||
def active(self):
|
||||
"""Get active page"""
|
||||
return LODrawPage(self._cc.CurrentPage)
|
||||
|
||||
def paste(self):
|
||||
"""Paste"""
|
||||
LOMain.dispatch(self.frame, 'Paste')
|
||||
return
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from pathlib import Path
|
||||
from com.sun.star.awt import Size, Point
|
||||
|
||||
from .easymain import (
|
||||
|
@ -14,13 +15,12 @@ from .easydoc import IOStream
|
|||
DEFAULT_WH = 3000
|
||||
DEFAULT_XY = 1000
|
||||
|
||||
TYPE_SHAPES = ('Line', 'Measure', 'Rectangle', 'Ellipse', 'Text', 'Connector',
|
||||
'ClosedBezier', 'OpenBezier', 'PolyLine', 'PolyPolygon', 'ClosedFreeHand',
|
||||
'OpenFreeHand')
|
||||
|
||||
# ~ class LOShapeBK(BaseObject):
|
||||
|
||||
# ~ @property
|
||||
# ~ def cell(self):
|
||||
# ~ return self.anchor
|
||||
|
||||
# ~ @property
|
||||
# ~ def anchor(self):
|
||||
# ~ obj = self.obj.Anchor
|
||||
|
@ -145,6 +145,16 @@ class LODrawPage(BaseObject):
|
|||
break
|
||||
return result
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
pass
|
||||
|
||||
def __len__(self):
|
||||
"""Count shapes"""
|
||||
return self.count
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.obj.Name
|
||||
|
@ -172,14 +182,28 @@ class LODrawPage(BaseObject):
|
|||
def _create_instance(self, name):
|
||||
return self.doc.createInstance(name)
|
||||
|
||||
def select(self, shape):
|
||||
if hasattr(shape, 'obj'):
|
||||
shape = shape.obj
|
||||
controller = self.doc.CurrentController
|
||||
controller.select(shape)
|
||||
return
|
||||
|
||||
def add(self, type_shape, options={}):
|
||||
properties = options.copy()
|
||||
"""Insert a shape in page, type shapes:
|
||||
Line
|
||||
Measure
|
||||
Rectangle
|
||||
Ellipse
|
||||
Text
|
||||
Connector
|
||||
ClosedBezier
|
||||
OpenBezier
|
||||
PolyLine
|
||||
PolyPolygon
|
||||
ClosedFreeHand
|
||||
OpenFreeHand
|
||||
"""
|
||||
index = self.count
|
||||
default_height = DEFAULT_WH
|
||||
|
@ -191,17 +215,22 @@ class LODrawPage(BaseObject):
|
|||
y = properties.pop('Y', DEFAULT_XY)
|
||||
name = properties.pop('Name', f'{type_shape.lower()}{index}')
|
||||
|
||||
service = f'com.sun.star.drawing.{type_shape}Shape'
|
||||
if type_shape in TYPE_SHAPES:
|
||||
service = f'com.sun.star.drawing.{type_shape}Shape'
|
||||
else:
|
||||
service = 'com.sun.star.drawing.CustomShape'
|
||||
shape = self._create_instance(service)
|
||||
shape.Size = Size(w, h)
|
||||
shape.Position = Point(x, y)
|
||||
shape.Name = name
|
||||
self.obj.add(shape)
|
||||
|
||||
if not type_shape in TYPE_SHAPES:
|
||||
shape.CustomShapeGeometry = dict_to_property({'Type': type_shape})
|
||||
|
||||
if properties:
|
||||
set_properties(shape, properties)
|
||||
|
||||
# ~ return LOShape(self.obj[index], index)
|
||||
return LOShape(self.obj[index])
|
||||
|
||||
def remove(self, shape):
|
||||
|
@ -225,8 +254,9 @@ class LODrawPage(BaseObject):
|
|||
|
||||
image = self._create_instance('com.sun.star.drawing.GraphicObjectShape')
|
||||
if isinstance(path, str):
|
||||
image.GraphicURL = _P.to_url(path)
|
||||
image.GraphicURL = Path(path).as_uri()
|
||||
else:
|
||||
# ~ URL = path
|
||||
gp = create_instance('com.sun.star.graphic.GraphicProvider')
|
||||
stream = IOStream.input(path)
|
||||
properties = dict_to_property({'InputStream': stream})
|
||||
|
|
|
@ -5,14 +5,24 @@ import unohelper
|
|||
|
||||
from com.sun.star.awt import XActionListener
|
||||
from com.sun.star.lang import XEventListener
|
||||
from com.sun.star.awt import XFocusListener
|
||||
from com.sun.star.util import XModifyListener
|
||||
from com.sun.star.awt import XMouseListener
|
||||
from com.sun.star.awt import XMouseMotionListener
|
||||
from com.sun.star.awt import XTextListener
|
||||
from com.sun.star.sheet import XRangeSelectionListener
|
||||
|
||||
from .easymain import Macro, dict_to_property
|
||||
from .easymain import Macro, Color, dict_to_property
|
||||
|
||||
|
||||
__all__ = [
|
||||
'EventsButton',
|
||||
'EventsFocus',
|
||||
'EventsModify',
|
||||
'EventsMouse',
|
||||
'EventsMouseLink',
|
||||
'EventsRangeSelectionListener',
|
||||
'EventsText',
|
||||
]
|
||||
|
||||
|
||||
|
@ -80,15 +90,12 @@ class EventsRangeSelectionListener(EventsListenerBase, XRangeSelectionListener):
|
|||
super().__init__(controller, '')
|
||||
|
||||
def done(self, event):
|
||||
range_selection = event.RangeDescriptor
|
||||
print(event)
|
||||
event_name = 'range_selection_done'
|
||||
if hasattr(self._controller, event_name):
|
||||
getattr(self._controller, event_name)(range_selection)
|
||||
getattr(self._controller, event_name)(event.RangeDescriptor)
|
||||
return
|
||||
|
||||
def aborted(self, event):
|
||||
range_selection = event.RangeDescriptor
|
||||
event_name = 'range_selection_aborted'
|
||||
if hasattr(self._controller, event_name):
|
||||
getattr(self._controller, event_name)()
|
||||
|
@ -96,6 +103,9 @@ class EventsRangeSelectionListener(EventsListenerBase, XRangeSelectionListener):
|
|||
|
||||
|
||||
class EventsButton(EventsListenerBase, XActionListener):
|
||||
"""
|
||||
See: https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1awt_1_1XActionListener.html
|
||||
"""
|
||||
|
||||
def __init__(self, controller, name):
|
||||
super().__init__(controller, name)
|
||||
|
@ -105,3 +115,99 @@ class EventsButton(EventsListenerBase, XActionListener):
|
|||
if hasattr(self._controller, event_name):
|
||||
getattr(self._controller, event_name)(event)
|
||||
return
|
||||
|
||||
|
||||
class EventsMouse(EventsListenerBase, XMouseListener, XMouseMotionListener):
|
||||
|
||||
def __init__(self, controller, name):
|
||||
super().__init__(controller, name)
|
||||
|
||||
def mousePressed(self, event):
|
||||
event_name = f'{self._name}_click'
|
||||
if event.ClickCount == 2:
|
||||
event_name = f'{self._name}_double_click'
|
||||
if hasattr(self._controller, event_name):
|
||||
getattr(self._controller, event_name)(event)
|
||||
return
|
||||
|
||||
def mouseReleased(self, event):
|
||||
pass
|
||||
|
||||
def mouseEntered(self, event):
|
||||
pass
|
||||
|
||||
def mouseExited(self, event):
|
||||
pass
|
||||
|
||||
# ~ XMouseMotionListener
|
||||
def mouseMoved(self, event):
|
||||
event_name = f'{self._name}_mouse_moved'
|
||||
if hasattr(self._controller, event_name):
|
||||
getattr(self._controller, event_name)(event)
|
||||
return
|
||||
|
||||
def mouseDragged(self, event):
|
||||
pass
|
||||
|
||||
|
||||
class EventsMouseLink(EventsMouse):
|
||||
|
||||
def mouseEntered(self, event):
|
||||
obj = event.Source.Model
|
||||
obj.TextColor = Color()('blue')
|
||||
return
|
||||
|
||||
def mouseExited(self, event):
|
||||
obj = event.Source.Model
|
||||
obj.TextColor = 0
|
||||
return
|
||||
|
||||
|
||||
class EventsFocus(EventsListenerBase, XFocusListener):
|
||||
|
||||
def __init__(self, controller, name):
|
||||
super().__init__(controller, name)
|
||||
|
||||
def focusGained(self, event):
|
||||
service = event.Source.Model.ImplementationName
|
||||
if service == 'stardiv.Toolkit.UnoControlListBoxModel':
|
||||
return
|
||||
|
||||
event_name = f'{self._name}_focus_gained'
|
||||
if hasattr(self._controller, event_name):
|
||||
getattr(self._controller, event_name)(event)
|
||||
|
||||
# ~ obj = event.Source.ModelBackgroundColor = 16777184
|
||||
return
|
||||
|
||||
def focusLost(self, event):
|
||||
event_name = f'{self._name}_focus_lost'
|
||||
if hasattr(self._controller, event_name):
|
||||
getattr(self._controller, event_name)(event)
|
||||
|
||||
# ~ event.Source.Model.BackgroundColor = -1
|
||||
return
|
||||
|
||||
|
||||
class EventsModify(EventsListenerBase, XModifyListener):
|
||||
|
||||
def __init__(self, controller, name):
|
||||
super().__init__(controller, name)
|
||||
|
||||
def modified(self, event):
|
||||
event_name = f'{self._name}_modified'
|
||||
if hasattr(self._controller, event_name):
|
||||
getattr(self._controller, event_name)(event)
|
||||
return
|
||||
|
||||
|
||||
class EventsText(EventsListenerBase, XTextListener):
|
||||
|
||||
def __init__(self, controller, name):
|
||||
super().__init__(controller, name)
|
||||
|
||||
def textChanged(self, event):
|
||||
event_name = f'{self._name}_text_changed'
|
||||
if hasattr(self._controller, event_name):
|
||||
getattr(self._controller, event_name)(event)
|
||||
return
|
||||
|
|
|
@ -24,13 +24,15 @@ from com.sun.star.beans import PropertyValue, NamedValue, StringPair
|
|||
from com.sun.star.datatransfer import XTransferable, DataFlavor
|
||||
from com.sun.star.ui.dialogs import TemplateDescription
|
||||
|
||||
# ~ from .constants import ALL
|
||||
from .messages import MESSAGES
|
||||
|
||||
|
||||
__all__ = [
|
||||
'ALL',
|
||||
'DESKTOP',
|
||||
'INFO_DEBUG',
|
||||
'IS_APPIMAGE',
|
||||
'IS_FLATPAK',
|
||||
'IS_MAC',
|
||||
'IS_WIN',
|
||||
'LANG',
|
||||
|
@ -63,13 +65,12 @@ PC = platform.node()
|
|||
USER = getpass.getuser()
|
||||
IS_WIN = OS == 'Windows'
|
||||
IS_MAC = OS == 'Darwin'
|
||||
|
||||
|
||||
ALL = 1023
|
||||
IS_FLATPAK = bool(os.getenv("FLATPAK_ID", ""))
|
||||
IS_APPIMAGE = bool(os.getenv("APPIMAGE", ""))
|
||||
|
||||
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_DATE = '%d/%m/%Y %H:%M:%S'
|
||||
LOG_DATE = '%Y/%m/%d %H:%M:%S'
|
||||
if IS_WIN:
|
||||
logging.addLevelName(logging.ERROR, 'ERROR')
|
||||
logging.addLevelName(logging.DEBUG, 'DEBUG')
|
||||
|
@ -149,7 +150,6 @@ day = get_app_config(node, 'DD')
|
|||
DATE_OFFSET = datetime.date(year, month, day).toordinal()
|
||||
|
||||
_info_debug = f"Python: {sys.version}\n\n{platform.platform()}\n\n" + '\n'.join(sys.path)
|
||||
# ~ doc
|
||||
INFO_DEBUG = f"{NAME} v{VERSION} {LANGUAGE}\n\n{_info_debug}"
|
||||
|
||||
|
||||
|
@ -221,6 +221,16 @@ def set_properties(model, properties):
|
|||
return
|
||||
|
||||
|
||||
def get_properties(obj):
|
||||
# ~ properties = obj.PropertySetInfo.Properties
|
||||
# ~ values = {p.Name: getattr(obj, p.Name) for p in properties}
|
||||
data = obj.PropertySetInfo.Properties
|
||||
keys = [p.Name for p in data]
|
||||
values = obj.getPropertyValues(keys)
|
||||
properties = dict(zip(keys, values))
|
||||
return properties
|
||||
|
||||
|
||||
# ~ https://github.com/django/django/blob/main/django/utils/functional.py#L61
|
||||
class classproperty:
|
||||
|
||||
|
@ -486,6 +496,7 @@ class LOMain():
|
|||
"""Class for disable and enable commands
|
||||
|
||||
`See DispatchCommands <https://wiki.documentfoundation.org/Development/DispatchCommands>`_
|
||||
https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1configuration_1_1ConfigurationProvider.html
|
||||
"""
|
||||
@classmethod
|
||||
def _set_app_command(cls, command: str, disable: bool) -> bool:
|
||||
|
@ -500,6 +511,7 @@ class LOMain():
|
|||
"""
|
||||
NEW_NODE_NAME = f'zaz_disable_command_{command.lower()}'
|
||||
name = 'com.sun.star.configuration.ConfigurationProvider'
|
||||
# ~ name = 'com.sun.star.configuration.theDefaultProvider'
|
||||
service = 'com.sun.star.configuration.ConfigurationUpdateAccess'
|
||||
node_name = '/org.openoffice.Office.Commands/Execute/Disabled'
|
||||
|
||||
|
@ -507,9 +519,6 @@ class LOMain():
|
|||
node = PropertyValue(Name='nodepath', Value=node_name)
|
||||
update = cp.createInstanceWithArguments(service, (node,))
|
||||
|
||||
m = create_instance('mytools.Mri')
|
||||
m.inspect(update)
|
||||
|
||||
result = True
|
||||
try:
|
||||
if disable:
|
||||
|
@ -538,7 +547,7 @@ class LOMain():
|
|||
return cls._set_app_command(command, True)
|
||||
|
||||
@classmethod
|
||||
def enabled(cls, command) -> bool:
|
||||
def enabled(cls, command: str) -> bool:
|
||||
"""Enabled UNO command
|
||||
|
||||
:param command: UNO command to enabled
|
||||
|
@ -600,13 +609,14 @@ class LOMain():
|
|||
|
||||
class ClipBoard(object):
|
||||
SERVICE = 'com.sun.star.datatransfer.clipboard.SystemClipboard'
|
||||
CLIPBOARD_FORMAT_TEXT = 'text/plain;charset=utf-16'
|
||||
TEXT = 'text/plain;charset=utf-16'
|
||||
IMAGE = 'application/x-openoffice-bitmap;windows_formatname="Bitmap"'
|
||||
|
||||
class TextTransferable(unohelper.Base, XTransferable):
|
||||
|
||||
def __init__(self, text):
|
||||
df = DataFlavor()
|
||||
df.MimeType = ClipBoard.CLIPBOARD_FORMAT_TEXT
|
||||
df.MimeType = ClipBoard.TEXT
|
||||
df.HumanPresentableName = 'encoded text utf-16'
|
||||
self.flavors = (df,)
|
||||
self._data = text
|
||||
|
@ -632,7 +642,7 @@ class ClipBoard(object):
|
|||
transferable = sc.getContents()
|
||||
data = transferable.getTransferDataFlavors()
|
||||
for df in data:
|
||||
if df.MimeType == cls.CLIPBOARD_FORMAT_TEXT:
|
||||
if df.MimeType == cls.TEXT:
|
||||
break
|
||||
if df:
|
||||
text = transferable.getTransferData(df)
|
||||
|
@ -841,6 +851,10 @@ class Paths(object):
|
|||
"""
|
||||
return Path(path).is_file()
|
||||
|
||||
@classmethod
|
||||
def is_symlink(cls, path: str):
|
||||
return Path(path).is_symlink()
|
||||
|
||||
@classmethod
|
||||
def temp_file(self):
|
||||
"""Make temporary file"""
|
||||
|
@ -1042,10 +1056,13 @@ class Paths(object):
|
|||
:return: Path with new extension
|
||||
:rtype: str
|
||||
"""
|
||||
p = Paths(path)
|
||||
name = f'{p.name}.{new_ext}'
|
||||
path = cls.join(p.path, name)
|
||||
return path
|
||||
if not new_ext.startswith('.'):
|
||||
new_ext = f'.{new_ext}'
|
||||
return Path(path).with_suffix(new_ext)
|
||||
|
||||
@classmethod
|
||||
def with_suffix(cls, path: str, new_ext: str):
|
||||
return cls.replace_ext(path, new_ext)
|
||||
|
||||
@classmethod
|
||||
def open(cls, path: str):
|
||||
|
|
|
@ -1,7 +1,31 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from typing import Any
|
||||
|
||||
from com.sun.star.awt import Size, Point
|
||||
from .easymain import BaseObject, set_properties
|
||||
from .easymain import (
|
||||
BaseObject, Paths,
|
||||
create_instance, dict_to_property, log, set_properties, get_properties
|
||||
)
|
||||
from .easyuno import (
|
||||
BaseObjectProperties,
|
||||
IOStream,
|
||||
get_input_stream)
|
||||
|
||||
|
||||
IMAGE = 'com.sun.star.drawing.GraphicObjectShape'
|
||||
|
||||
MIME_TYPE = {
|
||||
'image/png': 'png',
|
||||
'image/jpeg': 'jpg',
|
||||
'image/svg': 'svg',
|
||||
}
|
||||
|
||||
TYPE_MIME = {
|
||||
'svg': 'image/svg',
|
||||
'png': 'image/png',
|
||||
'jpg': 'image/jpeg',
|
||||
}
|
||||
|
||||
|
||||
class LOShapes(object):
|
||||
|
@ -41,38 +65,84 @@ class LOShapes(object):
|
|||
return self._obj
|
||||
|
||||
|
||||
class LOShape(BaseObject):
|
||||
IMAGE = 'com.sun.star.drawing.GraphicObjectShape'
|
||||
class LOShape(BaseObjectProperties):
|
||||
|
||||
def __init__(self, obj):
|
||||
self._obj = obj
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return f'Shape: {self.name}'
|
||||
|
||||
@property
|
||||
def obj(self):
|
||||
return self._obj
|
||||
def sheet(self):
|
||||
return self.anchor
|
||||
@sheet.setter
|
||||
def sheet(self, value):
|
||||
self.anchor = value
|
||||
@property
|
||||
def cell(self):
|
||||
return self.anchor
|
||||
@cell.setter
|
||||
def cell(self, value):
|
||||
self.anchor = value
|
||||
@property
|
||||
def anchor(self):
|
||||
from .easycalc import LOCalcSheet, LOCalcRange
|
||||
TYPE_ANCHOR = {
|
||||
'ScTableSheetObj': LOCalcSheet,
|
||||
'ScCellObj': LOCalcRange,
|
||||
}
|
||||
"""Get anchor object"""
|
||||
obj = self.obj.Anchor
|
||||
implementation = obj.ImplementationName
|
||||
if implementation in TYPE_ANCHOR:
|
||||
obj = TYPE_ANCHOR[implementation](obj)
|
||||
else:
|
||||
log.debug(implementation)
|
||||
return obj
|
||||
@anchor.setter
|
||||
def anchor(self, obj):
|
||||
if hasattr(obj, 'obj'):
|
||||
obj = obj.obj
|
||||
self.obj.Anchor = obj
|
||||
return
|
||||
|
||||
@property
|
||||
def resize_with_cell(self):
|
||||
"""If resize with cell"""
|
||||
return self.obj.ResizeWithCell
|
||||
@resize_with_cell.setter
|
||||
def resize_with_cell(self, value):
|
||||
self.obj.ResizeWithCell = value
|
||||
return
|
||||
|
||||
@property
|
||||
def properties(self):
|
||||
# ~ properties = self.obj.PropertySetInfo.Properties
|
||||
# ~ data = {p.Name: getattr(self.obj, p.Name) for p in properties}
|
||||
data = self.obj.PropertySetInfo.Properties
|
||||
keys = [p.Name for p in data]
|
||||
values = self.obj.getPropertyValues(keys)
|
||||
data = dict(zip(keys, values))
|
||||
return data
|
||||
"""Get all properties"""
|
||||
return get_properties(self.obj)
|
||||
@properties.setter
|
||||
def properties(self, values):
|
||||
set_properties(self.obj, values)
|
||||
|
||||
@property
|
||||
def shape_type(self):
|
||||
"""Get type shape"""
|
||||
return self.obj.ShapeType
|
||||
@property
|
||||
def type(self):
|
||||
value = ''
|
||||
if hasattr(self.obj, 'CustomShapeGeometry'):
|
||||
for p in self.obj.CustomShapeGeometry:
|
||||
if p.Name == 'Type':
|
||||
value = p.Value
|
||||
break
|
||||
else:
|
||||
value = self.shape_type
|
||||
return value
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Get name"""
|
||||
return self.obj.Name
|
||||
@name.setter
|
||||
def name(self, value):
|
||||
|
@ -80,11 +150,11 @@ class LOShape(BaseObject):
|
|||
|
||||
@property
|
||||
def is_image(self):
|
||||
return self.shape_type == self.IMAGE
|
||||
return self.shape_type == IMAGE
|
||||
|
||||
@property
|
||||
def is_shape(self):
|
||||
return self.shape_type != self.IMAGE
|
||||
return self.shape_type != IMAGE
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
|
@ -96,6 +166,7 @@ class LOShape(BaseObject):
|
|||
|
||||
@property
|
||||
def width(self):
|
||||
"""Width of shape"""
|
||||
s = self.obj.Size
|
||||
return s.Width
|
||||
@width.setter
|
||||
|
@ -106,6 +177,7 @@ class LOShape(BaseObject):
|
|||
|
||||
@property
|
||||
def height(self):
|
||||
"""Height of shape"""
|
||||
s = self.obj.Size
|
||||
return s.Height
|
||||
@height.setter
|
||||
|
@ -119,6 +191,7 @@ class LOShape(BaseObject):
|
|||
return self.obj.Position
|
||||
@property
|
||||
def x(self):
|
||||
"""Position X"""
|
||||
return self.position.X
|
||||
@x.setter
|
||||
def x(self, value):
|
||||
|
@ -126,6 +199,7 @@ class LOShape(BaseObject):
|
|||
|
||||
@property
|
||||
def y(self):
|
||||
"""Position Y"""
|
||||
return self.position.Y
|
||||
@y.setter
|
||||
def y(self, value):
|
||||
|
@ -181,11 +255,132 @@ class LOShape(BaseObject):
|
|||
self.obj.LayerID = value
|
||||
|
||||
@property
|
||||
def is_range(self):
|
||||
return False
|
||||
def mime_type(self):
|
||||
mt = self.obj.GraphicURL.MimeType
|
||||
mime_type = MIME_TYPE.get(mt, mt)
|
||||
return mime_type
|
||||
|
||||
@property
|
||||
def is_cell(self):
|
||||
return False
|
||||
def path(self):
|
||||
return self.url
|
||||
@property
|
||||
def url(self):
|
||||
if self.is_image:
|
||||
url = Paths.to_system(self.obj.GraphicURL.OriginURL)
|
||||
else:
|
||||
url = self.obj.FillBitmapName
|
||||
return url
|
||||
@url.setter
|
||||
def url(self, value):
|
||||
self.obj.FillBitmapURL = Paths.to_url(value)
|
||||
|
||||
@property
|
||||
def visible(self):
|
||||
return self.obj.Visible
|
||||
@visible.setter
|
||||
def visible(self, value):
|
||||
self.obj.Visible = value
|
||||
|
||||
@property
|
||||
def doc(self):
|
||||
return self.obj.Parent.Forms.Parent
|
||||
|
||||
@property
|
||||
def text_box(self):
|
||||
return self.obj.TextBox
|
||||
@text_box.setter
|
||||
def text_box(self, value):
|
||||
self.obj.TextBox = value
|
||||
|
||||
@property
|
||||
def text_box_content(self):
|
||||
return self.obj.TextBoxContent
|
||||
# ~ @property
|
||||
# ~ def text_box_content(self):
|
||||
# ~ controller = self.doc.CurrentController
|
||||
# ~ vc = controller.ViewCursor
|
||||
# ~ tbx = self.obj.TextBoxContent
|
||||
# ~ vc.gotoRange(tbx.Start, False)
|
||||
# ~ vc.gotoRange(tbx.End, True)
|
||||
# ~ text = controller.getTransferable()
|
||||
# ~ return text
|
||||
|
||||
def get_path(self, path: str='', name: str='', mime_type: str=''):
|
||||
if not path:
|
||||
path = Paths(self.doc.URL).path
|
||||
if not name:
|
||||
name = self.name.replace(' ', '_')
|
||||
if mime_type:
|
||||
file_name = f'{name}.{mime_type}'
|
||||
else:
|
||||
if self.is_image:
|
||||
file_name = f'{name}.{self.mime_type}'
|
||||
else:
|
||||
file_name = f'{name}.svg'
|
||||
path = Paths.join(path, file_name)
|
||||
return path
|
||||
|
||||
def select(self):
|
||||
controller = self.doc.CurrentController
|
||||
controller.select(self.obj)
|
||||
return
|
||||
|
||||
def remove(self):
|
||||
"""Auto remove"""
|
||||
self.obj.Parent.remove(self.obj)
|
||||
return
|
||||
|
||||
def export(self, path: str=''):
|
||||
if not path:
|
||||
path = self.get_path()
|
||||
mime_type = Paths(path).ext
|
||||
options = {
|
||||
'URL': Paths.to_url(path),
|
||||
'MimeType': TYPE_MIME.get(mime_type, mime_type)}
|
||||
args = dict_to_property(options)
|
||||
export = create_instance('com.sun.star.drawing.GraphicExportFilter')
|
||||
export.setSourceDocument(self.obj)
|
||||
export.filter(args)
|
||||
return path
|
||||
|
||||
def save(self, path: str=''):
|
||||
"""Save image"""
|
||||
if not path:
|
||||
path = self.get_path()
|
||||
|
||||
if self.is_image:
|
||||
data = IOStream.to_bin(self.obj.GraphicStream)
|
||||
Paths.save_bin(path, data)
|
||||
else:
|
||||
self.export(path)
|
||||
|
||||
return path
|
||||
|
||||
def _get_graphic(self):
|
||||
stream = self.obj.GraphicStream
|
||||
buffer = IOStream.output()
|
||||
_, data = stream.readBytes(buffer, stream.available())
|
||||
stream = get_input_stream(data)
|
||||
gp = create_instance('com.sun.star.graphic.GraphicProvider')
|
||||
properties = dict_to_property({'InputStream': stream})
|
||||
graphic = gp.queryGraphic(properties)
|
||||
return graphic
|
||||
|
||||
def clone(self, draw_page: Any=None, x: int=1000, y: int=1000):
|
||||
"""Clone image"""
|
||||
image = self.doc.createInstance('com.sun.star.drawing.GraphicObjectShape')
|
||||
image.Graphic = self._get_graphic()
|
||||
if draw_page is None:
|
||||
draw_page = self.obj.Parent
|
||||
else:
|
||||
if hasattr(draw_page, 'obj'):
|
||||
draw_page = draw_page.obj
|
||||
|
||||
draw_page.add(image)
|
||||
image.Size = self.size
|
||||
position = self.position
|
||||
position.X += x
|
||||
position.Y += y
|
||||
image.Position = position
|
||||
return LOShape(image)
|
||||
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
|
||||
from .easymain import log, BaseObject, set_properties, get_properties
|
||||
|
||||
|
||||
STYLE_FAMILIES = 'StyleFamilies'
|
||||
|
||||
|
||||
class LOBaseStyles(BaseObject):
|
||||
|
||||
def __init__(self, obj, create_instance=None):
|
||||
super().__init__(obj)
|
||||
self._create_intance = create_instance
|
||||
|
||||
def __len__(self):
|
||||
return self.obj.Count
|
||||
|
||||
def __contains__(self, item):
|
||||
return self.obj.hasByName(item)
|
||||
|
||||
def __getitem__(self, index):
|
||||
if index in self:
|
||||
style = self.obj.getByName(index)
|
||||
else:
|
||||
raise IndexError
|
||||
|
||||
if self.NAME == STYLE_FAMILIES:
|
||||
s = LOStyles(style, index, self._create_intance)
|
||||
else:
|
||||
s = LOStyle(style)
|
||||
return s
|
||||
|
||||
def __iter__(self):
|
||||
self._index = 0
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self._index < self.obj.Count:
|
||||
style = self[self.names[self._index]]
|
||||
else:
|
||||
raise StopIteration
|
||||
|
||||
self._index += 1
|
||||
return style
|
||||
|
||||
@property
|
||||
def names(self):
|
||||
return self.obj.ElementNames
|
||||
|
||||
|
||||
class LOStyle():
|
||||
NAME = 'Style'
|
||||
|
||||
def __init__(self, obj):
|
||||
self._obj = obj
|
||||
|
||||
def __str__(self):
|
||||
return f'Style: {self.name}'
|
||||
|
||||
def __contains__(self, item):
|
||||
return hasattr(self.obj, item)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name != '_obj':
|
||||
self.obj.setPropertyValue(name, value)
|
||||
else:
|
||||
super().__setattr__(name, value)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return self.obj.getPropertyValue(name)
|
||||
|
||||
@property
|
||||
def obj(self):
|
||||
return self._obj
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.obj.Name
|
||||
|
||||
@property
|
||||
def is_in_use(self):
|
||||
return self.obj.isInUse()
|
||||
|
||||
@property
|
||||
def is_user_defined(self):
|
||||
return self.obj.isUserDefined()
|
||||
|
||||
@property
|
||||
def properties(self):
|
||||
return get_properties(self.obj)
|
||||
@properties.setter
|
||||
def properties(self, values):
|
||||
set_properties(self.obj, values)
|
||||
|
||||
|
||||
class LOStyles(LOBaseStyles):
|
||||
NAME = 'Styles'
|
||||
|
||||
def __init__(self, obj, type_style, create_instance):
|
||||
super().__init__(obj)
|
||||
self._type_style = type_style
|
||||
self._create_instance = create_instance
|
||||
|
||||
def __str__(self):
|
||||
return f'Styles: {self._type_style}'
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key in self:
|
||||
style = self.obj.getByName(key)
|
||||
else:
|
||||
name = f'com.sun.star.style.{self._type_style[:-1]}'
|
||||
style = self._create_instance(name)
|
||||
self.obj.insertByName(key, style)
|
||||
set_properties(style, value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
self.obj.removeByName(key)
|
||||
|
||||
|
||||
class LOStyleFamilies(LOBaseStyles):
|
||||
NAME = STYLE_FAMILIES
|
||||
|
||||
def __init__(self, obj, create_instance):
|
||||
super().__init__(obj, create_instance)
|
||||
|
||||
def __str__(self):
|
||||
return f'Style Families: {self.names}'
|
||||
|
||||
def _validate_name(self, name):
|
||||
if not name.endswith('Styles'):
|
||||
name = f'{name}Styles'
|
||||
return name
|
||||
|
||||
def __contains__(self, item):
|
||||
return self.obj.hasByName(self._validate_name(item))
|
||||
|
||||
def __getitem__(self, index):
|
||||
if isinstance(index, int):
|
||||
index = self.names[index]
|
||||
else:
|
||||
index = self._validate_name(index)
|
||||
return super().__getitem__(index)
|
|
@ -338,7 +338,7 @@ class LOInspect():
|
|||
'STRUCT': '-Struct-',
|
||||
}
|
||||
|
||||
def __init__(self, obj: Any, to_doc: bool=False):
|
||||
def __init__(self, obj: Any, to_doc: bool=True):
|
||||
"""Introspection objects pyUno
|
||||
|
||||
:param obj: Object to inspect
|
||||
|
@ -381,7 +381,8 @@ class LOInspect():
|
|||
sheet['A1'].data = self.interfaces
|
||||
|
||||
sheet = doc.insert('Services')
|
||||
sheet['A1'].data = self.services
|
||||
if self.services:
|
||||
sheet['A1'].data = self.services
|
||||
|
||||
sheet = doc.insert('Listeners')
|
||||
sheet['A1'].data = self.listeners
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import uno
|
||||
import unohelper
|
||||
from com.sun.star.io import IOException, XOutputStream
|
||||
from .easymain import Paths, create_instance
|
||||
|
||||
|
||||
# UNO Enum
|
||||
class MessageBoxType():
|
||||
|
@ -9,3 +14,103 @@ class MessageBoxType():
|
|||
"""
|
||||
from com.sun.star.awt.MessageBoxType \
|
||||
import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX
|
||||
|
||||
|
||||
class LineStyle():
|
||||
from com.sun.star.drawing.LineStyle import NONE, SOLID, DASH
|
||||
|
||||
|
||||
class FillStyle():
|
||||
from com.sun.star.drawing.FillStyle import NONE, SOLID, GRADIENT, HATCH, BITMAP
|
||||
|
||||
|
||||
class BitmapMode():
|
||||
from com.sun.star.drawing.BitmapMode import REPEAT, STRETCH, NO_REPEAT
|
||||
|
||||
|
||||
class CellContentType():
|
||||
from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA
|
||||
|
||||
|
||||
class IOStream(object):
|
||||
"""Classe for input/output stream"""
|
||||
|
||||
class OutputStream(unohelper.Base, XOutputStream):
|
||||
|
||||
def __init__(self):
|
||||
self._buffer = b''
|
||||
self.closed = 0
|
||||
|
||||
@property
|
||||
def buffer(self):
|
||||
return self._buffer
|
||||
|
||||
def closeOutput(self):
|
||||
self.closed = 1
|
||||
|
||||
def writeBytes(self, seq):
|
||||
if seq.value:
|
||||
self._buffer = seq.value
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def buffer(cls):
|
||||
return io.BytesIO()
|
||||
|
||||
@classmethod
|
||||
def input(cls, buffer):
|
||||
service = 'com.sun.star.io.SequenceInputStream'
|
||||
stream = create_instance(service, True)
|
||||
stream.initialize((uno.ByteSequence(buffer.getvalue()),))
|
||||
return stream
|
||||
|
||||
@classmethod
|
||||
def output(cls):
|
||||
return cls.OutputStream()
|
||||
|
||||
@classmethod
|
||||
def to_bin(cls, stream):
|
||||
buffer = cls.OutputStream()
|
||||
_, data = stream.readBytes(buffer, stream.available())
|
||||
return data.value
|
||||
|
||||
|
||||
def get_input_stream(data):
|
||||
stream = create_instance('com.sun.star.io.SequenceInputStream', True)
|
||||
stream.initialize((data,))
|
||||
return stream
|
||||
|
||||
|
||||
class BaseObjectProperties():
|
||||
|
||||
def __init__(self, obj):
|
||||
self._obj = obj
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
pass
|
||||
|
||||
def __contains__(self, item):
|
||||
return hasattr(self.obj, item)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name == '_obj':
|
||||
super().__setattr__(name, value)
|
||||
else:
|
||||
if name in self:
|
||||
if name == 'FillBitmapURL':
|
||||
value = Paths.to_url(value)
|
||||
setattr(self.obj, name, value)
|
||||
else:
|
||||
object.__setattr__(self, name, value)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return self.obj.getPropertyValue(name)
|
||||
|
||||
@property
|
||||
def obj(self):
|
||||
return self._obj
|
||||
|
|
|
@ -1,11 +1,291 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from typing import Any
|
||||
|
||||
from .easymain import log, BaseObject
|
||||
from .easydoc import LODocument
|
||||
from .easydrawpage import LODrawPage
|
||||
from .easystyles import LOStyleFamilies
|
||||
|
||||
|
||||
class LOTableRange(BaseObject):
|
||||
|
||||
def __init__(self, table, obj):
|
||||
self._table = table
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return f'TextTable: Range - {self.name}'
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self.is_cell:
|
||||
n = self.obj.CellName
|
||||
else:
|
||||
c1 = self.obj[0,0].CellName
|
||||
c2 = self.obj[self.rows-1,self.columns-1].CellName
|
||||
n = f'{c1}:{c2}'
|
||||
return n
|
||||
|
||||
@property
|
||||
def is_cell(self):
|
||||
return hasattr(self.obj, 'CellName')
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self.obj.getDataArray()
|
||||
@data.setter
|
||||
def data(self, values):
|
||||
self.obj.setDataArray(values)
|
||||
|
||||
@property
|
||||
def rows(self):
|
||||
return len(self.data)
|
||||
|
||||
@property
|
||||
def columns(self):
|
||||
return len(self.data[0])
|
||||
|
||||
@property
|
||||
def string(self):
|
||||
return self.obj.String
|
||||
@string.setter
|
||||
def string(self, value):
|
||||
self.obj.String = value
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self.obj.Value
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
self.obj.Value = value
|
||||
|
||||
|
||||
class LORow(BaseObject):
|
||||
|
||||
def __init__(self, rows, index):
|
||||
self._rows = rows
|
||||
self._index = index
|
||||
super().__init__(rows[index])
|
||||
|
||||
def __str__(self):
|
||||
return 'TextTable: Row'
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
return self.obj.Height
|
||||
@height.setter
|
||||
def height(self, value):
|
||||
self.obj.Height = value
|
||||
|
||||
def remove(self):
|
||||
self._rows.removeByIndex(self._index, 1)
|
||||
return
|
||||
|
||||
|
||||
class LORows(BaseObject):
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return 'TextTable: Rows'
|
||||
|
||||
def __len__(self):
|
||||
return self.obj.Count
|
||||
|
||||
def __getitem__(self, key):
|
||||
return LORow(self.obj, key)
|
||||
|
||||
@property
|
||||
def count(self):
|
||||
return self.obj.Count
|
||||
|
||||
def remove(self, index, count=1):
|
||||
self.obj.removeByIndex(index, count)
|
||||
return
|
||||
|
||||
|
||||
class LOTextTable(BaseObject):
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return f'Writer: TextTable - {self.name}'
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
pass
|
||||
|
||||
def __iter__(self):
|
||||
self._i = 0
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
"""Interation cells"""
|
||||
try:
|
||||
name = self.obj.CellNames[self._i]
|
||||
except IndexError:
|
||||
raise StopIteration
|
||||
self._i += 1
|
||||
return self[name]
|
||||
|
||||
def __getitem__(self, key):
|
||||
if isinstance(key, str):
|
||||
if ':' in key:
|
||||
rango = self.obj.getCellRangeByName(key)
|
||||
else:
|
||||
rango = self.obj.getCellByName(key)
|
||||
elif isinstance(key, tuple):
|
||||
if isinstance(key[0], slice):
|
||||
rango = self.obj.getCellRangeByPosition(
|
||||
key[1].start, key[0].start, key[1].stop-1, key[0].stop-1)
|
||||
else:
|
||||
rango = self.obj[key]
|
||||
return LOTableRange(self.obj, rango)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.obj.Name
|
||||
@name.setter
|
||||
def name(self, value):
|
||||
self.obj.Name = value
|
||||
|
||||
@property
|
||||
def rows(self):
|
||||
return LORows(self.obj.Rows)
|
||||
|
||||
|
||||
class LOTextTables(BaseObject):
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return 'Writer: TextTables'
|
||||
|
||||
def __getitem__(self, key):
|
||||
return LOTextTable(self.obj[key])
|
||||
|
||||
|
||||
|
||||
class LOWriterTextPortion(BaseObject):
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return 'Writer: TextPortion'
|
||||
|
||||
@property
|
||||
def string(self):
|
||||
return self.obj.String
|
||||
|
||||
|
||||
class LOWriterParagraph(BaseObject):
|
||||
TEXT_PORTION = 'SwXTextPortion'
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return 'Writer: Paragraph'
|
||||
|
||||
def __iter__(self):
|
||||
self._iter = iter(self.obj)
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
obj = next(self._iter)
|
||||
type_obj = obj.ImplementationName
|
||||
if type_obj == self.TEXT_PORTION:
|
||||
obj = LOWriterTextPortion(obj)
|
||||
return obj
|
||||
|
||||
@property
|
||||
def string(self):
|
||||
return self.obj.String
|
||||
|
||||
@property
|
||||
def cursor(self):
|
||||
return self.obj.Text.createTextCursorByRange(self.obj)
|
||||
|
||||
|
||||
class LOWriterTextRange(BaseObject):
|
||||
PARAGRAPH = 'SwXParagraph'
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
def __str__(self):
|
||||
return 'Writer: TextRange'
|
||||
|
||||
def __getitem__(self, index):
|
||||
for i, v in enumerate(self):
|
||||
if index == i:
|
||||
return v
|
||||
if index > i:
|
||||
raise IndexError
|
||||
|
||||
def __iter__(self):
|
||||
self._enum = self.obj.createEnumeration()
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self._enum.hasMoreElements():
|
||||
obj = self._enum.nextElement()
|
||||
type_obj = obj.ImplementationName
|
||||
if type_obj == self.PARAGRAPH:
|
||||
obj = LOWriterParagraph(obj)
|
||||
else:
|
||||
raise StopIteration
|
||||
return obj
|
||||
|
||||
@property
|
||||
def string(self):
|
||||
return self.obj.String
|
||||
|
||||
@property
|
||||
def cursor(self):
|
||||
return self.obj.Text.createTextCursorByRange(self.obj)
|
||||
|
||||
|
||||
class LOWriterTextRanges(BaseObject):
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
# ~ self._doc = doc
|
||||
# ~ self._paragraphs = [LOWriterTextRange(p, doc) for p in obj]
|
||||
|
||||
def __str__(self):
|
||||
return 'Writer: TextRanges'
|
||||
|
||||
def __len__(self):
|
||||
return self.obj.Count
|
||||
|
||||
def __getitem__(self, index):
|
||||
return LOWriterTextRange(self.obj[index])
|
||||
|
||||
def __iter__(self):
|
||||
self._index = 0
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
try:
|
||||
obj = LOWriterTextRange(self.obj[self._index])
|
||||
except IndexError:
|
||||
raise StopIteration
|
||||
|
||||
self._index += 1
|
||||
return obj
|
||||
|
||||
|
||||
class LOWriter(LODocument):
|
||||
_type = 'writer'
|
||||
TEXT_RANGES = 'SwXTextRanges'
|
||||
_type = 'writer'
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
@ -17,3 +297,61 @@ class LOWriter(LODocument):
|
|||
@zoom.setter
|
||||
def zoom(self, value):
|
||||
self._view_settings.ZoomValue = value
|
||||
|
||||
@property
|
||||
def selection(self):
|
||||
"""Get current seleccion"""
|
||||
sel = None
|
||||
selection = self.obj.CurrentSelection
|
||||
type_obj = selection.ImplementationName
|
||||
|
||||
if type_obj == self.TEXT_RANGES:
|
||||
sel = LOWriterTextRanges(selection)
|
||||
if len(sel) == 1:
|
||||
sel = sel[0]
|
||||
else:
|
||||
log.debug(type_obj)
|
||||
log.debug(selection)
|
||||
sel = selection
|
||||
|
||||
return sel
|
||||
|
||||
@property
|
||||
def string(self):
|
||||
return self._obj.Text.String
|
||||
|
||||
@property
|
||||
def styles(self):
|
||||
ci = self.obj.createInstance
|
||||
return LOStyleFamilies(self.obj.StyleFamilies, ci)
|
||||
|
||||
@property
|
||||
def draw_page(self):
|
||||
"""Get draw page"""
|
||||
return LODrawPage(self.obj.DrawPage)
|
||||
@property
|
||||
def dp(self):
|
||||
return self.draw_page
|
||||
@property
|
||||
def shapes(self):
|
||||
return self.draw_page
|
||||
|
||||
@property
|
||||
def cursor(self):
|
||||
return self.obj.Text.createTextCursor()
|
||||
|
||||
@property
|
||||
def view_cursor(self):
|
||||
return self._cc.ViewCursor
|
||||
|
||||
@property
|
||||
def tables(self):
|
||||
return LOTextTables(self.obj.TextTables)
|
||||
|
||||
def select(self, rango: Any):
|
||||
""""""
|
||||
obj = rango
|
||||
if hasattr(rango, 'obj'):
|
||||
obj = rango.obj
|
||||
self._cc.select(obj)
|
||||
return
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# ~ https://github.com/pyca/cryptography/blob/main/src/cryptography/fernet.py#L27
|
||||
|
||||
import base64
|
||||
import binascii
|
||||
import os
|
||||
import time
|
||||
import typing
|
||||
|
||||
|
||||
_MAX_CLOCK_SKEW = 60
|
||||
|
||||
|
||||
class InvalidSignature(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidToken(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Fernet:
|
||||
def __init__(
|
||||
self,
|
||||
key: bytes | str,
|
||||
backend: typing.Any = None,
|
||||
) -> None:
|
||||
try:
|
||||
key = base64.urlsafe_b64decode(key)
|
||||
except binascii.Error as exc:
|
||||
raise ValueError(
|
||||
"Fernet key must be 32 url-safe base64-encoded bytes."
|
||||
) from exc
|
||||
if len(key) != 32:
|
||||
raise ValueError(
|
||||
"Fernet key must be 32 url-safe base64-encoded bytes."
|
||||
)
|
||||
|
||||
|
||||
self._signing_key = key[:16]
|
||||
self._encryption_key = key[16:]
|
||||
|
||||
|
||||
@classmethod
|
||||
def generate_key(cls) -> bytes:
|
||||
return base64.urlsafe_b64encode(os.urandom(32))
|
||||
|
||||
|
||||
def encrypt(self, data: bytes) -> bytes:
|
||||
return self.encrypt_at_time(data, int(time.time()))
|
||||
|
||||
|
||||
def encrypt_at_time(self, data: bytes, current_time: int) -> bytes:
|
||||
iv = os.urandom(16)
|
||||
return self._encrypt_from_parts(data, current_time, iv)
|
||||
|
||||
|
||||
def _encrypt_from_parts(
|
||||
self, data: bytes, current_time: int, iv: bytes
|
||||
) -> bytes:
|
||||
utils._check_bytes("data", data)
|
||||
|
||||
|
||||
padder = padding.PKCS7(algorithms.AES.block_size).padder()
|
||||
padded_data = padder.update(data) + padder.finalize()
|
||||
encryptor = Cipher(
|
||||
algorithms.AES(self._encryption_key),
|
||||
modes.CBC(iv),
|
||||
).encryptor()
|
||||
ciphertext = encryptor.update(padded_data) + encryptor.finalize()
|
||||
|
||||
|
||||
basic_parts = (
|
||||
b"\x80"
|
||||
+ current_time.to_bytes(length=8, byteorder="big")
|
||||
+ iv
|
||||
+ ciphertext
|
||||
)
|
||||
|
||||
|
||||
h = HMAC(self._signing_key, hashes.SHA256())
|
||||
h.update(basic_parts)
|
||||
hmac = h.finalize()
|
||||
return base64.urlsafe_b64encode(basic_parts + hmac)
|
||||
|
||||
|
||||
def decrypt(self, token: bytes | str, ttl: int | None = None) -> bytes:
|
||||
timestamp, data = Fernet._get_unverified_token_data(token)
|
||||
if ttl is None:
|
||||
time_info = None
|
||||
else:
|
||||
time_info = (ttl, int(time.time()))
|
||||
return self._decrypt_data(data, timestamp, time_info)
|
||||
|
||||
|
||||
def decrypt_at_time(
|
||||
self, token: bytes | str, ttl: int, current_time: int
|
||||
) -> bytes:
|
||||
if ttl is None:
|
||||
raise ValueError(
|
||||
"decrypt_at_time() can only be used with a non-None ttl"
|
||||
)
|
||||
timestamp, data = Fernet._get_unverified_token_data(token)
|
||||
return self._decrypt_data(data, timestamp, (ttl, current_time))
|
||||
|
||||
|
||||
def extract_timestamp(self, token: bytes | str) -> int:
|
||||
timestamp, data = Fernet._get_unverified_token_data(token)
|
||||
# Verify the token was not tampered with.
|
||||
self._verify_signature(data)
|
||||
return timestamp
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _get_unverified_token_data(token: bytes | str) -> tuple[int, bytes]:
|
||||
if not isinstance(token, (str, bytes)):
|
||||
raise TypeError("token must be bytes or str")
|
||||
|
||||
|
||||
try:
|
||||
data = base64.urlsafe_b64decode(token)
|
||||
except (TypeError, binascii.Error):
|
||||
raise InvalidToken
|
||||
|
||||
|
||||
if not data or data[0] != 0x80:
|
||||
raise InvalidToken
|
||||
|
||||
|
||||
if len(data) < 9:
|
||||
raise InvalidToken
|
||||
|
||||
|
||||
timestamp = int.from_bytes(data[1:9], byteorder="big")
|
||||
return timestamp, data
|
||||
|
||||
|
||||
def _verify_signature(self, data: bytes) -> None:
|
||||
h = HMAC(self._signing_key, hashes.SHA256())
|
||||
h.update(data[:-32])
|
||||
try:
|
||||
h.verify(data[-32:])
|
||||
except InvalidSignature:
|
||||
raise InvalidToken
|
||||
|
||||
|
||||
def _decrypt_data(
|
||||
self,
|
||||
data: bytes,
|
||||
timestamp: int,
|
||||
time_info: tuple[int, int] | None,
|
||||
) -> bytes:
|
||||
if time_info is not None:
|
||||
ttl, current_time = time_info
|
||||
if timestamp + ttl < current_time:
|
||||
raise InvalidToken
|
||||
|
||||
|
||||
if current_time + _MAX_CLOCK_SKEW < timestamp:
|
||||
raise InvalidToken
|
||||
|
||||
|
||||
self._verify_signature(data)
|
||||
|
||||
|
||||
iv = data[9:25]
|
||||
ciphertext = data[25:-32]
|
||||
decryptor = Cipher(
|
||||
algorithms.AES(self._encryption_key), modes.CBC(iv)
|
||||
).decryptor()
|
||||
plaintext_padded = decryptor.update(ciphertext)
|
||||
try:
|
||||
plaintext_padded += decryptor.finalize()
|
||||
except ValueError:
|
||||
raise InvalidToken
|
||||
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
|
||||
|
||||
|
||||
unpadded = unpadder.update(plaintext_padded)
|
||||
try:
|
||||
unpadded += unpadder.finalize()
|
||||
except ValueError:
|
||||
raise InvalidToken
|
||||
return unpadded
|
|
@ -9,6 +9,6 @@ USER = 'elmau'
|
|||
IS_WIN = False
|
||||
IS_MAC = False
|
||||
|
||||
LIBO_VERSION = '7.4'
|
||||
LIBO_VERSION = '7.6'
|
||||
LANGUAGE = 'en-US'
|
||||
LANG = 'en'
|
||||
|
|