Integrando Python e ChatGPT com LibreOffice Calc

Integrando Python e ChatGPT com LibreOffice Calc

O Excel agora permite executar scripts Python dentro de uma célula, simplesmente usando a fórmula =PY. No entanto, essa é uma funcionalidade disponível apenas nas licenças pagas. O LibreOffice é um pacote para escritórios, a exemplo do Office da Microsoft, todavia livre e de código aberto. Ele tem planilha, editor de textos, editor de apresentação e muitas outras aplicações. E ainda roda em vários sistemas operacionais, incluindo Linux.

Se você prefere usar ferramentas gratuitas e ainda assim não abrir mão de recursos tais como rodar scripts Python numa célula de planilha, este artigo pode lhe interessar.

Neste post iremos apresentar a LibrePythonista, uma extensão para LibreOffice que nos habilita usar Python dentro de uma planilha Calc, possibilitando que utlizemos a biblioteca pandas, por exemplo, e assim, analisar dados usando um DataFrame. Dado que podemos instalar qualquer biblioteca com essa extensão, iremos instalar e usar a openai, para acessar o ChatGPT e criar conteúdo usando IA.

Tela do LibreOffice Calc com Python

Pré-requisitos

LibreOffice e Python instalados. Tudo vai rodar no seu PC. Não vamos abordar essas instalações aqui.
Iremos tratar apenas da instalação e configuração da extensão LibrePythonista.
Precisamos também das bibliotecas python-dotenv e openai, as quais mostraremos mais adiante como instalá-las.

Instalando a extensão

Inicialmente, acesse o repositório de extensões do LibreOffice, digite LibrePythonista na caixa de pesquisa e clique no botão Search. Você verá esta tela:

Tela de https://extensions.libreoffice.org/

Clique no card da biblioteca e em seguida no botão Download latest. Agora abra o Calc e vá em Ferramentas -> Extensões. Você verá uma janela com as extensões instaladas. Clique em Adicionar e procure o arquivo LibrePythonista.oxt na pasta de downloadas do seu computador. Aceite a licença e quando a instalação finalizar concorde em reiniciar o Calc. Agora você verá o menu LibrePy. Nesse processo de instalação, alguns pacotes são instalados por padrão: pandas e matplotlib, por exemplo.

O último passo antes de ver a extensão em ação é configurar a segurança de macros. É necessário configurar de modo que o Calc permita a execução de macros. O padrão é que não execute. Então vá em Ferramentas -> Opções.

Tela de configutação de segurança de macros

Clique em Segurança e em Segurança de macros. Selecione a segurança Média, a qual exibe uma caixa de diálogo pede a confirmação do usuário antes da execução do script. Daí é só confirmar.

O primeiro script

Com o propósito de ver se está tudo certo. Digite, por exemplo, 10 na célula A1, 20 na célula B1 e, com C1 selecionada, clique no menu LibrePy -> Inserir Python. Ou use o atalho SHIFT+CTRL+ALT+L. Um botão será inserido em C1, indicando que esta célula tem script Python.


Clique no botão dentro da célula e em Editar Código e o editor irá abrir. Digite o código que aparece na imagem e clique em OK. O resultado será exibido na célula C1. A função lp() pega o valor de uma célula e o atribui a uma variável. O restante do script é Python, sendo que na última linha digitamos a variável que será exibida na célula. Quando salvamos a planilha, o script é salvo também. 

Pronto. A extensão está instalada, configurada e funcionando. Mas o que queremos é utilizar o Calc como nossa ferramenta para controle de finanças pesoais, a exemplo que temos feito com Google Sheets. Mais especificamente, queremos acessar o ChatGPT a partir de uma célula a fim de registrar transações e de obter  diagnóstico e insights sobre nossas finanças.

Acessando o ChatGPT

A primeira providencia a tomar a fim de ter acesso à IA é guardar o token da API da OpenAI em lugar seguro. E temos duas opções:
  • Criar uma variável de ambiente no sistema operacional e manter aí o token. O procedimento para isso depende do sistema onde o LibreOffice está executando.
  • Utiizar a biblioteca python-dotenv, conforme já mostramos neste artigo. Neste caso, precisamos manter a chave da API num arquivo denominado .env.
