Macros em Pyhton no Libreoffice

Vou usar esse espaço para responder uma pergunta do ( @Rafael_Vilela ), que foi feita no vídeo do youtube do @Dio

Essa foi a pergunta:

Só por curiosidade amigo. Funciona direito os macros do Libreoffice + python? Pergunto, por que só não migrei do microsoft office por conta do VBA. Mas estou doido para usar o Pop OS no trabalho, só uso em casa.

Aqui vai um relato de como usar Macros em Python no LibreOffice e deixar elas embutidas no documento:

Primeiro, no Linux precisa ter o provider python no libreoffice, no Windows normalmente já vem por padrão:

$sudo apt-get install libreoffice-script-provider-python -y

Vai precisar da extensão APSO para editar e embutir as macros em python diretamente no documento (planilha, texto…) do libreoffice.

nas configurações do APSO eu escolho editor de python que uso - VS Code:
No Linux: /usr/share/code/code
No Windows, versão Portable: C:\Portable\VSCode.[Portable]\Code.exe

No Documento:
(Shift + alt + F11) exibe o gerenciador de macros em pyhton, existe um inconveniente, a macro só pode ser editada enquanto esse gerenciador estiver sendo exibido. Como ele usa um editor externo de python vc precisa ficar atento. Se vc fechar a janela do Gerenciador de macro no libreoffice, tudo o que vc editar no arquivo python que esta no editor python será perdido.

A dica é fechou o Gerenciador de Janela das macros, fecha também o arquivo no VScode. Se precisar editar novamente aperta (Shit + alt + F11) e edita novamente a macro pelo editor externo.
Menu > Edit , no Gerenciador de Janela das macros

Esse foi o problema que eu tive até agora, já perdi muitas edições por esse problema. Pois para testar a macro eu normamente fecho o gerenciador de macros e uso o documento do libreffice normalmente para efetuar uma ação, o problema é que o editor externo mantem o arquivo do modulo python aberto. Se a macro não se comportou como o esperado, e eu preciso reedita-la, é muito mais intuitivo eu ir direto no Vs code que já está com o arquivo aberto e continuar mexendo no código da macro. Esse é o problema…

Para fazer a edição eu tenho que fechar o arquivo no VScode e abrir novamente o Gerenciador de macro em python e abir novamente modulo pelo editor externo.

Mas como acho a linguagem em pyhton mais fácil e mais poderosa de usar que vba, eu me adaptei a contornar esse problema…


Indico também a extensão ZAZ-pip pra adicionar pacotes do python para usar no libreoffice:


https:// vimeo.com/369488703

#################
veja tambem:
https://wiki.documentfoundation.org/Macros/Python_Guide

https://ask.libreoffice.org/pt-br/question/188812/documentacao-para-macros-basic-calc-referencia/

obs:
em opções do Libreoffice, vc deve alterar a segurança das macros para permitir sua execução

3 Curtidas

Complemento:

Nas opções da extensção APSO eu costumo preencher o campo Content of new module com um código base que eu uso com frequencia, dai já abre o arquivo python com esse conteúdo personalizado:

# -*- coding: cp1252 -*-
from __future__ import unicode_literals
import uno
from com.sun.star.awt import MessageBoxButtons as MSG_BUTTONS

CTX = uno.getComponentContext()
SM = CTX.getServiceManager()
ODOC = XSCRIPTCONTEXT.getDocument()

def create_instance(name, with_context=False):
    if with_context:
        instance = SM.createInstanceWithContext(name, CTX)
    else:
        instance = SM.createInstance(name)
    return instance

