Exportação de Resultados SQL Diretamente para Excel Formatado com Python e Pandas
Em ambientes corporativos, a extração de dados armazenados em bancos de dados relacionais (como PostgreSQL, MySQL, SQL Server ou SQLite) é uma rotina diária para analistas e engenheiros de dados. Contudo, entregar resultados em arquivos CSV brutos ou dados sem formatação frequentemente gera retrabalho manual para equipes de negócios que dependem do Microsoft Excel para tomar decisões.
A combinação da biblioteca Pandas com a engine openpyxl permite construir pipelines automatizados em Python capazes de executar consultas SQL complexas, estruturar os dados e exportá-los diretamente para pastas de trabalho .xlsx altamente formatadas, com suporte a múltiplas abas, larguras de colunas ajustadas e formatação monetária.
1. Conectando ao Banco de Dados e Executando Consultas SQL
O primeiro passo para automatizar a geração de relatórios é conectar o Python ao banco de dados relacional e converter o resultado das consultas diretamente em um DataFrame do Pandas através da função pd.read_sql_query().
O Pandas interage com bancos de dados utilizando conectores padronizados como o SQLAlchemy (ou drivers nativos como sqlite3, psycopg2 ou pymysql). Esta abordagem garante que a execução da query ocorra diretamente no motor do banco de dados, trazendo para a memória do Python apenas o conjunto de resultados necessário.
import sqlite3
import pandas as pd
from sqlalchemy import create_engine
# Exemplo de conexão com banco de dados SQLite (ou via SQLAlchemy para PostgreSQL/MySQL)
engine = create_engine("sqlite:///empresa.db")
# Consulta SQL estruturada para extrair vendas por categoria
query_vendas = """
SELECT
p.categoria AS Categoria,
p.nome_produto AS Produto,
v.quantidade AS Unidades,
v.preco_unitario AS Preco_Unitario,
(v.quantidade * v.preco_unitario) AS Total_Vendas,
v.data_venda AS Data
FROM vendas v
JOIN produtos p ON v.produto_id = p.id
WHERE v.data_venda >= '2026-01-01'
ORDER BY v.data_venda DESC;
"""
# Leitura direta da consulta SQL para um DataFrame
df_vendas = pd.read_sql_query(query_vendas, con=engine)
Ao utilizar pd.read_sql_query(), os nomes das colunas definidos nos aliases da consulta SQL (como categoria AS Categoria) são preservados no DataFrame, estabelecendo a estrutura que será exportada para a planilha.
2. Exportação Fundamental para Excel com to_excel()
Para exportar um DataFrame do Pandas para o formato .xlsx, o Python necessita da biblioteca openpyxl, que atua como o motor de escrita do Excel. O método nativo to_excel() realiza a conversão com poucas linhas de código.
Na exportação padrão, é essencial definir o parâmetro index=False. Por padrão, o Pandas inclui o seu índice numérico interno (0, 1, 2…) como a primeira coluna do arquivo exportado. Desativar o índice evita colunas desnecessárias que costumam confundir os leitores da planilha.
# Exportação simples para um arquivo Excel
df_vendas.to_excel("relatorio_vendas.xlsx", sheet_name="Vendas_2026", index=False)
Principais Parâmetros do Método to_excel()
A tabela a seguir destaca os parâmetros mais importantes do método to_excel() para personalizar a saída inicial dos dados:
| Parâmetro | Tipo | Descrição |
excel_writer | str ou ExcelWriter | Caminho do arquivo de destino ou objeto ExcelWriter ativo. |
sheet_name | str | Nome da aba que será criada na planilha (Padrão: 'Sheet1'). |
index | bool | Define se o índice numérico do DataFrame será gravado na planilha (Padrão: True). |
columns | list | Permite selecionar e reordenar um subconjunto de colunas do DataFrame. |
na_rep | str | Texto substituto para representar células com valores ausentes ou nulos (NaN). |
startrow | int | Linha inicial de inserção da tabela, permitindo deixar espaço superior para títulos. |
3. Consolidação de Múltiplas Consultas em Diferentes Abas com pd.ExcelWriter
Quando a automação exige a entrega de um relatório completo — contendo, por exemplo, os dados detalhados em uma aba e o resumo consolidado em outra —, chamadas consecutivas de to_excel() sobrescreveriam o arquivo anterior.
Para consolidar múltiplos DataFrames provenientes de diferentes consultas SQL no mesmo arquivo .xlsx, utiliza-se o gerenciador de contexto pd.ExcelWriter(). O bloco with garante que todas as abas sejam gravadas e o arquivo seja fechado e salvo de forma segura após a execução.
# Segunda consulta SQL: Resumo de vendas por categoria
query_resumo = """
SELECT
p.categoria AS Categoria,
SUM(v.quantidade) AS Total_Unidades,
SUM(v.quantidade * v.preco_unitario) AS Faturamento_Total
FROM vendas v
JOIN produtos p ON v.produto_id = p.id
GROUP BY p.categoria
ORDER BY Faturamento_Total DESC;
"""
df_resumo = pd.read_sql_query(query_resumo, con=engine)
# Exportando múltiplas consultas para abas distintas em um único arquivo
with pd.ExcelWriter("relatorio_executivo.xlsx", engine="openpyxl") as writer:
df_resumo.to_excel(writer, sheet_name="Resumo_Executivo", index=False)
df_vendas.to_excel(writer, sheet_name="Detalhamento_Vendas", index=False)
4. Formatação Avançada e Estilização com openpyxl
Embora o Pandas posicione os dados nas células corretamente, a planilha gerada nativamente carece de formatação visual: as colunas possuem largura fixa (o que frequentemente corta textos longos) e os valores numéricos aparecem sem símbolos de moeda ou separadores de milhar.
Ao acessar diretamente os objetos de planilha (worksheets) disponibilizados pelo pd.ExcelWriter(), é possível aplicar regras de estilização avançadas da biblioteca openpyxl.
from openpyxl.styles import Font, PatternFill, Alignment
from openpyxl.utils import get_column_letter
with pd.ExcelWriter("relatorio_formatado.xlsx", engine="openpyxl") as writer:
df_vendas.to_excel(writer, sheet_name="Vendas", index=False)
# Acesso aos objetos nativos do openpyxl
workbook = writer.book
worksheet = writer.sheets["Vendas"]
# 1. Estilização do Cabeçalho (Linha 1)
header_font = Font(name="Calibri", size=11, bold=True, color="FFFFFF")
header_fill = PatternFill(start_color="1F497D", end_color="1F497D", fill_type="solid")
for cell in worksheet[1]:
cell.font = header_font
cell.fill = header_fill
cell.alignment = Alignment(horizontal="center", vertical="center")
# 2. Formatação Monetária nas colunas Preco_Unitario e Total_Vendas (Colunas D e E)
# Formato numérico em Real Brasileiro (R$)
formato_moeda = 'R$ #,##0.00'
for row in range(2, worksheet.max_row + 1):
worksheet[f"D{row}"].number_format = formato_moeda
worksheet[f"E{row}"].number_format = formato_moeda
# 3. Ajuste Automático da Largura das Colunas
for col in worksheet.columns:
max_len = 0
col_letter = get_column_letter(col[0].column) # Obtém a letra da coluna (A, B, C...)
for cell in col:
if cell.value is not None:
max_len = max(max_len, len(str(cell.value)))
worksheet.column_dimensions[col_letter].width = max(max_len + 3, 12)
Dica Prática: O ajuste dinâmico da largura calcula o tamanho da maior string contida em cada coluna e adiciona uma margem de segurança (como + 3 caracteres), garantindo que nenhum rótulo ou número fique oculto com os símbolos ### do Excel.
5. Boas Práticas e Processamento de Grandes Volumes de Dados
Ao trabalhar com bases de dados SQL volumosas contendo centenas de milhares de linhas, a leitura integral para a memória de uma só vez pode consumir recursos excessivos do sistema. Nesses cenários, é recomendado aplicar boas práticas de otimização:
- Filtragem Nativa na Consulta SQL: Sempre restrinja o volume de dados extraído utilizando cláusulas
WHERE, agregando valores comGROUP BYou selecionando apenas as colunas estritamente necessárias diretamente na query SQL, em vez de carregar tabelas inteiras no Pandas. - Processamento em Blocos (
chunksize): Para consultas que excedem a memória RAM disponível, utilize o parâmetrochunksizena funçãopd.read_sql_query(). Isso permite iterar sobre os dados em lotes menores e processar ou gravar registros gradualmente. - Tratamento de Nulos na Exportação: Configure o parâmetro
na_rep="N/A"ouna_rep="-"no métodoto_excel()para garantir que células vazias sejam exibidas de forma padronizada. - Garantia de Fechamento de Recursos: Sempre envolva a gravação em blocos
with pd.ExcelWriter(...)para evitar o corrompimento de arquivos caso ocorra uma falha durante o processo de gravação.
A automação da extração SQL diretamente para planilhas formatadas no Excel elimina etapas operacionais manuais, reduz riscos de erros humanos e garante que os relatórios sejam entregues com qualidade visual profissional e prontos para uso pelas equipes corporativas.
