Convertir BD SQLite a Excel con Python

Convertir BD SQLite a Excel con Python
La base de datos resolvió la mitad del problema: el inventario tiene una sola versión de la verdad. La otra mitad quedó pendiente, porque quien necesita esos números todos los días —el contador, el encargado de compras, el dueño— no va a abrir una consola: ese público lee un libro de Excel, filtra por categoría, ordena por fecha y guarda una copia en un pendrive. Este programa es el puente entre los dos mundos: lee una base SQLite y escribe un libro Excel con una hoja por tabla más una hoja índice, y de paso deja una consulta en un archivo CSV.
La base la lee Python por dentro, así que de ese lado no hay nada que instalar. El Excel sí necesita una librería: openpyxl, la única dependencia. Si falta, el programa lo avisa con la orden exacta y se detiene ahí mismo.
⬇ Descargar el código (ZIP)Qué trae el ZIP
Cinco archivos: el programa, dos ejemplos de datos, la salida real y la guía.
| Archivo del paquete | Para qué sirve |
|---|---|
sqlite_a_excel.py | El programa completo, 427 líneas comentadas en español, con los seis pasos. |
datos/productos.csv | Ocho productos de ejemplo, con código, nombre, categoría, precio y existencias. |
datos/movimientos.csv | Catorce movimientos de entrada y salida, con fecha, unidades, precio y documento. |
salida_ejemplo.txt | La salida real del programa, para compararla con lo que le salga a usted. |
LEEME.md | Instalación, opciones de la línea de comandos y los tres detalles que valen dinero. |
Qué hace el programa
La traza de la consola va en seis pasos, de arriba abajo.
- Prepara la base: sin argumentos arma
salida/ejemplo.dbcon dos tablas llenadas desde los CSV. - Lee el esquema: lista las tablas de usuario y las columnas de cada una, con su tipo y su clave.
- Lee las filas: una consulta por tabla, siempre en el mismo orden y con cada valor convertido a su tipo.
- Escribe el Excel: índice más una hoja por tabla, con encabezado, panel congelado, filtro y anchos ajustados.
- Exporta la consulta: deja el resultado en un CSV que Excel abre con doble clic.
- Cierra la conexión y resume tablas, hojas y archivos escritos.
Cómo ejecutarlo
Instale Python 3.11 o superior (marcando la casilla que lo agrega al sistema) y después la única librería que hace falta: pip install openpyxl. Descomprima el ZIP en una carpeta cómoda, abra la terminal ahí y escriba python sqlite_a_excel.py. La primera corrida arma su propia base de ejemplo, así que no depende de nada más. Con una base de verdad, pase la ruta como argumento: python sqlite_a_excel.py ruta/a/tu_base.db --excel salida/mi_libro.xlsx. Para exportar una consulta suelta están --consulta y --csv.
El código, explicado
El programa son 427 líneas de funciones cortas. Estos cinco pedazos son los que conviene entender, porque se repiten en cualquier exportación de datos.
Uno: de dónde salen las herramientas. Tres de estas cuatro importaciones son de la biblioteca estándar, y la tercera importa un detalle de fondo: sqlite3 viene dentro de Python. Por eso no hay motor de base de datos que instalar y el respaldo del inventario sigue siendo un solo archivo.
import argparse # argparse: opciones de línea de comandos, para aceptar una base o una consulta
import csv # csv: escribe el CSV de la consulta
import sqlite3 # sqlite3: la base de datos viene dentro de Python, no hay que instalar nada
from pathlib import Path # pathlib: rutas que funcionan en Windows, Linux y Mac
Dos: abrir la base y descubrir sus tablas. La consulta mira el catálogo interno de SQLite y descarta las tablas propias del motor, las que empiezan con sqlite_; después, por cada tabla, PRAGMA table_info devuelve sus columnas con el tipo declarado y marca cuál es la clave. No hay ninguna lista de tablas escrita a mano: el programa sirve para cualquier base.
conexion = sqlite3.connect(origen)
cursor = conexion.cursor()
paso(2, "LEER EL ESQUEMA (TABLAS Y COLUMNAS)")
tablas = listar_tablas(cursor)
print(f"Tablas de usuario en la base: {len(tablas)}")
Tres: leer las filas, siempre en el mismo orden. Aquí está el detalle que hace comparables dos exportaciones: los registros se ordenan por la clave primaria y, si la tabla no tiene una sola, por todas las columnas. Sin ese orden la hoja cambiaría de una corrida a otra y nadie podría comparar el libro de hoy con el de la semana pasada. Cada valor sale además convertido al tipo declarado de su columna, y por eso los precios llegan al Excel como números y no como texto.
def leer_tabla(cursor, tabla: str, columnas: list[tuple]) -> list[list]:
"""Lee todas las filas de una tabla, en orden y ya convertidas de tipo."""
tipos = [columna[2] for columna in columnas]
sql = f'SELECT * FROM "{tabla}" ORDER BY {orden_por(columnas)}'
return [
[convertir(valor, tipo) for valor, tipo in zip(registro, tipos)]
for registro in cursor.execute(sql)
]
Cuatro: escribir la hoja con las comodidades de uso. Después del encabezado y los datos, la hoja queda lista para trabajar: congela la primera fila para que los títulos se vean al bajar, ajusta el ancho de cada columna a lo más largo que tenga dentro y deja puesto el filtro automático sobre todo el rango.
# Panel congelado: el encabezado queda a la vista al bajar por la hoja
hoja.freeze_panes = "A2"
# El ancho de cada columna se ajusta a lo más largo que tenga dentro
for posicion, nombre in enumerate(nombres, start=1):
medidas = [len(str(nombre))] + [len(str(fila[posicion - 1])) for fila in filas]
letra = get_column_letter(posicion)
hoja.column_dimensions[letra].width = min(max(medidas) + 2, ANCHO_MAXIMO)
# Filtro automático en el encabezado: se puede filtrar y ordenar sin tocar nada
ultima = get_column_letter(len(nombres))
hoja.auto_filter.ref = f"A1:{ultima}{len(filas) + 1}"
Cinco: la misma consulta, ahora como archivo. El detalle que importa está en la marca de orden del UTF-8: con ella, Excel abre el CSV con doble clic y las tildes de Categoría y Plomería se ven bien, sin el paso previo de importación.
def exportar_csv(cursor, sql: str, parametros: tuple, ruta: Path) -> int:
"""Ejecuta una consulta y escribe su resultado como CSV; devuelve las filas."""
registros = cursor.execute(sql, parametros).fetchall()
nombres = [descripcion[0] for descripcion in cursor.description]
ruta.parent.mkdir(parents=True, exist_ok=True)
# UTF-8 con marca de orden: así Excel abre bien las tildes con doble clic
with open(ruta, "w", encoding="utf-8-sig", newline="") as archivo:
pluma = csv.writer(archivo)
pluma.writerow(nombres)
pluma.writerows(registros)
return len(registros)
Qué va a ver en pantalla
La salida dice, paso por paso, lo que encontró y lo que escribió. El trozo del Excel y el cierre:
PASO 4: ESCRIBIR EL LIBRO EXCEL ======================================================================== Hojas escritas en el libro: 3 Hojas del libro: Índice, movimientos, productos Archivo Excel escrito: salida/inventario.xlsx
El libro queda con la hoja Índice y una hoja por tabla: tres hojas a partir de dos tablas. La consulta de salidas por categoría deja un CSV de tres filas, ordenado de mayor a menor importe.
======================================================================== CIERRE ======================================================================== Base leída: salida/ejemplo.db Tablas de usuario: 2 Hojas del Excel: 3 Archivo Excel: salida/inventario.xlsx Archivo CSV: salida/resumen_categorias.csv
El resultado de esa consulta, ya en el archivo:
| Categoría | Movimientos | Unidades | Importe |
|---|---|---|---|
| Herramientas | 2 | 8 | 1.099.200 |
| Plomería | 2 | 48 | 1.032.000 |
| Eléctrico | 2 | 170 | 658.000 |
Errores comunes y consejos
- Instale openpyxl antes de la primera corrida; si falta, el programa avisa y se detiene.
- Los dos CSV del paquete van junto al programa, en
datos/. Si los mueve, la base de ejemplo sale vacía. - No quite el
ORDER BYde la lectura: sin ese orden, dos exportaciones dejan de ser comparables. - Las fechas viajan como texto ISO: se ordenan bien, pero no son fechas del Excel. Para tratarlas como fechas, agregue al lado una columna con
FECHAVALOR. - El nombre de cada hoja sale del de la tabla; si su base trae una tabla llamada igual que la hoja índice, renómbrela antes.
- Pruebe primero sobre una copia de la base: copiar ese archivo es todo el respaldo.
Cuándo esto no alcanza
Este programa es la herramienta correcta cuando la base ya existe y hace falta sacarla de ahí para que otros la lean. Pero llega un momento en que el negocio pide más: varias personas trabajando a la vez, compras y facturación, informes que el contador imprima sin ayuda, respaldos que no dependan de que alguien se acuerde. Ahí es cuando un programa hecho para eso —como Kardex Tauro, que es gratis y sirve para ordenar el inventario— se vuelve la opción sensata: por dentro sigue siendo la misma base, solo que ya no la tiene que exportar usted. Este ZIP y Kardex Tauro comparten la misma idea: los datos del negocio se guardan una sola vez y bien.
⬇ Descargar el código (ZIP)Descargue el paquete, ejecútelo una vez con la base de ejemplo y mire la pantalla con calma. Al final tendrá el libro y el CSV en la carpeta salida.