Convertir Excel a JSON, CSV y SQL
Abre un .xlsx en el navegador y expórtalo a JSON, CSV o sentencias SQL con CREATE TABLE. Detecta fechas y tipos, y el archivo no sale de tu equipo.
Qué hace esta herramienta
Abre un archivo .xlsx dentro de tu navegador y lo convierte a tres formatos:
- JSON — un array de objetos usando la primera fila como claves.
- CSV — separador configurable, entrecomillado según RFC 4180.
- SQL — sentencias
INSERTpor lotes, con unCREATE TABLEdeducido de tus datos, para MySQL, PostgreSQL o SQLite.
El archivo no se sube a ningún servidor. Se lee, se convierte y se descarga sin salir de tu equipo, lo que importa cuando la hoja lleva nóminas, precios de proveedor o datos de clientes.
Cómo usarla
- Arrastra el
.xlsxa la zona de carga, o pulsa para elegirlo. - Si tiene varias hojas, elige cuál.
- Marca si la primera fila son cabeceras.
- Elige el formato de salida, ajusta las opciones y copia o descarga.
Las fechas: el motivo por el que casi todos los conversores fallan
Si alguna vez has convertido un Excel y te has encontrado una columna de 45000, 45001, 45002 donde esperabas fechas, este es el motivo.
En un archivo .xlsx las fechas no existen como tipo de dato. Una fecha se guarda como un número: los días transcurridos desde una referencia. El 45000 de arriba es el 15 de marzo de 2023.
Lo único que distingue ese número de una cantidad cualquiera es el formato aplicado a la celda, y ese formato vive en un archivo aparte dentro del .xlsx (xl/styles.xml). Un conversor que no lo lea ve un número y copia un número. No está roto: es que no está mirando donde debe.
Esta herramienta lee la hoja de estilos, reconoce los formatos de fecha —los que Excel trae de fábrica y también los personalizados que hayas definido— y devuelve una fecha real en formato ISO.
Y el bug de 1900, que se lleva arrastrando 40 años
Aquí hay un detalle que casi ninguna implementación casera acierta.
Excel cree que 1900 fue año bisiesto. No lo fue: los años divisibles por 100 no son bisiestos salvo que además lo sean por 400, y 1900 no lo es. El error viene de Lotus 1-2-3, que lo tenía mal en los ochenta, y Microsoft lo copió a propósito para ser compatible: lo documenta la propia Microsoft. Nunca se ha corregido porque arreglarlo movería todas las fechas de todas las hojas del mundo.
La consecuencia es concreta: el número de serie 60 es un 29 de febrero de 1900 que no existió, y eso parte la conversión en dos tramos:
| Serial | Fecha real | Referencia que hay que usar |
|---|---|---|
| 1 | 1 de enero de 1900 | 31/12/1899 |
| 59 | 28 de febrero de 1900 | 31/12/1899 |
| 60 | no existe | — |
| 61 | 1 de marzo de 1900 | 30/12/1899 |
| 45000 | 15 de marzo de 2023 | 30/12/1899 |
Con una sola referencia se acierta en un tramo y se falla un día entero en el otro. Y como los datos reales viven casi siempre por encima del serial 61, el fallo no se nota nunca… hasta que alguien mete una fecha de nacimiento antigua y la conversión la desplaza un día.
Los tipos se deducen de los datos, no de la cabecera
Antes de generar nada, la herramienta recorre cada columna entera y le asigna un tipo, con una regla conservadora: el tipo solo se aplica si todos los valores no vacíos lo cumplen. En cuanto aparece uno que no encaja, la columna cae a texto.
| Detecta | Cuándo |
|---|---|
entero | Todos los valores son números sin decimales |
decimal | Todos son números y al menos uno tiene decimales |
booleano | Todos son verdadero/falso |
fecha | Todos son fechas y todas las horas son medianoche |
fecha y hora | Todos son fechas y alguna lleva hora |
texto | Cualquier otro caso |
También marca si la columna admite vacíos, y eso es lo que decide el NOT NULL del CREATE TABLE.
La tabla de tipos se muestra en pantalla antes de convertir, así que puedes ver de un vistazo si alguna columna se está interpretando como texto porque tiene un valor sucio: un “N/A” en una columna de números, una celda con un espacio, un total escrito a mano al final.
Sobre el SQL que genera
Se emite un CREATE TABLE con los tipos deducidos y luego los INSERT agrupados por lotes (100 filas por sentencia por defecto, configurable). Los tres motores se tratan como lo que son:
| MySQL / MariaDB | PostgreSQL | SQLite | |
|---|---|---|---|
| Identificadores | `col` | "col" | "col" |
| Booleano | TINYINT(1), 1/0 | BOOLEAN, TRUE/FALSE | INTEGER, 1/0 |
| Fecha y hora | DATETIME | TIMESTAMP | DATETIME |
| Decimal | DECIMAL(15,4) | DECIMAL(15,4) | REAL |
El escapado. Los valores se escapan siempre duplicando la comilla simple (O'Brien → 'O''Brien'), que es lo que dice el estándar SQL y lo que entienden los tres motores igual. No se usa la barra invertida a propósito: en MySQL funciona, pero su comportamiento depende del modo NO_BACKSLASH_ESCAPES, y un escapado que depende de la configuración del servidor no es un escapado.
Aun así, revisa el CREATE TABLE antes de ejecutarlo. Los tipos y las longitudes son una propuesta razonable deducida de la muestra que le has dado, no un diseño de esquema: no sabe qué campo es la clave primaria, ni cuál lleva índice, ni si esa columna de texto va a crecer.
Las cabeceras también se sanean
Una cabecera de Excel puede ser Fecha de alta, Precio ($) o 2026 total, y ninguna de las tres vale como nombre de columna. Junto al nombre original verás el identificador generado:
Fecha de alta→fecha_de_altaAño→ano(sin acentos, sin ñ)Precio ($)→precio2026 total→col_2026_total(ningún motor admite un identificador que empiece por dígito)- Una cabecera vacía →
col_3, por su posición
Y si dos cabeceras producen el mismo identificador —id, ID e Id son la misma cosa una vez saneadas— se les añade un sufijo numérico para que el CREATE TABLE no falle.
Qué formatos acepta
Solo .xlsx, el formato de Office 2007 en adelante. También funcionan los .xlsx exportados por Google Sheets, LibreOffice Calc y Numbers, que siguen el mismo estándar.
Lo que no acepta:
.xls(Office 2003 y anteriores). Es un binario completamente distinto, no un ZIP de XML. Ábrelo en Excel o LibreOffice y guárdalo como.xlsx..csv. Ya es texto plano; para eso está el conversor de JSON y CSV..odsde LibreOffice. Guárdalo como.xlsx.
Sin dependencias externas, y por qué importa aquí
Un .xlsx es un ZIP lleno de XML. Para leerlo bastan dos cosas que el navegador ya trae: DecompressionStream para descomprimir y un analizador de XML.
Merece la pena decir por qué no se usa la librería habitual para esto. El paquete xlsx de npm está congelado en la versión 0.18.5 de 2022 y arrastra dos vulnerabilidades conocidas —contaminación de prototipo (CVE-2023-30533) y una denegación de servicio por expresión regular (CVE-2024-22363)—. Sus autores movieron la distribución a su propio CDN y nunca publicaron las correcciones en npm, así que instalar xlsx desde ahí hoy significa instalar las vulnerabilidades. Escribir el lector, en cambio, son unas trescientas líneas y no añade superficie de ataque.
Preguntas frecuentes
¿Se sube mi archivo de Excel a algún servidor?
No. El .xlsx se abre y se convierte dentro de tu navegador con JavaScript: no se sube, no se guarda y no queda en ningún registro. Es la diferencia que importa cuando la hoja lleva nóminas, precios de proveedor, datos de clientes o cualquier cosa que no debería pasar por un servidor ajeno. Puedes comprobarlo desconectando la red después de cargar la página: la conversión sigue funcionando.
¿Por qué mis fechas salen como números tipo 45000?
Porque en un .xlsx las fechas no existen como tipo: son números que cuentan los días transcurridos desde una fecha de referencia, y lo único que las distingue de una cantidad cualquiera es el formato aplicado a la celda. Un conversor que no lea la hoja de estilos ve el número y lo copia tal cual. Esta herramienta sí lee los estilos, reconoce los formatos de fecha —los de fábrica y los personalizados— y devuelve una fecha real en ISO. Si aun así te sale un número, esa celda no tenía formato de fecha en el Excel de origen.
¿Qué es el bug del año 1900 y por qué afecta a mis fechas?
Excel considera que 1900 fue año bisiesto, por compatibilidad con Lotus 1-2-3 en los años ochenta. No lo fue: el número de serie 60 corresponde a un 29 de febrero de 1900 que nunca existió. La consecuencia es que la conversión de un número de serie a fecha necesita dos referencias distintas, una para los valores anteriores a ese día fantasma y otra a partir de él. Usar una sola acierta en un tramo y falla un día en el otro, y como los datos reales casi siempre caen en el tramo bueno, el error pasa desapercibido hasta que aparece una fecha antigua.
¿Cómo decide qué tipo de dato tiene cada columna?
Mirando los valores, no la cabecera. Recorre toda la columna y solo asigna un tipo si todos los valores no vacíos lo cumplen: si son enteros da entero, si hay algún decimal da decimal, si todos son fechas da fecha —y distingue entre fecha y fecha con hora según si las horas son todas medianoche—, y en cuanto encuentra algo que no encaja cae a texto. También marca si la columna admite vacíos, que es lo que decide el NOT NULL del CREATE TABLE.
¿El SQL que genera es seguro para pegarlo directamente?
Los valores se escapan siempre: las comillas simples se duplican, que es lo que dice el estándar y lo que entienden MySQL, PostgreSQL y SQLite por igual. No se usa la barra invertida, porque en MySQL su comportamiento depende del modo NO_BACKSLASH_ESCAPES y eso la hace poco fiable. Aun así, revisa siempre el CREATE TABLE antes de ejecutarlo: los tipos y las longitudes son una propuesta razonable a partir de tus datos, no un diseño de esquema.
¿Soporta archivos .xls antiguos o .csv?
Solo .xlsx, que es el formato desde Office 2007. El .xls antiguo es un binario completamente distinto, y el .csv ya es texto plano: para eso está el conversor de JSON y CSV. Si tienes un .xls, ábrelo en Excel o LibreOffice y guárdalo como .xlsx. También funcionan los .xlsx exportados por Google Sheets, LibreOffice y Numbers.
Reseñas y valoraciones
Aún no hay reseñas. ¡Sé la primera persona en opinar!
Guías relacionadas
Tutoriales del blog donde esta herramienta resulta útil.
Herramientas relacionadas
Otras del catálogo que se usan bien junto a esta.