Executando verificação de segurança...
2

Gerando PDFs personalizados com Python

Imagine a seguinte situação: você possui uma base de dados com várias informações, como nome, data de nascimento, e-mail, endereço, cidade, estado e CEP de diversas pessoas. Agora, você precisa criar um documento em PDF estilizado para cada indivíduo. Como você faria isso de forma rápida e eficiente?

  1. O primeiro passo dessa tarefa é criar um tipo de arquivo “template”, no qual possamos editar apenas as informações necessárias para cada linha da nossa base. Para resolver essa etapa, optei por usar HTML com Bootstrap. Essa escolha se mostrou ideal, pois o HTML é um formato de arquivo de texto fácil de modificar e que permite personalização completa.

  2. O segundo passo é adicionar marcadores a esse template, como {% dado_personalizado %}, que serão substituídos pelos dados reais posteriormente. A ideia é simplesmente utilizar a função replace do Python para alterar os dados personalizados. Por exemplo:

dados = {
    'nome': 'Daniel'
}

conteudo_do_html = '<p> {% nome %} </p>'

for dado in dados:
    conteudo_do_html = conteudo_do_html.replace(f'{{% {dado} %}}', dados[dado])

Nesse exemplo, a variável conteudo_do_html teria o valor ‘{% nome %}’ substituído pela string ‘Daniel’. Entendeu a ideia?

  1. O terceiro passo é colocar isso em prática, lendo o template e gerando um novo HTML com o conteúdo substituído para cada linha da nossa base de dados.
# Itera sobre as linhas do dataframe
for i in range(df.shape[0]):
    
    # Copia o conteúdo html para uma variável auxiliar
    conteudo_html_aux = conteudo_html
    
    # Cria um dicionário com os dados da linha atual
    dados = {
        'identificador': df.loc[i, 'identificador'],
        'nome': df.loc[i, 'nome'],
        'nascimento': df.loc[i, 'data_de_nascimento'],
        'rua': df.loc[i, 'rua'],
        'cidade': df.loc[i, 'cidade'],
        'estado': df.loc[i, 'estado'],
        'cep': df.loc[i, 'cep'],
    }
    
    # Define os nomes dos arquivos html e pdf com o identificador do dado
    identificador = dados['identificador']
    html_file = f'{identificador}.html'
    pdf_file = f'{identificador}.pdf'
    
    # Substitui os dados personalizados no conteúdo html
    for dado in dados:
        conteudo_html_aux = conteudo_html_aux.replace(f'{{% {dado} %}}', f'{dados[dado]}')

    # Cria um arquivo html com o conteúdo personalizado
    arquivo = open(os.path.join(path, 'formularios', html_file), mode='w', encoding='utf-8')
    arquivo.write(conteudo_html_aux)
    arquivo.close()
  1. Por fim, o quarto e último passo é utilizar uma biblioteca que converta o HTML para PDF. No meu caso, utilizei a biblioteca pyhtml2pdf, que se mostrou a melhor opção para conversões de HTML para PDF. Diferentemente de outras bibliotecas, ela literalmente renderiza o HTML para gerar um PDF, garantindo que o resultado final seja fiel ao HTML original.
# Define o caminho do arquivo html
path_html = os.path.join(path, 'formularios', html_file)

# Converte o arquivo html em pdf
converter.convert(f'file:///{path_html}', os.path.join(path, 'formularios/formularios_gerados', pdf_file))

# Remove o arquivo html
os.remove(path_html)

Você pode conferir mais sobre este projeto acessando o meu repositório no GitHub:
https://github.com/danielneresrodrigues/robo-pdf/

Carregando publicação patrocinada...
1

Já fiz algo desse tipo, mas usei a formatação de strings antiga do python, substituindo os marcadores na string pelos valores de mesmo nome presentes no dict para formar o html estático e depois converter para pdf.
Um exemplo básico:

# Variável
nome = "Cleiton"

# Dicionário de substituição
dados = {'nome': nome}

# Estrutura básica do HTML com formatação
html_template = """
<!DOCTYPE html>
<html>
<head>
    <title>Olá, Mundo!</title>
</head>
<body>
    <h1>Bem-vindo, %(nome)s!</h1>
    <p>Esta é uma página HTML simples.</p>
</body>
</html>
"""

# Substituição dos valores no template
html_final = html_template % dados

# Imprime o HTML resultante
print(html_final)

O % é chamado de "operador de formatação" e é usado para substituir marcadores de posição em uma string pelos valores de um dicionário ou tupla.

1

Muito bom!

Eu montei o HTML de exemplo com este padrão "{% dado %}" pois estou acontumado com esse cenario com templates em Django.

Mas realmente pra uma abordagem mais simples o operador de formatacao seria mais facil de aplicar.

Muito obrigado por compartilhar.