Modelado financieroIntermedio9 min de lectura

Automatiza el control de gastos para freelancers en Sheets

Crea un categorizador de gastos en Google Sheets con mapeo dinámico de columnas, tabla de reglas de proveedores y salidas para un P&L real.

Esta guía te lleva paso a paso en la construcción de un categorizador automatizado de gastos en Google Sheets que normaliza exportaciones desordenadas de bancos y procesadores de pago, mapea cadenas de proveedores a categorías usando una tabla de reglas mantenible, y vuelca actuals mensuales limpios en una estructura de P&L - una que puedes referenciar en un modelo de burn o mostrarle a un inversionista.

Lo que necesitarás

  • Cuenta de Google con acceso a Google Sheets
  • Exportación CSV de un banco, Stripe, Mercury u otra herramienta contable
  • Familiaridad básica con SUMIFS, INDEX/MATCH y fórmulas de arreglo
  • Una lista de categorías alineada a las líneas reales de tu P&L (Software, Nómina, Marketing, etc.) - no las categorías del SAT o DIAN
  • (Opcional) Acceso a Google Apps Script para conjuntos de datos de más de 2,000 filas

Guía paso a paso

1

Crea la arquitectura de 3 pestañas

Separa tu flujo de datos en 3 pestañas: Import, Expenses y Summary. Puede sonar obvio, pero la mayoría de los registros de gastos fallidos se rompen porque alguien pegó una exportación CSV directamente encima de fórmulas activas. Eso borra las fórmulas, los datos quedan en crudo y nada se agrega correctamente.

  • Import**: Zona de pegado en crudo - ninguna fórmula vive aquí, nunca. Los datos CSV llegan aquí y se quedan intactos.
  • Expenses**: La capa de normalización. Cada fila es una fórmula que jala de Import, limpia y categorizada.
  • Summary**: Agregación pura. SUMIFS contra Expenses, agrupado por categoría y mes.
  • Rules**: Una pestaña separada que mapea patrones de palabras clave de proveedores a nombres de categoría. La mantendrás de forma independiente a toda la lógica de fórmulas.

Pro Tip

Protege la pestaña Import de ediciones accidentales usando Datos → Proteger hojas y rangos. Es muy fácil escribir accidentalmente en una celda y corromper la zona de pegado.
2

Crea un buscador dinámico de columnas

Las exportaciones de bancos, pagos de Stripe y volcados de herramientas contables no llegan en el mismo orden de columnas cada mes. Mercury pone la fecha en la columna A; tu software contable puede ponerla en la columna D. Esa secuencia también cambia cuando modificas la configuración de exportación o agregas un nuevo campo de datos.

La solución es una búsqueda por encabezado de fila que encuentra la columna correcta por nombre, no por posición. En la pestaña Expenses, define 3 celdas auxiliares que almacenen el índice de columna para cada campo que necesitas:

=MATCH("Date", Import!$1:$1, 0)
=MATCH("Description", Import!$1:$1, 0)
=MATCH("Amount", Import!$1:$1, 0)

Nombra estas celdas col_date, col_desc, col_amount usando el Cuadro de Nombre. Luego en las filas de Expenses, jala los datos dinámicamente:

=INDEX(Import!$A:$Z, ROW(A2), col_date)
=INDEX(Import!$A:$Z, ROW(A2), col_desc)
=INDEX(Import!$A:$Z, ROW(A2), col_amount)

