Las exportaciones CSV de los bancos son hostiles siempre de las mismas maneras, y conocer la lista convierte un archivo confuso en un trabajo de cinco minutos. Cada uno de los problemas de abajo es una decisión de formato del banco, no un daño en el archivo:
- Filas de preámbulo. Nombre de la cuenta, código de sucursal (sort code), rango de fechas y una línea en blanco antes del encabezado. Cualquier lector al que le pases el archivo tomará la primera de esas filas como nombres de columna.
- Dos columnas de importe,
DebityCredit, en lugar de un solo importe con signo. O un importe con signo cuya convención es la contraria de la que esperas. - Fechas ambiguas.
03/04/2026es el 3 de abril en el Reino Unido y el 4 de marzo en Estados Unidos, y el archivo no dice cuál. - Una columna de descripción que lleva cinco campos a la vez: comercio, ubicación, número de tarjeta, referencia y el tipo de operación propio del banco.
- Importes como texto, con separadores de miles, símbolos de moneda o negativos escritos como
(45.00).
Arregla esos cinco y el archivo pasa a ser datos normales.
Primero, la forma del archivo
Abre el archivo y mira las primeras diez líneas antes que nada:
head -n 12 statement.csv
Cuenta las filas de preámbulo y fíjate cuál es el encabezado real. Luego sáltalas:
tail -n +5 statement.csv > clean.csv
Si lo abres en una hoja de cálculo, borra esas filas antes de hacer cualquier otra cosa. Si ordenas o filtras con ellas todavía puestas, el resumen de la cuenta queda en medio de tus movimientos, donde es difícil de ver y fácil de meter en un total.
Las fechas, la trampa
Este es el error que da respuestas equivocadas en lugar de una avería evidente. Un lector con formato estadounidense que procese un extracto británico convierte en silencio el 3 de abril en 4 de marzo en todos los días hasta el doce, y deja el resto como está. El resultado parece completamente normal y todos los totales mensuales están mal.
Dos maneras de resolverlo, de la más fiable a la menos:
Busca un día mayor que 12. Recorre la columna de fechas buscando un valor como 25/12/2026. Si el primer componente pasa de doce, el formato empieza por el día. Lleva diez segundos y es definitivo.
Compara con un movimiento que recuerdes. Cualquier cosa que puedas fechar de memoria resuelve la convención al instante.
Después convierte de forma explícita, en vez de dejar que algo adivine:
duckdb -c "SELECT strptime(\"Transaction Date\", '%d/%m/%Y') d, * FROM read_csv('clean.csv', all_varchar=true)"
all_varchar=true es la mitad importante: impide que el lector infiera tipos, de modo que decides tú cada conversión. Eso también protege los números de referencia y los dígitos de cuenta, que de otro modo llegarían como decimales.
Normaliza el importe
Quieres una sola columna numérica con signo, y hay tres formas de partida.
Columnas Debit y Credit separadas. Combínalas, con los débitos en negativo:
COALESCE(-TRY_CAST(replace("Debit", ',', '') AS DOUBLE), TRY_CAST(replace("Credit", ',', '') AS DOUBLE), 0)
Texto con separadores o símbolos. Quita todo lo que no sea un dígito, un signo menos o un punto decimal antes de convertir. £1,234.56 y 1 234,56 necesitan esto, y el segundo además necesita que se trate la coma decimal.
Negativos contables. (45.00) significa −45,00. Nada lo convierte bien por defecto; reemplaza primero los paréntesis.
Luego verifica la conversión antes de fiarte de ningún total: el número de importes no nulos debe coincidir con el número de filas de movimientos. Un TRY_CAST que falla te da un NULL silencioso, y un NULL dentro de un SUM simplemente no cuenta, que es como un total acaba siendo plausiblemente erróneo en lugar de evidentemente roto.
Divide la columna de descripción
La información útil está escondida en la descripción, y llega como una sola cadena:
CARD PAYMENT TO TESCO STORES 3421 ON 02-04-2026 GBP 43.19
Rara vez necesitas un analizador completo. Dos operaciones cubren casi todo lo que la gente quiere:
Una columna de comercio, comparando con una lista de nombres que te interesan. Veinte cláusulas CASE WHEN description LIKE '%TESCO%' THEN 'Tesco' categorizarán la gran mayoría de un extracto personal, y la cola larga no merece automatizarse.
Una columna de tipo de operación, a partir del prefijo. CARD PAYMENT, DIRECT DEBIT, FASTER PAYMENT, ATM. Los bancos son coherentes con esto dentro de una misma exportación, y agrupar por tipo suele ser más revelador que agrupar por comercio.
Lo que no conviene intentar: sacar un importe o una fecha fiables de dentro de la descripción. Los dos ya son columnas, y las copias incrustadas en el texto tienen otro formato y a veces no coinciden.
Ahora sí, la pregunta de verdad
Cuando el archivo tiene una fecha, un importe con signo y un comercio, cada pregunta cabe en una línea:
SELECT strftime(d, '%Y-%m') month, sum(amount) FROM tx GROUP BY month ORDER BY month
SELECT merchant, count(*) n, sum(amount) FROM tx WHERE amount < 0 GROUP BY merchant ORDER BY sum(amount) LIMIT 20
SELECT * FROM tx WHERE amount < -100 ORDER BY amount
Neto mensual, mayores gastos por comercio, todo lo que pasa de cien. Esas tres responden la mayor parte de lo que alguien quiere saber cuando abre un extracto.
Tanto el SQL como el editor visual de filtros se ejecutan sobre el archivo donde está, que es lo importante cuando se trata de una exportación bancaria que prefieres no subir a ningún sitio. Los gráficos salen de la misma consulta, así que un total mensual se convierte en un gráfico de barras en el mismo paso.
Qué haceConviene decir claro esta última consideración. Un extracto bancario es de los archivos más sensibles que maneja la mayoría de la gente: cada comercio, cada lugar, cada pago recurrente y, a menudo, un número de cuenta parcial. Los visores de CSV gratuitos en línea y los sitios de «convierte tu extracto» suben todo a un servidor del que no sabes nada. Para este archivo en concreto, una herramienta que trabaje en local no es manía: es la opción por defecto más obvia.
Prepararlo para otra persona
Muchas veces abres el extracto porque alguien necesita una parte: un contador, un casero, un reembolso de gastos. El trabajo consiste en restar:
- Quédate con las columnas que importan: fecha, descripción, importe. Borra el resto, incluido el saldo corriente y los dígitos de la cuenta.
- Filtra por el periodo o la categoría que realmente te piden.
- Añade una columna de categoría si te la van a pedir.
- Exporta y comprueba que el total de la exportación coincide con el total de tu filtro.
Conviene ocultar la columna de saldo a propósito, y no dejarla por pereza, porque revela bastante más que los propios movimientos.
Borrar columnas, filtrar por periodo y añadir una columna de categoría calculada son ediciones directas aquí, y las columnas de fórmulas guardan sus resultados en el CSV, así que el archivo que entregas es un CSV normal que se abre bien en lo que use quien lo reciba.
Qué haceVarios meses, varias cuentas
Los bancos exportan un periodo cada vez, así que cualquier pregunta que abarque un año implica varios archivos. Dos cosas que hacer antes de combinarlos:
Comprueba que los encabezados coinciden. Los bancos cambian los formatos de exportación de un año a otro, y una columna que cambió de posición desalinea todo lo que viene detrás si concatenas a ciegas. Compara primero las líneas de encabezado; la guía para combinar archivos CSV explica la combinación por nombre de columna, que aguanta esto.
Añade una columna de cuenta antes de combinar archivos de cuentas distintas. Sin ella, una transferencia entre tus propias cuentas aparece dos veces, una como salida y otra como entrada, y todo total que lo ignore se equivoca en el doble de la transferencia. Etiquetar el origen y luego excluir de forma explícita las transferencias internas es la única manera de obtener un total del hogar que signifique algo.