Converter um banco de dados SQLite em Excel com Python

Converter um banco de dados SQLite em Excel com Python
A planilha não vai embora: é o formato que o contador abre sem pedir ajuda e que o dono imprime para a reunião. O banco resolve a outra metade — guarda cada produto uma única vez e impede dois cadastros com o mesmo código. As duas convivem mal quando alguém mantém as duas à mão: cada digitação nova cria uma segunda versão dos números. Este programa faz a ponte em um sentido só: lê o arquivo SQLite e escreve uma pasta de trabalho Excel com uma planilha de índice mais uma por tabela, sem copiar e colar, e o resultado sai igual toda vez que roda.
O banco é a fonte única da verdade; o Excel é a fotografia tirada na hora, e uma fotografia nova custa uma linha de comando.
⬇ Baixar o código (ZIP)O que vem no ZIP
| Arquivo do pacote | Para que serve |
|---|---|
sqlite_a_excel.py | O programa completo, comentado linha por linha em português, com os seis passos. |
datos/productos.csv | Oito produtos de exemplo, com código, nome, categoria, preço e estoque. |
datos/movimientos.csv | Catorze movimentos de entrada e de saída, com data, unidades e preço unitário. |
salida_ejemplo.txt | A saída real do programa, para comparar com a que aparecer na tela. |
LEIAME.md | As instruções de instalação e de execução, em dois minutos de leitura. |
Por que o Excel continua sendo pedido
Quem trabalha no depósito não vai abrir um terminal para saber quantas unidades de cabo sobraram. Quem paga as contas quer os subtotais prontos e poder filtrar por uma coluna sem pedir ajuda. O Excel faz isso bem e faz mal ser a memória do negócio: cada arquivo é uma cópia que envelhece sozinha. A saída é deixar cada ferramenta no seu lugar — o SQLite guarda, o Excel apresenta.
O que o programa faz
- Prepara o banco: sem argumento, monta um de exemplo com duas tabelas a partir dos CSV do pacote.
- Lê o esquema: lista as tabelas de usuário e as colunas de cada uma.
- Lê as linhas: percorre cada tabela em ordem fixa e converte os valores pelo tipo da coluna.
- Escreve o Excel: a pasta de trabalho com a planilha de índice e uma por tabela.
- Exporta a consulta: roda uma consulta SQL e deixa o resultado em CSV.
- Fecha: encerra a conexão e resume o que escreveu.
Como executar
Instale o Python 3.11 ou mais novo e marque a caixa que o adiciona ao sistema. Falta uma biblioteca só, a que escreve arquivos Excel: pip install openpyxl. O resto — sqlite3, csv e argparse — já vem dentro do Python. Com o pacote descompactado, rode python sqlite_a_excel.py e, para converter um banco seu, passe o caminho do arquivo. As opções --excel e --consulta mudam a pasta de saída.
O código, explicado
O programa se lê de cima para baixo. Estes cinco trechos são os que voltam depois.
Um: as ferramentas vêm de dois lugares. Destas importações, só uma exige instalação: o sqlite3 vem embutido no Python, e por isso a cópia de segurança do estoque é um arquivo único, que se copia como uma fotografia. A que escreve o Excel é o openpyxl: se faltar, o programa avisa e para, em vez de estourar no meio da tarefa.
import argparse # argparse: opções de linha de comando, para aceitar um banco ou uma consulta
import csv # csv: escreve o CSV da consulta
import sqlite3 # sqlite3: o banco de dados vem dentro do Python, nada para instalar
from pathlib import Path # pathlib: caminhos que funcionam no Windows, Linux e Mac
Dois: antes de ler qualquer linha, o programa pergunta ao banco quais tabelas ele tem. A busca vai na tabela interna onde o SQLite guarda o próprio desenho e deixa de fora as de uso internas, as que começam com sqlite_. Depois lê as colunas de cada tabela com o comando do motor, que devolve nome, tipo e qual é a chave. É esse desenho lido na hora que governa a conversão.
def listar_tablas(cursor) -> list[str]:
"""Devolve as tabelas de usuário do banco, ordenadas por nome."""
# As tabelas internas do SQLite ficam de fora: as que começam com sqlite_
sql = ("SELECT name FROM sqlite_master WHERE type = 'table' "
"AND name NOT LIKE 'sqlite_%' ORDER BY name")
return [registro[0] for registro in cursor.execute(sql)]
def columnas_tabla(cursor, tabla: str) -> list[tuple]:
"""Devolve as colunas de uma tabela como o PRAGMA table_info as descreve."""
# PRAGMA table_info devolve: número, nome, tipo, obrigatório, padrão e chave
return cursor.execute(f'PRAGMA table_info("{tabla}")').fetchall()
Três: as linhas são lidas já convertidas. Aqui está o detalhe que separa uma planilha que soma de uma que apenas parece somar: o banco informa o tipo de cada coluna e a conversão usa essa informação. Onde o tipo é inteiro, o valor chega como inteiro; onde é decimal, como decimal. Sem isso, os números entrariam no Excel como texto e as somas devolveriam zero.
def convertir(valor, tipo: str):
"""Devolve o valor convertido para o tipo declarado da sua coluna."""
# Converte o valor pelo tipo declarado: assim o Excel guarda números e não texto
if valor is None:
return None
if "INT" in tipo.upper():
try:
return int(valor)
except (TypeError, ValueError):
return valor
if "REAL" in tipo.upper() or "FLOA" in tipo.upper() or "DEC" in tipo.upper():
try:
return float(valor)
except (TypeError, ValueError):
return valor
return valor
Quatro: a planilha é montada célula a célula. A primeira linha é o cabeçalho em negrito com fundo cinza, e o painel é congelado logo abaixo, para os títulos continuarem à vista quando se desce por uma tabela longa. Os números são escritos como números, com separador de milhar. O mesmo bloco ajusta a largura das colunas e liga o filtro automático.
def escribir_hoja(hoja, nombres: list[str], filas: list[list], relleno) -> None:
"""Escreve uma planilha: cabeçalho, dados, painel congelado, larguras e filtro."""
for posicion, nombre in enumerate(nombres, start=1):
celda = hoja.cell(row=1, column=posicion, value=nombre)
celda.font = FUENTE_ENCABEZADO
celda.fill = relleno
for numero, fila in enumerate(filas, start=2):
for posicion, valor in enumerate(fila, start=1):
celda = hoja.cell(row=numero, column=posicion, value=valor)
# Os números são escritos como números; só os textos ficam como texto
if isinstance(valor, float):
celda.number_format = "#,##0.00"
elif isinstance(valor, int):
celda.number_format = "#,##0"
# Painel congelado: o cabeçalho continua à vista ao descer pela planilha
hoja.freeze_panes = "A2"
Cinco: a pergunta de negócio, em uma consulta. Somar unidades e valor por categoria, do maior para o menor, é o número que o dono leva para a reunião; aqui é uma única consulta, rodada na hora, que junta os movimentos com os produtos pelo código. A exportação para CSV grava em UTF-8 com marca de ordem, e é isso que faz o Excel abrir os acentos certos com duplo clique.
SQL_CONSULTA = (
f'SELECT p."{COL_P_CATEGORIA}" AS "Categoria", '
f'COUNT(*) AS "Movimentos", '
f'SUM(m."{COL_M_UNIDADES}") AS "Unidades", '
f'SUM(m."{COL_M_UNIDADES}" * m."{COL_M_PRECIO}") AS "Valor" '
f'FROM "{TABLA_MOVIMIENTOS}" m JOIN "{TABLA_PRODUCTOS}" p '
f'ON p."{COL_P_CODIGO}" = m."{COL_M_CODIGO}" '
f'WHERE m."{COL_M_TIPO}" = ? '
f'GROUP BY p."{COL_P_CATEGORIA}" '
f'ORDER BY "Valor" DESC, "Categoria"'
)
O que você vai ver na tela
A saída está em português e mostra a trilha dos seis passos. Um trecho do esquema lido do banco:
Tabelas de usuário no banco: 2 ------------------------------------- Coluna Tipo Chave ------------------------------------- codigo TEXT PK produto TEXT - categoria TEXT - preco INTEGER - estoque INTEGER - -------------------------------------
Depois, a pasta de trabalho escrita e a consulta que sai em CSV:
Planilhas escritas na pasta de trabalho: 3 Planilhas da pasta de trabalho: Índice, movimentos, produtos Arquivo Excel escrito: salida/inventario.xlsx Consulta de exemplo com os movimentos do tipo: saída SQL: SELECT p."categoria" AS "Categoria", COUNT(*) AS "Movimentos", SUM(m."unidades") AS "Unidades", SUM(m."unidades" * m."preco_unitario") AS "Valor" FROM "movimentos" m JOIN "produtos" p ON p."codigo" = m."codigo" WHERE m."tipo" = ? GROUP BY p."categoria" ORDER BY "Valor" DESC, "Categoria" Linhas do CSV: 3
O resultado dessa consulta, já no arquivo:
| Categoria | Movimentos | Unidades | Importe |
|---|---|---|---|
| Ferramentas | 2 | 8 | 1.099.200 |
| Hidráulica | 2 | 48 | 1.032.000 |
| Elétrica | 2 | 170 | 658.000 |
Erros comuns e conselhos
- Rodar duas vezes seguidas não faz sujeira: ele apaga o banco de exemplo anterior e o cria de novo.
- O Excel é o resultado, nunca o original: quem edita a planilha e salva não altera o banco.
- As datas chegam do SQLite como texto e não são datas do Excel: para somá-las, use a função de data do seu Excel em uma coluna ao lado, sem mexer no banco.
Quando isso deixa de bastar
Este programa é o ponto certo para quem quer o estoque em um só lugar e nas mãos de quem só lê planilha. Mas chega um momento em que o negócio pede mais: várias pessoas ao mesmo tempo, compras, relatórios prontos para imprimir e botões no lugar de comandos. É aí que um programa feito para isso — como o Kardex Tauro, gratuito e feito para organizar o estoque — passa a ser a escolha sensata.
⬇ Baixar o código (ZIP)Baixe o pacote, rode uma vez e abra o arquivo Excel: o seu banco de dados virou uma pasta de trabalho que qualquer pessoa da equipe lê, filtra e imprime.