Libreoffice (Material para essa suíte)

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

1 curtida