Aqui um video de como usar a extensão APSO, que é responsável por embutir a macro no documento do libreoffice:
obs: usei o VS Code como editor de python
obs2: usei um código template com as funções mais comuns, assim sempre que crio uma macro já insere esse template no meu arquivo
obs3: para usar uma macro em python é igual em basic, ex: escreve sua macro no editor externo, depois insere um botão e adiciona a macro no evento do clique do mouse
Fiz um arquivo de exemplo para vc estudar com as operações básicas de macros em pyhton no calc:
Código do ‘Content of new module’ com as funções básicas
# -*- coding: UTF-8 -*-
from __future__ import unicode_literals
import uno
from com.sun.star.awt import MessageBoxButtons as MSG_BUTTONS
from pathlib import Path
'''+===================+
| Variáveis Globais |
+===================+'''
CTX = uno.getComponentContext()
SM = CTX.getServiceManager()
#---
def create_instance(name, with_context=False):
if with_context:
instance = SM.createInstanceWithContext(name, CTX)
else:
instance = SM.createInstance(name)
return instance
def openConsole(event=None):
"""
https://extensions.libreoffice.org/extensions/apso-alternative-script-organizer-for-python
"""
create_instance("apso.python.script.organizer.impl")
from apso_utils import console
#console()
console(BACKGROUND=0x0, FOREGROUND=0xD3D7CF)
return
def closeConsole(*args):
import theconsole
try:
theconsole.console.enddialog()
except AttributeError:
pass
def msg(message, title='LibreOffice', buttons=MSG_BUTTONS.BUTTONS_OK, type_msg='INFOBOX'):
""" MSG_BUTTONS = BUTTONS_OK = 1, BUTTONS_OK_CANCEL = 2, BUTTONS_YES_NO = 3, BUTTONS_YES_NO_CANCEL = 4, BUTTONS_RETRY_CANCEL = 5, BUTTONS_ABORT_IGNORE_RETRY = 6
https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1awt_1_1MessageBoxButtons.html
type_msg = MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX
https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1awt.html#ad249d76933bdf54c35f4eaf51a5b7965
"""
toolkit = create_instance('com.sun.star.awt.Toolkit')
parent = toolkit.getDesktopWindow()
mb = toolkit.createMessageBox(parent, type_msg, buttons, title, str(message)+'\n\n')
return mb.execute()
def call_dispatch(doc, url, args=()):
"""
https://wiki.documentfoundation.org/Development/DispatchCommands
"""
frame = doc.getCurrentController().getFrame()
dispatch = create_instance('com.sun.star.frame.DispatchHelper')
dispatch.executeDispatch(frame, url, '', 0, args)
return
def _toProperties(**kwargs):
"""
função auxiliar para call_dispatch, quando ela usa argumentos, ex de quando é usada:
call_dispatch(doc, '.uno:InsertDoc', _toProperties(Name='arquivo.odt', Filter='writer8'))
O retorno dessa função será uma tupla de dicionários ({key1='valor1'}, {key2='valor2'}, ....)
"""
props = []
for key in kwargs:
prop = PropertyValue()
prop.Name = key
prop.Value = kwargs[key]
props.append(prop)
return tuple(props)
#=========================================================================================
#Fim do 'Content of new module' {código template com as funções mais comuns}
#*****************************************************************************************
Aqui o código da macro propriamente dita:
def mostrar_infos(*args):
openConsole()
doc = XSCRIPTCONTEXT.getDocument()
planilha_ativa = doc.CurrentController.ActiveSheet
nome_ativa = planilha_ativa.Name
sheets = doc.getSheets()
total_de_folhas = len(sheets)
this_doc_url = doc.URL
this_doc_path = uno.fileUrlToSystemPath(this_doc_url)
absolute_path = Path(this_doc_path).parent
str_doc_path = str(this_doc_path)
str_absolute_path = str(absolute_path)
print(nome_ativa)
print(total_de_folhas)
print(str_doc_path)
print(str_absolute_path)
mymessage = f'''Nome da panilha atual: {nome_ativa}\n
Número total de abas 'planilhas': {str(total_de_folhas)}\n
Caminho do documento: {str_doc_path}\n
Diretório do documento: {str_absolute_path}'''
msg(mymessage, title='LibreOffice', buttons=MSG_BUTTONS.BUTTONS_OK, type_msg='INFOBOX')
def print_dialog(*args):
doc = XSCRIPTCONTEXT.getDocument()
call_dispatch(doc, '.uno:Print')
def criar_documento_em_branco(*args):
desktop = XSCRIPTCONTEXT.getDesktop()
model = desktop.getCurrentComponent()
if not hasattr(model, "Text"):
document = desktop.loadComponentFromURL("private:factory/swriter","_blank", 0, () )
def abrir_documento(caminho_arquivo):
arquivo = Path(caminho_arquivo)
if arquivo.is_file():
try:
desktop = XSCRIPTCONTEXT.getDesktop()
myFileUrl = uno.systemPathToFileUrl(str(arquivo))
document = desktop.loadComponentFromURL(myFileUrl, '_blank', 0, ())
except Exception as e:
mymessage = f'''Erro ao abrir arquivo\n{e}'''
msg(mymessage, title='LibreOffice', buttons=MSG_BUTTONS.BUTTONS_OK, type_msg='ERRORBOX')
else:
mymessage = f'''Esse arquvio não existe:\n{caminho_arquivo}'''
msg(mymessage, title='LibreOffice', buttons=MSG_BUTTONS.BUTTONS_OK, type_msg='ERRORBOX')
def abrir_doc_existente(*args):
#meu_arquivo = '/home/MEU_USUARIO/qualquer.ods'
meu_arquivo = str(Path.home() / 'qualquer.ods')
print(meu_arquivo)
abrir_documento(meu_arquivo)
def ler_celula(*args):
doc = XSCRIPTCONTEXT.getDocument()
sheets = doc.getSheets()
planConfig = sheets.getByName('Configuração')
mycelula = planConfig['A2']
conteudo_celula = mycelula.getString()
msg(conteudo_celula)
def ler_range(*args):
doc = XSCRIPTCONTEXT.getDocument()
planilha_ativa = doc.CurrentController.ActiveSheet
myrange = planilha_ativa.getCellRangeByName('A2:C4')
conteudo_matriz = myrange.getDataArray()
print(type(conteudo_matriz))
print(conteudo_matriz)
msg(str(conteudo_matriz))
def escrever_range(*args):
doc = XSCRIPTCONTEXT.getDocument()
planilha_ativa = doc.CurrentController.ActiveSheet
myrange = planilha_ativa.getCellRangeByName('A15:D18')
my_matriz = (
(10, 'Azul', 100.0, 'teste1'),
(11, 'Amarelo', 200.0, 'teste2'),
(12, 'Vermelho', 300.0, 'teste3'),
(12, 'Verde', 400.0, 'teste4')
)
myrange.setDataArray(my_matriz)
def escrever_celula(*args):
doc = XSCRIPTCONTEXT.getDocument()
planilha_ativa = doc.CurrentController.ActiveSheet
mycelula = planilha_ativa['A21']
#Escrever Texto
#myvalor = 'Hello'
#mycelula.setString(myvalor)
#Escrever Número
myvalor = 45.00
mycelula.setValue(int(myvalor))
#Esvrever Fórmula, fórmula deve estar em inglês
#myformula = '=SUM(5+10)'
#mycelula.setFormula(myformula)
obs: Quando vai trabalhar no calc, o conteúdo das planilhas é uma matriz multidimensional - é uma tupla de tuplas. Onde cada linha do CALC é uma tupla separada e cada item dessa tupla se refere a uma coluna dessa linha do CALC