Grist: la hoja con base de datos que arregla acumulados

Por qué tu balance acumulado se rompe al insertar una fila

Un acumulado que falla en silencio es más peligroso que uno que muestra un error. En una hoja de cálculo tradicional, insertar una transacción en medio de la tabla no dispara ninguna alerta: el saldo simplemente queda mal desde esa fila hacia abajo.

El caso es concreto. Tienes transacciones una por fila y un saldo que se calcula como el saldo de arriba más el monto de la fila. Llega un recibo del 11 de enero y lo insertas entre las filas 3 y 4. La fila nueva no tiene fórmula, así que la copias. Pero el saldo de abajo ahora dice =C3+B5: al desplazarse las filas, la referencia se ajustó para seguir apuntando a la misma celda, y esa celda ya no es la de arriba. La transacción nueva se salta sin mostrar ningún error.

Si en lugar de insertar borras una fila, el resultado es el opuesto: la fórmula de abajo se convierte en #REF! y arrastra a todos los saldos siguientes.

¿Y esto cómo se aplica en tu negocio?

Dueños de negocio de Latinoamérica y España usan un agente de IA para ganar más y recuperar su tiempo. El Kit «tu mano derecha con IA» te muestra cómo en un video de 11 minutos, con una ficha para armar el tuyo. CAR está cerrada por ahora; al anotarte, te avisamos cuando abra.

👥 Quiero el Kit →

No es un bug. Para una hoja de cálculo tradicional, "la transacción anterior" significa "la celda de arriba". Las dos cosas coinciden solo mientras nadie reordene nada.

Qué cambia cuando la fórmula dice "la transacción anterior por fecha"

Grist, la herramienta de hoja de cálculo relacional con base de datos, publicó en su blog un enfoque distinto: en lugar de referenciar una celda, la fórmula referencia un registro ordenado. La sintaxis es esta:

prev_balance = PREVIOUS(rec, order_by="Date").Running_Balance or 0

PREVIOUS() ordena la tabla por fecha, encuentra el registro actual y devuelve el anterior. Como devuelve el registro completo y no una celda, se puede leer su campo de saldo. La primera transacción no tiene anterior, de ahí el or 0.

La diferencia clave es dónde vive el orden: en la fórmula, no en la vista. Inserta una transacción en cualquier parte y se acomoda por su fecha. Bórrala y los saldos se cierran alrededor. Ordena la tabla por monto o aplícale un filtro y cada registro conserva su saldo por fecha, porque eso fue lo que se pidió.

El mismo mecanismo resuelve el caso de una cuenta con varios titulares. En vez de partir los datos en una tabla por persona, se agrega el parámetro de agrupación: PREVIOUS(rec, group_by="Card_Member", order_by="Date").Balance or 0. Así cada tarjetahabiente tiene su propio acumulado dentro de la misma tabla, y se pueden tener varios acumulados en paralelo: uno de la cuenta completa, uno por persona, uno que reinicia cada mes.

PREVIOUS() tiene dos hermanas: NEXT() mira hacia adelante y RANK() asigna la posición en el orden, de modo que RANK(rec, order_by="-Amount") <= 10 marca las diez transacciones más grandes.

El costo oculto de calcular un acumulado con un bucle

Las fórmulas de Grist son Python, así que siempre se pudo escribir esto a mano: traer los registros, recorrerlos, elegir el correcto. La pregunta es cuánto cuesta.

Un acumulado hecho con escaneo, SUM(r.Amount for r in Transactions.all if r.Date <= $Date), mira la tabla completa por cada registro. Con 1.000 transacciones son un millón de pasos; con 20.000, 400 millones. En una tabla de prueba de 20.000 transacciones, PREVIOUS() calculó toda la columna de saldos en segundos, mientras la versión con escaneo seguía corriendo después de cinco minutos.

La razón es que las búsquedas ordenadas no escanean: mantienen los registros ordenados y encuentran lo pedido con búsqueda binaria, que es la forma rápida de hacerlo.

Tarifas vigentes, comisiones y tramos: el otro problema del orden

Una vez que una búsqueda entiende de orden, "anterior" es solo una de las preguntas posibles. El artículo de Grist usa el ejemplo de tarifas por hora que cambian en el tiempo: Bertha gana 110 dólares la hora desde el 30 de agosto de 2019 y 125 desde el 24 de marzo de 2020. Una nómina de febrero de 2020 necesita la tarifa vigente en su fecha, es decir, la última que empezó en o antes de esa fecha.

Con lookupRecords(Person=$Person, order_by="Rate_Start") y find.le($Date) se obtiene exactamente eso. Nada de esto es específico de fechas: los tramos de comisión funcionan igual, con lookupRecords(order_by="Sales_Target") y find.le($Sales_Amount).

En Excel y Google Sheets esto se conoce como coincidencia aproximada: VLOOKUP() con VERDADERO como último argumento. La documentación de Microsoft advierte que la primera columna debe estar ordenada y que, si no lo está, "el valor devuelto puede ser algo que no esperas". Sin error, solo una respuesta distinta. En Grist el orden es parte de la fórmula: ordena los tramos por su cuenta, sin importar cómo se presenten en pantalla.

