¿Te suena esto? Llevas toda la mañana copiando filas de un Excel a tu CRM a mano, saltando entre pestañas, rezando por no desplazar una columna. En Hacker News, Reddit y Stack Overflow es la misma queja repetida con distintas palabras: gente buscando "middleware para pasar SQL a Firebase", desarrolladores hartos de reescribir el enésimo script para "simplemente subir un CSV" a un sistema que debería tener esto resuelto de fábrica, o directamente maldiciendo un CRM heredado que ni siquiera tiene API.
No es solo tedio. Cada copia manual es una oportunidad de error: un email mal transcrito, una fecha en el formato equivocado, un cliente duplicado porque alguien pegó la misma fila dos veces. El coste real no es el tiempo que pierdes tú frente a la hoja de cálculo, es el tiempo que pierde todo tu equipo comercial trabajando con datos de los que no puede fiarse, y las decisiones que se toman sobre esos datos sucios.
La buena noticia es que da igual cuál sea tu caso concreto —Excel o SQL hacia Firebase, Excel hacia un CRM con API decente, o Excel hacia un dinosaurio sin API— el patrón que lo resuelve es siempre el mismo: un pipeline ETL (Extracción, Transformación, Carga) montado con n8n. Cambia el nodo de salida, cambia algo de la transformación, pero la arquitectura se repite. Vamos escenario por escenario para que reconozcas el tuyo.
Escenario 1: migrar Excel (o SQL) a Firebase
Este es el caso típico de quien está saliendo de las hojas de cálculo hacia una base de datos de verdad, o de quien tiene los datos en un SQL antiguo y quiere consolidarlos en Firestore para una app nueva. La clave está en orquestar el flujo, no en escribirlo todo a mano cada vez:
- Nodo Excel/CSV: carga tu hoja de cálculo (o su export a CSV).
- Nodo SQL (si aplica): si tienes acceso directo a la base de datos origen, te conectas y extraes solo lo que necesitas, no la tabla entera.
- Nodo de transformación (JavaScript/Expresiones): limpia, normaliza formatos de fecha, y reestructura los campos para que encajen con tu modelo de datos en Firebase.
- Nodo Firebase: escribe en Firestore con el SDK/API nativo de n8n para Firebase.
// Ejemplo de transformación en n8n antes de escribir en Firestore
items.map(item => {
return {
...item,
nombre_cliente: item.Nombre.toUpperCase(),
fecha_registro: new Date(item.Fecha),
};
});
Nada exótico: normalizar mayúsculas, convertir fechas de texto a objetos Date válidos, renombrar un par de campos. El 80% del trabajo de un ETL de este tipo es precisamente esto, y automatizarlo una vez te ahorra repetirlo cada semana a mano.
Escenario 2: mantener un CRM estándar sincronizado con tu Excel
Si tu CRM sí tiene API REST (la mayoría de los modernos la tienen), el reto ya no es técnico sino de disparo: ¿cuándo se sincroniza? Aquí hay dos formas de resolverlo:
- Webhook: algo dispara la sincronización en el momento en que se modifica una fila (por ejemplo, si tu Excel vive en Google Sheets o SharePoint, ambos disparan eventos que n8n puede escuchar).
- Trigger programado: un cron que revisa cambios cada cierto tiempo —cada hora, cada noche— y sincroniza lo que haya cambiado desde la última pasada.
Una vez disparado, el flujo recorre cada fila del Excel/CSV y la mapea al formato que espera el CRM:
// Asumiendo que 'items' es el array de objetos de tu Excel/CSV
for (const item of items) {
const crmData = {
nombre: item.NombreCliente,
email: item.EmailContacto,
// ... otros campos
};
// Llama a la API de tu CRM para crear o actualizar el registro
// await yourCRM.updateOrCreate(crmData);
}
Con esto, tu equipo comercial deja de vivir con el CRM desactualizado tres días respecto a la realidad, y tú dejas de ser el cuello de botella que "cuando tenga un rato lo actualizo".
Escenario 3: tu CRM no tiene API (y cómo migrar igual)
Este es el caso que más frustra, y el que más me preguntan por Stack Overflow y foros de código heredado: "¿y si mi CRM ni siquiera tiene API?". Pasa más de lo que parece con sistemas antiguos que llevan una década en producción y a los que nadie se atreve a tocar. Aun así, hay salidas:
- Automatización de UI con herramientas como Playwright, que simula literalmente a una persona rellenando el formulario del CRM: abre la página, escribe en los campos, hace clic en guardar. Más frágil que una API, pero funciona cuando no queda otra.
- Importación de CSV generados programáticamente, si el CRM tiene aunque sea un importador manual de archivos: automatizas la generación del CSV con el formato exacto que espera y solo queda el clic final de "importar" (o automatizas también eso con UI).
Cuando sí hay algo de superficie de API, aunque sea limitada, un script sencillo en Node.js puede encargarse de leer el Excel y empujar los datos fila a fila:
const XLSX = require('xlsx');
const axios = require('axios');
async function migrateData(filePath, crmEndpoint, apiKey) {
const workbook = XLSX.readFile(filePath);
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
const data = XLSX.utils.sheet_to_json(worksheet);
for (const row of data) {
try {
await axios.post(crmEndpoint, row, {
headers: { 'Authorization': `Bearer ${apiKey}` },
});
console.log(`Fila migrada: ${JSON.stringify(row)}`);
} catch (error) {
console.error(`Error en fila ${JSON.stringify(row)}: ${error.message}`);
}
}
}
migrateData('tu_archivo.xlsx', 'https://api.tu-crm.com/records', 'TU_API_KEY');
Fíjate en el try/catch dentro del bucle: si falla una fila, se registra el error y el proceso sigue con las siguientes, en lugar de morir a la primera excepción y dejarte sin saber cuántas filas se llegaron a migrar.
Corriendo el pipeline en Docker, sin depender de nadie
Da igual el escenario que tengas: en algún punto vas a querer que esto corra solo, sin tu portátil abierto ni un cron casero. Ahí es donde entra montar n8n autoalojado en Docker, dentro de tu propia infraestructura (AWS, un VPS, lo que ya uses). Un pipeline mínimo, en formato de definición de flujo n8n, sería algo así:
// Ejemplo conceptual de flujo n8n para importar datos de Excel a un CRM
{
"nodes": [
{
"parameters": {
"filePath": "/data/input.csv",
"options": { "skipHeaderRow": true }
},
"name": "ReadCSV",
"type": "n8n-nodes-base.csvReader"
},
{
"parameters": {
"crmEndpoint": "YOUR_CRM_API_ENDPOINT",
"credentials": "yourCrmCredentials",
"method": "POST",
"data": "={{ $json }}"
},
"name": "SendToCRM",
"type": "n8n-nodes-base.genericApiRequest"
}
],
"connections": {
"ReadCSV": { "0": [{ "node": "SendToCRM", "type": "target" }] }
}
}
Tener n8n en tu propia infraestructura, en lugar de depender de un servicio externo, significa que el pipeline sigue siendo tuyo: tú controlas las credenciales, los logs y cuándo se ejecuta, y puedes reutilizar el mismo contenedor para el siguiente flujo que necesites automatizar.
Si te has visto reflejado en alguno de estos tres escenarios —o en los tres a la vez, porque el Excel de la empresa siempre acaba alimentando más de un sistema— es exactamente el tipo de pipeline que monto en consultoría. Podemos empezar con un diagnóstico gratuito de 30 minutos para ver cuál de estos casos es el tuyo, y de ahí a un paquete de 10 horas por 500€ o un proyecto cerrado desde 1200€ según la complejidad del CRM que tengas al otro lado.
Preguntas frecuentes
¿Qué es un proceso ETL y por qué hace falta para mover datos a un CRM o a Firebase? ETL significa Extracción, Transformación y Carga: extraes los datos de origen (Excel, SQL...), los transformas al formato que necesita el destino y los cargas ahí, en lugar de copiarlos y pegarlos a mano cada vez.
¿Qué dos formas hay de disparar la sincronización entre Excel y el CRM? Un webhook que se activa al modificar una fila (por ejemplo en Google Sheets o SharePoint), o un trigger programado que revisa los cambios cada cierto tiempo, por ejemplo cada hora.
¿Qué se hace si el CRM de destino no ofrece una API REST? Se puede recurrir a automatización de UI, con herramientas como Playwright, que simula la interacción humana con el CRM, o a la importación de archivos CSV generados programáticamente si el CRM lo permite.
¿Qué pasa si falla el envío de una fila concreta durante la migración?
Con un manejo de errores adecuado (un try/catch por fila), se registra qué fila falló sin detener el resto del proceso, y se puede reintentar o revisar después en lugar de perder toda la migración.
¿Qué papel juega Docker cuando este pipeline tiene que correr de forma autónoma? Permite alojar n8n dentro de tu propia infraestructura, por ejemplo en AWS, de forma aislada y reproducible, para que el flujo se ejecute solo sin depender de un portátil encendido ni de un servicio externo.
¿Qué tipo de transformaciones suelen hacer falta antes de cargar los datos? Normalizaciones sencillas como poner nombres en mayúsculas, convertir fechas de texto a un formato de fecha válido, o renombrar campos para que coincidan con el modelo de datos del CRM o de Firebase.