def apsoConsole(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 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 get_Documents_linux():
    """ Determina o nome da pasta Documents no Linux, para o respectivo idioma
        https://wiki.archlinux.org/index.php/XDG_user_directories_(Portugu%C3%AAs)
    """

    #abre o arquivo user-dirs.dirs no diretorio de .config do usuário Linux
    xdgFile = os.path.join(os.path.expanduser("~"), ".config", "user-dirs.dirs")
    if not os.path.isfile(xdgFile):
        #se o arquivo não existe, adota o nome padrão em pt-BR para a pasta Documentos
        doc_name = 'Documentos'
    else:
        fs = open(xdgFile,'r')
        data = fs.read()
        fs.close()
        
        #retorna a linha que contém o valor da pasta do sistema 'XDG_DOCUMENTS_DIR'
        doc_paths = re.findall(r'XDG_DOCUMENTS_DIR=\"([^\"]*)', data)
       
        #remove a string '$HOME/'
        doc_name = doc_paths[0].replace('$HOME/', '')

    return doc_name 

def changeFocus(oPlan, tagFoco):
    """ Muda o foco do mouse para a célula tagFoco
        tagFoco => é o nome da célula que receberá o foco, ex: "A1"
    """
    oFoco = oPlan.getCellRangeByName(tagFoco)
    ODOC.getCurrentController().select(oFoco)

def dlgUnoPrint(oPlan, tagFoco):
    """
        tagFoco => é o nome da célula que receberá o foco, ex: "A1"
    """

    #muda o foco do mouse para a célula tagFoco
    changeFocus(oPlan, tagFoco)

    #abre o diálogo de impressão do Libreoffice
    call_dispatch(ODOC, '.uno:Print')

    return

def quietPrint(oPlan, tagFoco):
    """
        tagFoco => é o nome da célula que receberá o foco, ex: "A1"
    """

    #muda o foco do mouse para a célula tagFoco
    changeFocus(oPlan, tagFoco)
    from com.sun.star.beans import PropertyValue
    p = PropertyValue()
    p.Name = "Imprimir"
    p.Value = 0
    ODOC.print( (p,) ) 

    return
#=========================================================================================
#*****************************************************************************************

Exemplo de uma macro do CALC pra exibir o dialogo de impressão, usando o codigo personalizado acima:

def minha_macro(*args):
    oSheets = ODOC.getSheets()
    planName = oSheets.getByName("Planilha1")
    dlgUnoPrint(planName, "A1")
2 Curtidas

vocês conhecem algum curso / material bom demonstrando o que é possível fazer com estas Macros?

2 Curtidas

Vc pode fazer praticamente tudo o que o python te permite, pois tem os modulos padrão do python pre instalados e com a extensão Zaz-pip permite instalar os modulos do site pip · PyPI

  • Com python vc pode fazer conexão com banco de dados e incluir o resultado de uma consulta diretamente na planilha do Calc.

  • Pode abrir um arquivo txt, csv… , fazer a manipulação dos dados e inserir apenas o que vc precisa na planilha do Calc.

  • Pode fazer webscraping (requisição http e manipulação dos dados via beautifulsoup4) e inserir os dados de uma pagina html diretamente na planilha do Calc.


não conheço nehum curso específico em macro python no libreoffice, mas vc precisa ter conhecimento em python geral. E para trabalhar com o libreoffice vai precisar conhecer a API UNO. Se já tiver conhecimento em VBA vai ser facil a migração, pois o vba interage com essa API UNO do libreoffice.

é aconselhavel tambem ter a extensão MRI instalada para ver as propriedades de cada objeto da API UNO.

Para ler um range de celulas numa planilha do CALC vc usa o .getDataArray()
Para escrever um range de celulas numa planilha do CALC vc usa o .setDataArray()

exemplo de como pegar os dados de um range de celulas do CALC e passar isso pra uma variavel em python (usando o conteudo template padrão que eu mostrei no post acima):

ODOC = XSCRIPTCONTEXT.getDocument()
oSheets = ODOC.getSheets()
planAgenda = oSheets.getByName("Agenda")
cellContent = planAgenda.getCellRangeByName('A2:E5')
valueContent = cellContent.getDataArray()

Onde ‘Agenda’ é o nome da planilha (Aba), e A2:E5 é o intervalo onde estão os dados nessa planilha.


Exemplos Python - Libreoffice
https://wiki.documentfoundation.org/Macros/Basic/Calc/Sheets#Sheets
https://wiki.documentfoundation.org/Macros/Python_Guide

Macro tutorial VBA

Livro macro VBA - Andrew Pitonyak
https://www.pitonyak.org/oo.php
https://www.pitonyak.org/OOME_4_0.odt

2 Curtidas

Olha, ao meu ver, se alguém precisa recorrer a Macros, o ideal é que essa pessoa opte por uma ferramenta mais apropriada para o trabalho em questão.

1 Curtida

Eu até concordo. Mas macros automatizam rotinas e facilita a vida do usuário.

Por exemplo no trabalho não tenho permissão de administrador do windows, então não consigo instalar nenhum programa. E o pessoal do DTI não faz a instalação de programas extras por questões de segurança.

Aqui usamos um programa tipo CRUD proprietario que também gera um relatorio CSV, porém esse csv é muito bagunçado. E minha chefia exige o relatório com um layout totalmente diferente desse programa proprietario. Então com uma macro python posso manipular os dados desse CSV e criar o relatório com um único clique. coisa que quando fazia manualmente levava horas e horas para fazer.

Depois que aprendi macros em python, meu serviço ficou muito mais fácil…

2 Curtidas

Caramba, que incoveniente :neutral_face:

Cara, minha situação é muito parecida com a citada pelo @mrkalvin

Claro que temos BILHÕES de ferramentas mais decentes, inclusive, lembro uma vez que discuti numa boa com um colega que era pró software proprietário justamente porque utilizava Excel (tinha comprado uma licença do próprio bolso) para gerar folha de pagamento, e eu falava que era ÓBVIO que não se implementaria isto (tão cedo) no CALC, porque existem outras ferramentas muito mais robustas que vão verificar uma série de situações.

Enfim, eu tenho um problema muito sério no trabalho que este tipo de solução pode me ajudar MUITO. No meu caso, penso em integrar relatórios orçamentários e criar um tipo de informação que eu até pego, mas um computador é muito mais rápido e confiável.
Não haverá sistema da TI (inclusive, com uma hipótese que nem ouso comentar), não tenho acesso de administrador e uma série de restrições de acesso. Minha ideia: além do meu problema, numa segunda iteração dar acesso a minha hospedagem e permitir alguns compartilhamentos de maneira inteligente.

Infelizmente, muito pouca gente em TI mantém o tesão após formar.

Aqui alem de não ter permissão de administrador, a internet é via proxy. Então pra fazer conexão com a internet eu preciso adicionar os dados da proxy nos script pyhton.

import os

PROXY_HOST = "100.00.0.1" #endereço do host
PROXY_PORT = "8080" #porta
PROXY_AUTH_USER = "meu_usuario_windows"
PROXY_AUTH_PASS = "minha_senha_windows"

os.environ['http_proxy'] = f'''http://{PROXY_AUTH_USER}:{PROXY_AUTH_PASS}@{PROXY_HOST}:{PROXY_PORT}'''
os.environ['https_proxy'] = f'''http://{PROXY_AUTH_USER}:{PROXY_AUTH_PASS}@{PROXY_HOST}:{PROXY_PORT}'''

qualquer script pyhton é só adicionar esse código no inicio do arquivo e vou ter a conexão com internet.

por exemplo: Uso o Libreoffice portable no Windows, e pra instalar o pip via extensão ZAZPip, eu adiciono esse código acima no arquivo ‘ZAZPip.py’.
que esta na pasta:

‘C:\Portable\LibreOffice.[Portable]\Data\settings\user\uno_packages\cache\uno_packages\lu60401jopq.tmp_\ZAZPip_v0.5.0.oxt\ZAZPip.py’

obs: ‘C:\Portable\LibreOffice.[Portable]’ é o local onde foi extraido o libreoffice portable.

provavelmente para outras pessoas só muda o nome da pasta temporaria (lu60401jopq.tmp_).

obs: essa conexão continua limitada as permissões da sua proxy, os mesmos sites restritos pelo navegador também serão restristos pelos scripts python.

Offtopic:

Se quiser uma solução apenas com python, pode usar a versão Portátil do python:
Portable Python - Browse Files at SourceForge.net

Para instalar modulos via pip é só fazer via Console-Launcher.exe que está na pasta:
C:\Pasta_onde_foi_descompactado_o_python_portable\Console-Launcher.exe

se usar proxy é só inserir os dados com sua proxy, ao abrir o Console-Launcher.exe, digite o código abaixo com seus dados, no Console-Launcher:
SET HTTPS_PROXY=http://meu_usuario_windows:minha_senha_windows@100.00.0.1:8080

Depois pode usar o Console-Launcher portable para fazer acesso a internet
ex: pip install requests
ou instalar qualquer outro modulo, ex: pip install beautifulsoup4

E para os scripts feitos para rodar no python portable vai precisar inserir nesses scripts o “os.environ[‘http_proxy’]” igual indicado par ao libreoffice!

Meu amigo, muito obrigado pela informação e por te lembrado, vou estudar mais, testarei no windows 10 no trabalho e em casa no POP OS. Sou muito grato. Já até favoritei.

Só um outro detalhe, na versão portable do libreoffice para windows 10 na versão 7 em diante, está tendo um problema com o Content of new module da extensão Apso. O libreoffice está removendo toda a tabulação e quebra de linha do código, então vai ser melhor copiar e colar de um arquivo que esteja correto.

As configurações do libreoffice são salvas nesse arquivo:
registrymodifications.xcu

Quando fecha o libreoffice, eles está automaticamente “limpando o arquivo registrymodifications.xcu” e removendo a tabulação e quebras de linha no interior das tags xml onde é salvo o Content of new module ao APSO.

No Linux não tive esse problema.
Não testei na versão instalada do Windows

1 Curtida

Muito obrigado amigo. Vou cair fundo em todas as dicas que você deu. Obrigado mesmo!