Vamos adotar a segunda opção, a qual funciona em qualquer sistema operacional. Para isso, crie o arquivo .env com a chave OPENAI_API_KEY=sua_chave_da_API_OpenAI, por exemplo, e salve-o em uma pasta apropriada. Eu salvei no mesmo diretório onde salvei a planilha.

Na planilha, eu quero solicitar ao ChatGPT que leia uma frase que está na célula A1, interprete e extraia dados de uma transação financeira e retorne um JSON com esses dados. O script estará na célula B1.

Para isso, nós precisamos de duas bibliotecas externas: python-dotenv, reponsável para ler variáveis de ambiente, no caso OPEN_API_KEY, e openai, para acesso a modelos de IA da OpenAI.

A fim de instalar esses pacotes, abra o menu LibrePy -> Pip -> Instalar pacote Pip. Na janela que será aberta digite o nome do pacote, python-dotenv, e clique em OK. Repita o procedimento para instalar o pacote openai.

Agora selecione a célula B1 e clique no menu LibrePy -> Inserir Python. Ou use o atalho SHIFT+CTRL+ALT+L. O controle será exibido na célula, indicando que ela contém um script Python. clique no controle e em Editar Código. Digite o código no editor:

import os
import json
from openai import OpenAI
from dotenv import load_dotenv
from datetime import date

load_dotenv(dotenv_path = "/home/carlos/development/libreoffice-com-ia/.env")

API_KEY = os.getenv("OPENAI_API_KEY")

client = OpenAI(api_key=API_KEY)

mensagem = lp("A1")

response = client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[
                {
                    "role": "system",
                    "content": """Você é um sistema de categorização de
                        transações financeiras. Responda APENAS em formato
                        JSON válido, sem explicações adicionais."""
                },
                {
                    "role": "user",
                    "content": f"""Extraia da frase abaixo:
                        - valor (float, usar . como separador decimal)
                        - tipo: "Receita" ou "Despesa"
                        - categoria (uma palavra)
                        - data (DD/MM/YYYY; se não informado,
                            usar {date.today().strftime("%d/%m/%Y")})

                    Frase: "{mensagem}"

                    Retorne APENAS JSON, exemplo:
                        {{"valor": 58,.0, "tipo": "Despesa",
                            "categoria": "Alimentacao",
                            "data": "28/11/2025"}}"""
                }
            ],
            max_tokens=800,
            temperature=0.3)
texto = response.choices[0].message.content.strip()
texto

Inicialmente importamos as bibliotecas necessárias, e em seguida carregamos o arquivo .env informando o caminho absoluto na função load_dotenv(). Assegure-se de informar o caminho correto para o seu arquivo .env. Feito isso, lemos o token e inicializamos um cliente OpenAI. Depois, a frase é lida da célula A1. Estamos utilizando o mesmo prompt já usado em artigos passados para chamar o método chat.completions.create().

A chamada retorna um response, e o conteúdo mesmo da resposta é extraido para a variável texto. Daí temos um json exibido na célula em formato string. Observe que na caixa de entrada referente à célula com o código Python, há a seguinte fórmula: =PY.C(PLANILHA();CÉL("ADDRESS"); A1). O último parâmetro indica uma célula ou intervalo, o qual dispara a execução do script, caso seja modificado. Assim, informamos A1 neste caso. 

Nosso objetivo é preencher cada célula subsequente, na mesma linha, com os valores retornados no json. Entretanto, não vimos, na extensão LibrePythonista, uma maneira de o script preencher células diferentes daquela onde o script está executando. Por esse motivo, iremos partir para uma solução alternativa.

Insira Python na célula C1 e digite o seguinte código:

import json

texto = lp("B1")
texto_json = json.loads(texto)

valor = texto_json["valor"]
valor

O que fazemos aqui é pegar o conteúdo de B1 (resposta da IA) e exibir valor na célula. Defina a fórmula na caixa de entrada como =PY.C(PLANILHA();CÉL("ADDRESS");B1), de modo que C1 seja atualizada sempre que B1 se modificar. Repita isso para categoria e tipo nas células D1 e E1, respectivamente. Finalmente, podemos ocultar a coluna B1.