Las mismas dos líneas responden una familia entera de preguntas de coincidencia más cercana: la tarifa vigente en una fecha, el tramo de comisión de una venta, la tarifa de envío según el peso, el tramo de impuestos de un ingreso o el tipo de cambio del día de una compra. Y para la pregunta más simple —el primer o último registro de un grupo— no hace falta find(): Orders.lookupOne(Customer=$id, order_by="-Date") devuelve el pedido más reciente, porque el signo menos indica orden descendente.

Cómo se compara con Airtable, Notion y las hojas clásicas

En las hojas tradicionales hay trucos conocidos: Vertex42 propone OFFSET() o un rango con nombre relativo para apuntar a "la celda de arriba" de forma que sobreviva a las ediciones, y Exceljet propone una única fórmula SCAN() para toda la columna en Excel 365.

Las herramientas tipo base de datos con interfaz de hoja tienen el problema inverso: según el artículo de Grist, en Airtable y Baserow una fórmula solo puede ver el registro en el que está, y lo mismo ocurre con NocoDB y las bases de Notion. Quien pregunta en esos foros cómo hacer un acumulado termina en scripts o vinculando cada registro con el anterior a mano. Evitan el problema no teniendo "fila de arriba", pero la necesidad sigue ahí: un saldo corriente, los días desde la última visita de un paciente, el stock que queda después de cada envío.

SQL ya tenía la respuesta: funciones de ventana como LAG y LEAD para la fila anterior y la siguiente, o SUM(amount) OVER (PARTITION BY account ORDER BY date) para un acumulado. Funcionan, pero son una herramienta avanzada para quien escribe consultas, no para quien trabaja en una tabla.

Un dato relevante para equipos pequeños: Grist es de código abierto y se puede instalar en un servidor propio con Docker, según documenta XDA Developers, lo que permite mantener los documentos dentro de la propia infraestructura y controlar accesos y respaldos.

¿Qué significa esto para tu startup?

Si tu operación corre sobre hojas de cálculo o bases tipo Airtable, es probable que ya tengas acumulados frágiles sin saberlo. Cuatro cosas para revisar:

  • Haz la prueba de la fila insertada. Toma tu hoja de saldos, MRR acumulado, inventario o días desde la última visita del cliente, e inserta una fila en el medio. Si el total de abajo cambia o aparece un #REF!, tu reporte depende de que nadie reordene la tabla. Ese es el riesgo real: el error no avisa.
  • Mueve el orden a la fórmula, no a la vista. Cada vez que un cálculo dependa de "el anterior", define explícitamente por qué campo se ordena y si hay agrupación. Es la diferencia entre un número que se recalcula solo y uno que hay que revisar a mano cada vez que alguien edita.
  • Usa el patrón de tarifa vigente para precios y comisiones. Si manejas planes que cambian de precio, comisiones por volumen o tramos de descuento, el lookup ordenado con find.le() evita el VLOOKUP aproximado y su dependencia de que la tabla esté ordenada.
  • Cuida el volumen antes de que duela. Si tu cálculo recorre toda la tabla por cada fila, el costo crece muy rápido: pasar de 1.000 a 20.000 registros multiplica el trabajo por 400. Vale la pena revisarlo antes de que el tablero tarde minutos en abrir.

Conclusión

La lección no es solo sobre Grist. Es sobre escribir fórmulas que digan lo que significan. "La celda de arriba" era una aproximación cómoda a "la transacción anterior", y funcionó mientras nadie movió nada. Cuando el orden se declara dentro de la fórmula, insertar, borrar, ordenar o filtrar deja de ser un riesgo y pasa a ser una operación más.

Para un equipo chico, eso es tiempo que no se gasta auditando números que deberían ser automáticos.

Fuentes

¿Y esto cómo se aplica en tu negocio?

Dueños de negocio de Latinoamérica y España usan un agente de IA para ganar más y recuperar su tiempo. El Kit «tu mano derecha con IA» te muestra cómo en un video de 11 minutos, con una ficha para armar el tuyo. CAR está cerrada por ahora; al anotarte, te avisamos cuando abra.

👥 Quiero el Kit →

Daily Shot: Tu ventaja táctica

Lo que pasó en las últimas 24 horas, resumido para que tú no tengas que filtrarlo.

Suscríbete para recibir cada mañana la curaduría definitiva del ecosistema startup e inversionista. Sin ruido ni rodeos, solo la información estratégica que necesitas para avanzar:

  • Venture Capital & Inversiones: Rondas, fondos y movimientos de capital.
  • IA & Tecnología: Tendencias, Web3 y herramientas de automatización.
  • Modelos de Negocio: Actualidad en SaaS, Fintech y Cripto.
  • Propósito: Erradicar el estancamiento informativo dándote claridad desde tu primer café.

📡 El Daily Shot Startupero

Noticias del ecosistema startup en 2 minutos. Gratis, todos los días.

Share to...