Crie arquivos PDF a partir de modelos com Scripts Python e Google

muitas vezes, é útil criar arquivos PDF a partir de seus scripts Python. Se você está criando faturas, cartas, relatórios, ou quaisquer outros documentos que contêm um monte de repetição de formatação, mas apenas um pouco de conteúdo dinâmico, adicionando alguma automação pode economizar muitas horas.

você tem algumas opções para isso. Os habituais são:

  1. Use uma biblioteca PDF como o reportlab para gerar arquivos PDF diretamente (e.g. https://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/)
  2. Use uma biblioteca HTML templating como Jinja2 e converter de HTML para PDF (e.g. http://pbpython.com/pdf-reports.html)
  3. Use uma API de terceiros como https://pdfgeneratorapi.com/.

para a opção 1, gerar PDFs diretamente do interior do Python pode tornar a formatação muito difícil. Você tem que desenhar qualquer coisa que você precisa elemento por elemento, usando código, e mesmo uma vez que você tem um modelo olhando como você quer, é difícil de manter.

A Opção 2 pode muitas vezes funcionar melhor, mas você ainda tem que construir o boilerplate Jinja HTML, e às vezes a conversão HTML para PDF não sai como você esperava.

A Opção 3 requer que você construa o modelo primeiro usando a interface web de um serviço online. Embora você tenha uma interface drag-and-drop, é bastante desajeitado e difícil de fazer o seu modelo olhar como você quer. Normalmente, você também tem que pagar para usar o serviço.

enquanto uma das opções acima pode funcionar para você, se você não gosta de nenhuma delas, você também pode hackear uma API de geração de documentos com base no Google Drive. Você terá uma API gratuita, e será capaz de usar o Google Docs como sua ferramenta de template, que é bastante poderosa e tem muitos modelos pré-existentes para coisas como faturas, cartas e CVs.

comecei com um modelo de factura que encontrei online. Parece-se com isto.:

 modelo de fatura do Google Docs

neste tutorial, vamos caminhar através da criação de uma API que gera estas faturas e permite-lhe programaticamente inserir o número de fatura de um script externo em Python. Na realidade, você precisa fazer o mesmo para muitos outros campos, mas vamos começar com um exemplo simples por razões de demonstração.

estaremos escrevendo algumas linhas de código de Script do Google App, e algumas linhas de código Python.

criar um documento modelo

Use um dos modelos de documentos do Google, procure online por um que corresponda às suas necessidades, ou construa o seu próprio em docs.google.com. (você vai precisar de uma Conta Google).

adicione espaços onde necessita de informação dinâmica. No exemplo abaixo, eu adicionei a fatura no {invoice_id} no lugar do id ” 456 ” que eu tinha no documento original. Não há nada de especial nesta sintaxe — nós estaremos usando uma função básica de pesquisa e substituição mais tarde para trocar isso para a informação real, então use algo que é improvável de realmente aparecer no documento final.

tome nota do seu id do documento, que é a parte seleccionada na barra de URL.

 modelo de fatura com substituição

configurar um script Google personalizado

vá para o Google Drive, pressione “novo” no canto superior esquerdo. Em” More”, selecione “Google Apps Script” se estiver disponível ou “conectar mais apps” se você não vê.

conectar mais aplicativos

procurar “apps script” e escolher conectá-lo. Você pode ver algumas mensagens de aviso perguntando se você confia em si mesmo. Diz que sim.

adicionando Apps Script

uma vez que você pode criar um novo script App, você verá um script padrão em branco que aparece como segue.

Script em branco do Google Apps

Delete o código que você vê lá, e substitua-o por uma função createDocument que parece como se segue.

function createDocument(invoice_id) { var TEMPLATE_ID = '1Ybq8r_SiWu4Z4-_Z6S0IW1L8FJywfpjPAATPCvvkKk8'; var documentId = DriveApp.getFileById(TEMPLATE_ID).makeCopy().getId(); drivedoc = DriveApp.getFileById(documentId); drivedoc.setName("Invoice " + invoice_id); doc = DocumentApp.openById(documentId); var body = doc.getBody(); body.replaceText('{invoice_id}', invoice_id); drivedoc.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT); return "https://docs.google.com/document/d/" + documentId + "/export?format=pdf";}

na linha 2, Desligue o TEMPLATE_ID com o ID do documento que copiou da barra de URL na sua templated Google Doc.

este código encontra o cod templated, cria uma cópia dele e define o nome do arquivo para “fatura” Mais o que invoice_id nós passamos dentro. Ele então abre o novo arquivo através do DocumentApp (em vez do aplicativo Drive, para que possamos realmente obter o conteúdo do arquivo e editá-los). Ele procura o doc para a substituição que adicionamos ({invoice_id}) e substitui-o com o real invoice_id que a função toma como entrada. Em seguida, define o documento para ser acessível ao público e retorna uma URL que irá diretamente para uma exportação de PDF para esse documento.

abaixo desta função, adicione outra chamada doGet. Embora a função anterior possa ser chamada de qualquer coisa, doGet é uma função especial em Scripts do Google Apps, então você terá que nomeá-la exatamente doGet. Esta função irá lidar com os pedidos de entrada da web depois de termos implantado o nosso aplicativo.

o código para a função doGet é o seguinte. Colar isto por baixo da função anterior createDocument().

function doGet(e) { var invoice_id = e.parameter.invoice_id; var url = createDocument(invoice_id); return ContentService.createTextOutput(url);}

isto toma o invoice_id como um parâmetro URL, passa isto para a nossa função createDocument que acabamos de escrever, e devolve o URL do documento criado como texto simples.

publicar a nossa API

do menu” publicar”, seleccionar “implantar como aplicação web”

Implay as web app

you’ll be asked to name the project. Dá-lhe um nome como “API PDF” ou qualquer outra coisa que queiras.

 nomeando o projeto

você verá um novo menu para definir as opções para a implantação do seu aplicativo web.

implantar opções

adicionar uma mensagem como ” implantação inicial “sob onde diz” Novo “e escolher” qualquer um, mesmo anônimo ” das configurações de acesso. Deixe as configurações de execução como “eu”.

Aviso: Se você compartilhar o link em um lugar público, as pessoas podem abusar do serviço e spam com pedidos automáticos. O Google pode bloquear a sua conta por abuso se isso acontecer, por isso mantenha o link seguro.

carregue no botão implantar e anote a URL que vê no próximo pop up.

o URL da sua aplicação

Add”?invoice_id=1″ ao final do URL e visite-o no seu navegador. Deve parecer algo como

https://script.google.com/macros/s/AKfycbxDiKpTGqMijZmU8-0cPj06DBFjDOPYZJ9IFvhcO111GCh8jqxC/exec?invoice_id=1

se tudo correu bem, você deve ver um link do Google Docs exibido.

Resposta da nossa aplicação web

se visitar o URL, deve ser descarregado um PDF da factura com a substituição com 1.

actualizando a aplicação

se vir um erro em vez disso, ou não obtiver uma resposta, provavelmente cometeu um erro no código. Você pode alterá-lo e atualizar a implantação da mesma forma que você inicialmente implantou. A tela de atualização é apenas ligeiramente diferente da tela de implantação.

atualizar as opções de implantação

a única coisa complicada é que você tem que selecionar “Novo” como a versão para cada mudança que você faz. Se você fizer alterações ao código e atualizar uma versão anterior, as alterações não farão efeito, o que não é óbvio a partir da IU. (Você pode ver que me levou algumas tentativas para fazer isso direito.).

criando as nossas facturas em Python

agora podemos criar facturas e salvá-las localmente de um script em Python. O seguinte código mostra como gerar três faturas em um laço for.

import requestsurl = "https://script.google.com/macros/s/AKfycbyYL5jhEstkuzZAmZjo0dUIyAmzUc1XL5B-01fHRHx8h63cieXc/exec?invoice_id={}"invoice_ids = for invoice_id in invoice_ids: print("processing ", invoice_id) response = requests.get(url.format(invoice_id)) print("file generated") response = requests.get(response.content) print("file downloaded") with open("invoice{}.pdf".format(invoice_id), "wb") as f: f.write(response.content)

Note que o processo de criação e download é bastante lento, por isso levará alguns segundos para cada factura que criar.

você provavelmente notou que esta é uma solução bastante “hacky” para gerar arquivos PDF de dentro do Python. A funcionalidade “substituir” é bastante limitada em comparação com uma linguagem de templação adequada, e passar dados através de um pedido de get também tem limitações. Se você passar por algo mais complicado do que uma identificação de fatura, você vai codificar os dados primeiro. Você pode fazer isso em Python usando o módulo urllib.parse. Uma modificação exemplo do script Python para lidar com dados mais complicados é a seguinte.

import requestsimport urllib.parseurl = "https://script.google.com/macros/s/AKfycbyYL5jhEstkuzZAmZjo0dUIyAmzUc1XL5B-01fHRHx8h63cieXc/exec?"invoice_ids = for invoice_id in invoice_ids: print("processing ", invoice_id) payload = {"invoice_id": invoice_id} u = url + urllib.parse.urlencode(payload) response = requests.get(u) print("file generated") response = requests.get(response.content) print(response.content) print("file downloaded") with open("invoice{}.pdf".format(invoice_id), "wb") as f: f.write(response.content)

mas ainda existem limitações de que tipo de dados e quanto você pode passar apenas usando URLs, então você teria que modificar o script para usar pedidos de POST em vez disso, se você estivesse enviando um monte de dados dinâmicos.

também é bastante lento em comparação com alguns dos outros métodos que discutimos no início, e o Google tem algumas limitações em quantos arquivos você pode criar automaticamente desta forma.

dito isto, ser capaz de gerar modelos usando o Google Docs pode ser rápido e poderoso, então você vai precisar avaliar os tradeoffs para si mesmo.

também note que este é um exemplo bastante inventado, onde poderíamos ter executado o script Python dentro do ecossistema do Google, e evitou a necessidade de criar uma API pública de frente que poderia ser abusada se outras pessoas descobrissem a URL. No entanto, você pode ter uma aplicação Python existente, não hospedado no Google, que você precisa se conectar com arquivos PDF gerados automaticamente, e este método ainda permite que você configure um “microservice” auto-contido dentro do ecossistema do Google que permite a fácil geração de PDF.

conclusão