Outra limitação com a qual me deparei é que ao copiar uma célula para outra, o script não é copiado. Então, temos que repetir todo esse processo nas demais linhas.

Solução alternativa usando Python com ScriptForge

Essa parte final, onde os valores do json são escritos nas células seguintes, pode ser feita com uma macro Python usando ScriptForge, a qual é uma biblioteca de ferramentas que simplifica o desenvolvimento de macros e scripts em Python e LibreOffice Basic.

Vamos instalar a extensão APSO (Alternative Python Script Organizer), que simplifica um pouco mais a criação e organização das macros Python. O processo de instalação é o mesmo que fizemos para instalar a LibrePythonista.

Antes de prosseguir é recomendado configurar o editor de sua preferência. Vá em Ferramentas -> Extensões. Clique na extensão APSO e em Opções. Digite o caminho completo do editor na caixa de texto ou clique no botão Escolher para selecionar pelo navegador de pastas. Com isso, o menu Editar na janela do APSO irá abrir o editor que você definiu.

Outro ponto a se preocupar é onde as macros serão salvas. Em geral, o LibreOffice procura as macros em um diretório no perfil do usuário:
  • No Windows: %appdata%\libreoffice\4\user\scripts\python
  • No Linux: ~/.config/libreoffice/4/user/scripts/python
Se as pastas scripts e python não existirem, você precisa criá-las.

Agora, vá em Ferramentas -> Macros -> Organizar scripts em Python. Esta janela será aberta:
Tela do APSO

Com Minhas Macros selecionada, clique em Menu e Criar Módulo. Informe um nome para o módulo. Por exemplo minhas_macros.py e confirme. Agora, clique no nome do módulo e em Menu -> Editar. Digite este código no arquivo criado:

import json
from scriptforge import CreateScriptService

doc = CreateScriptService("Calc")

def fill_cells(args=None):
    value = doc.GetValue("B1")
    texto_json = json.loads(value)

    doc.SetValue("F1", texto_json["valor"])
    doc.SetValue("G1", texto_json["categoria"])
    doc.SetValue("H1", texto_json["tipo"])

g_exportedScripts = (fill_cells, )

Após os imports necessários, o primeiro passo é definir que estaremos lidando com uma planilha do Calc. Em seguida definimos uma função denominada fill_cells(). Ela irá aparecer na janela do APSO e dará a opção de ser executada.

Depois, o valor retornado pelo ChatGPT é lido e convertido em json. E cada um dos campos é escrito numa célula.

Finalmente, nós exportamos as funções que serão nossos scripts a ser executados. Note que, na imagem da janela do APSO, fill_cells aparece abaixo de arquivo, que foi o nome que dei ao meu módulo. Note também que, se você clicar em fill_cells, o botão Executar é habilitado. Clique nele para rodar o script. E, pronto, os valores preenchem as células F1, G1 e H1, conforme programamos no script.

Conclusão

A extensão LibrePythonista ainda está em beta. Possui muitas limitações. No entanto, podemos nos beneficiar do uso de IA para tarefas mais esporádicas, tais como analisar uma planilha de finanças pessoais e nos dar alguns insights que podem nos ajudar a economizar e usar mais racionalmente o nosso dinheiro.

Alternativamente, podemos criar esse script usando ScriptForge e Python. O uso de pacotes externos pode ser um desafio, mas está em beta na extensão APSO a opção de gerenciar pacotes pip, o que pode ser de grande ajuda. No entanto, apesar das limitações, LibrePythonista oferece uma fórmula que possibilita que o script seja executado sempre que uma célula ou intervalo de células seja modificado. A execução de scripts ScriptForge com Python a partir de atualizações de células parece ser bastante desafiador.

De todo modo, num próximo post, iremos tratar como fazer esta integração usando ScriptForge e Python.

Se você tem interesse em outras soluções de macros em Basic ou Python para LibreOffice dê uma olhada em https://stonefull.gumroad.com/l/financial_data_chatgpt_libreoffice

Comentários