Ahora, cuando tu exportación llegue con Description en la columna C en lugar de B el próximo mes, nada se rompe. La búsqueda por encabezado lo encuentra y cada fórmula descendente se ajusta automáticamente.

    Pro Tip

    Agrega un cuarto MATCH para cualquier columna que varíe según la fuente - "Memo", "Reference", "Counterparty" aparecen en posiciones distintas dependiendo del banco.
    3

    Normaliza las cadenas de proveedores

    Las cadenas de proveedores crudas de exportaciones bancarias son hostiles: espacios al final, mayúsculas y minúsculas mezcladas, espacios adicionales de campos OCR, artefactos de codificación. Dos transacciones del mismo proveedor pueden verse completamente distintas para una fórmula SEARCH si una tiene un espacio de más.

    En la pestaña Expenses, agrega una columna Vendor_Clean que aplica tres transformaciones en secuencia:

    =TRIM(UPPER(SUBSTITUTE(C2, "  ", " ")))
    

    TRIM elimina espacios al inicio y al final. UPPER elimina la diferencia entre mayúsculas y minúsculas. SUBSTITUTE colapsa los dobles espacios que a veces aparecen en campos memo exportados. Esta única columna es lo que referenciará cada fórmula descendente - la descripción de importación cruda permanece intacta en su propia columna como registro de auditoría.

    Para la normalización de fechas, agrega una columna Date_Clean. Los formatos mixtos - MM/DD/YYYY vs YYYY-MM-DD vs "16 Apr 2026" - son comunes al jalarse de múltiples fuentes. Forzarlos a un valor estándar:

    =IF(ISNUMBER(D2), D2, DATEVALUE(D2))
    

      Pro Tip

      Formatea Date_Clean como fecha, no como general. DATEVALUE devuelve un número de serie que se ve como "46000-algo" hasta que aplicas el formato de fecha.
      4

      Crea la tabla de reglas de proveedores

      La pestaña Rules contiene una tabla de 2 columnas: Keyword en la columna A, Category en la columna B. Este es el único lugar que tocas cuando aparece un nuevo proveedor o quieres reclasificar una categoría.

      KeywordCategoría
      ZOOMSoftware
      GOOGLE CLOUDSoftware
      AWSSoftware
      NOTIONSoftware
      FACEBOOK ADSMarketing
      LINKEDINMarketing
      STRIPE FEEProcesamiento de Pagos
      GUSTONómina
      UNITED AIRLINESViajes

      Algunas reglas de diseño que importan. Las palabras clave deben coincidir con la parte más distintiva de la cadena del proveedor - no "GOOGLE" (demasiado amplio; captura Google Drive, Google Ads y Google Cloud como una misma cosa) sino "GOOGLE CLOUD" o "GOOGLE ADS" específicamente. El número de reglas por categoría no tiene límite artificial; usa tantas como necesites para ser preciso. Un procesador de pagos que genera 7 variantes distintas para el mismo proveedor necesita 7 filas de palabras clave.

      Mantén las palabras clave ordenadas por especificidad dentro de cada categoría - los patrones más específicos primero. El categorizador devuelve la primera coincidencia, por lo que "FACEBOOK ADS" debe aparecer antes que "FACEBOOK" si ambos están en tu tabla.

        Pro Tip

        Agrega una tercera columna, Notes, para registrar por qué existe una regla. Cuando vuelvas a esta tabla en 6 meses preguntándote por qué "AMZN MKTPLACE" se mapea a Software en lugar de Misceláneos, vas a agradecer ese contexto.
        5

        Escribe el categorizador INDEX/MATCH

        La fórmula de categoría escanea tu tabla de Rules buscando cualquier palabra clave que aparezca dentro de la cadena del proveedor limpia. En la pestaña Expenses, agrega una columna Category:

        =IFERROR(INDEX(Rules!$B$2:$B$100, MATCH(TRUE, ISNUMBER(SEARCH(Rules!$A$2:$A$100, E2)), 0)), "Sin categoría")
        

        Ingrésala con Ctrl+Shift+Enter para convertirla en fórmula de arreglo (en versiones más recientes de Sheets también puedes envolver la expresión interna en ARRAYFORMULA). La fórmula devuelve la primera categoría cuya palabra clave aparece en cualquier parte de la cadena del proveedor limpia - las coincidencias parciales funcionan, por lo que "GOOGLE CLOUD STORAGE" activa correctamente la regla "GOOGLE CLOUD" aunque no sean idénticas.

        El fallback "Sin categoría" es más importante de lo que parece. Si devuelves "" para las filas sin coincidencia, esas transacciones desaparecen silenciosamente de los totales SUMIFS - SUMIFS omite las celdas en blanco. Usar una cadena explícita significa que los gastos sin mapear aparecen como su propia categoría en el resumen, donde puedes ver exactamente qué no se ha mapeado aún. Esa visibilidad es lo que te indica cuándo necesita actualizarse tu tabla de Rules.

          Pro Tip

          Después de ejecutar la fórmula, filtra la columna Category por "Sin categoría" y ordena por Amount en forma descendente. Las transacciones sin mapear más grandes te muestran exactamente qué reglas agregar primero.
          6

          Crea la grilla de resumen con SUMIFS

          La pestaña Summary agrega totales por categoría y mes. Configura una grilla con las categorías en la columna A y los meses en la fila 1 (formateados como el primer día de cada mes, p. ej., 2026-01-01). Luego, para cada celda de la grilla:

          =SUMIFS(Expenses!$F:$F, Expenses!$G:$G, $A2, Expenses!$H:$H, ">="&B$1, Expenses!$H:$H, "<"&EDATE(B$1, 1))
          

          Donde la columna F es Amount, la columna G es Category y la columna H es Date_Clean. EDATE(B$1, 1) acota el rango de fechas al mes calendario sin codificar fechas de fin en duro.

          Agrega una fila Total al final (SUMA de cada columna de mes) y una fila Presupuesto donde codifiques tu gasto planificado por categoría. La varianza es simplemente Actuals menos Presupuesto:

          =B3 - B2
          

          Aplica formato condicional a las celdas de varianza: rojo para sobre presupuesto, verde para bajo. Es una verificación útil, pero no es la salida final - es una capa de entrada.

            Pro Tip

            Usa las referencias de columna completa con cuidado. Expenses!$F:$F funciona bien en la práctica, pero escanear 1,000,000 filas para 200 filas reales desperdicia tiempo de recálculo en hojas grandes. Acota tu rango a Expenses!$F$2:$F$5000 una vez que conozcas tu volumen de datos.
            7

            Conecta el resumen a una estructura de P&L

            Este es el paso que la mayoría de las guías de control de gastos omiten. La grilla de Summary del Paso 6 es útil para la contabilidad personal, pero no es un modelo financiero - es una tabla plana. Para que sea útil como entrada a un modelo de burn o a un P&L para inversionistas, necesitas una pestaña P&L separada que trate el Summary como una capa de Actuals.

            Configura la pestaña P&L con tu estructura completa de líneas en la columna A, alineada a cómo aparecen los costos en un estado de resultados real:

            LíneaEneFebMar
            Ingresos
            Costo de Ventas
            - Hosting e Infraestructura
            - Procesamiento de Pagos
            Utilidad Bruta
            Gastos Operativos
            - Software y Suscripciones
            - Nómina
            - Marketing
            - Viajes
            Total OpEx
            EBITDA

            Cada celda de Actuals en el P&L jala de Summary usando una referencia directa o un SUMIFS que mapea las líneas del P&L a las categorías de Summary:

            =SUMIFS(Summary!$B:$B, Summary!$A:$A, "Software")
            

            Para categorías que se consolidan en una línea del P&L (p. ej., "Hosting e Infraestructura" puede combinar filas de Summary de AWS, Google Cloud y Cloudflare), usa múltiples SUMIFS:

            =SUMIFS(Summary!B:B,Summary!A:A,"Software") + SUMIFS(Summary!B:B,Summary!A:A,"Hosting")
            

            Esta es la arquitectura: el categorizador llena Summary, Summary es la capa de entrada de Actuals y la pestaña P&L es el modelo. Los ingresos van al P&L directamente o desde su propio feed. Desde aquí, tus actuals mensuales fluyen naturalmente a los cálculos de burn rate y runway - para esa estructura, consulta cómo calcular el runway de una startup y dashboard de burn rate para startups.

              Pro Tip

              Agrega una fila de Presupuesto en el P&L que haga referencia a una pestaña de supuestos separada, no a valores codificados en duro. La varianza presupuestaria en el P&L queda como =Actuals - Presupuesto, y cualquier revisión del presupuesto solo requiere cambiar una celda en los supuestos.
              8

              Automatiza la ingesta con Apps Script

              La fórmula de arreglo del Paso 5 ejecuta una comparación N × M en cada recálculo - cada fila en Expenses escaneada contra cada fila de la tabla de Rules. Con 500 filas de gastos contra una tabla de 50 reglas, eso son 25,000 búsquedas por recálculo. Con 10,000 filas, se convierte en 500,000, y notarás que la hoja se congela por varios segundos cada vez que cambia una celda.

              Para conjuntos de datos de más de 2,000 filas, mueve la categorización a Apps Script. La lógica es idéntica, pero se ejecuta una sola vez y escribe los resultados en un único lote:

              function categorizeExpenses() {
                const ss = SpreadsheetApp.getActiveSpreadsheet();
                const expenses = ss.getSheetByName('Expenses');
                const rules = ss.getSheetByName('Rules');
              
                const expData = expenses.getDataRange().getValues();
                const ruleData = rules.getRange(2, 1, rules.getLastRow() - 1, 2).getValues();
              
                const categories = [];
              
                for (let i = 1; i < expData.length; i++) {
                  const vendor = String(expData[i][4]).toUpperCase(); // Vendor_Clean column
                  let matched = 'Uncategorized';
              
                  for (const [keyword, category] of ruleData) {
                    if (vendor.includes(String(keyword).toUpperCase())) {
                      matched = category;
                      break;
                    }
                  }
                  categories.push([matched]);
                }
              
                // Single batch write - never write inside the loop
                expenses.getRange(2, 6, categories.length, 1).setValues(categories);
              }
              

              La regla crítica: nunca llames a setValue() dentro de un bucle. Cada escritura individual dispara un ida y vuelta a la API de Sheets. Con 10,000 filas, escribir dentro del bucle puede tomar más de 15 minutos. El setValues() en lote al final ejecuta la misma operación en menos de 10 segundos.

              Conecta esto a un trigger en Extensiones → Apps Script → Activadores para que se ejecute automáticamente al editar, o configúralo para que se dispare cuando cambie la pestaña Import. A partir de abril de 2026, el tiempo de ejecución de Apps Script está limitado a 6 minutos para cuentas de consumidor y 30 minutos para cuentas de Workspace - el patrón de escritura en lote te mantiene cómodamente dentro de ambos límites, incluso con el máximo de 10 millones de celdas de Google Sheets.

                Pro Tip

                Agrega SpreadsheetApp.flush() después de setValues() si estás encadenando múltiples escrituras en lote. Sin él, Sheets puede almacenar los cambios en búfer y aplicarlos fuera de orden.

                Conclusión

                Lo que construiste es un pipeline de datos, no un simple registro. Import es una zona de pegado que sobrevive cualquier formato de exportación. Expenses normaliza y categoriza. Summary agrega. P&L consume. Cada capa hace un trabajo y se lo pasa a la siguiente - lo que significa que cuando tu banco cambia el formato CSV o agregas una nueva categoría de proveedor, cambias una cosa y el resto se actualiza automáticamente.

                El error que cometen la mayoría de los setups de gastos es tratar la grilla de Summary como la salida final. No lo es. Es un feed de actuals. En el momento en que lo conectas a una pestaña de P&L con ingresos y una estructura de líneas adecuada, esto deja de ser un ejercicio contable y se convierte en un modelo financiero.

                Elige un plan de ModelMonkey - funciona tanto en Google Sheets como en Excel, y puede manejar la categorización, el conexionado de fórmulas y la configuración de la estructura del P&L a través de una sola conversación.

                Preguntas frecuentes

                ¿Por qué el categorizador INDEX/MATCH necesita Ctrl+Shift+Enter?

                La fórmula usa ISNUMBER(SEARCH(...)) para verificar todas las filas de palabras clave simultáneamente, lo que requiere evaluación de arreglo. Sin Ctrl+Shift+Enter (o un envoltorio explícito de ARRAYFORMULA), Sheets la evalúa como una operación escalar solo contra la primera fila de la tabla de Rules. En la práctica: si tu categorizador devuelve solo la primera categoría para cada proveedor, olvidaste ingresarla como fórmula de arreglo.

                ¿Cuántas filas debo extender las fórmulas hacia abajo?

                Extiende tus fórmulas de Expenses a 5,000 filas si eres operador individual; a 20,000 si jalás de múltiples fuentes o procesas un año completo de una vez. Las fórmulas SUMIFS y P&L usan rangos acotados de todos modos, por lo que las filas vacías al final de Expenses no inflan los totales. Evita extender a 1,000,000 filas - las referencias de columna completa en conjuntos de fórmulas grandes causan recálculo lento en cada edición.

                ¿Cómo manejo el mismo proveedor que aparece con 5 variantes distintas?

                Agrega las 5 variantes como filas separadas en la tabla de Rules, cada una mapeando a la misma Categoría. Si las variantes comparten una subcadena distintiva (p. ej., todas contienen "STRIPE"), una sola regla con esa subcadena las cubre a todas. Si no comparten una cadena común, necesitas una fila por variante. Esto es esperado - los procesadores de pago y los sistemas POS generan cadenas de proveedor inconsistentes, y una tabla de reglas robusta lo contempla en lugar de intentar limpiarlo upstream.

                ¿Puede manejar gastos en múltiples monedas?

                La lógica de fórmulas es agnóstica a la moneda - categoriza por cadena de proveedor independientemente de la divisa. Para el seguimiento multimoneda, agrega una columna Moneda en Expenses y una columna Tipo_FX que convierta a tu moneda de reporte. Los SUMIFS en Summary deben referenciar la columna convertida (=Amount * Tipo_FX), no el Amount crudo. Los tipos de cambio pueden jalarse con =GOOGLEFINANCE("CURRENCY:USDMXN") para tasas en tiempo real, o codificarse en duro para un período de reporte.

                ¿Cómo evito que la tabla de Rules crezca sin control?

                Audítala trimestralmente. Filtra la columna Category por "Sin categoría" y agrega reglas para cualquier proveedor con gasto superior a $50 USD/mes que aún no esté categorizado. Elimina las reglas de proveedores que ya no uses - las reglas inactivas ralentizan el escaneo de la fórmula de arreglo sin ningún beneficio. Una tabla de reglas bien mantenida para una operación freelance típica tiene entre 30 y 80 filas; si la tuya se acerca a 200, probablemente tengas reglas superpuestas o redundantes que pueden consolidarse.