Con la opción de triggers o activadores de Google Sheets, podemos automatizar casi cualquier cosa. Es cuestión de indicarle cada cuánto tiempo debe hacerlo, y listo. Imagina alguna tarea que debas realizar constantemente cada cierto tiempo, por ejemplo, reportar un gasto que se repite siempre en el mismo día del mes. Hoy, creando un pequeños sistema práctico, vamos a aprender a usar los activadores o triggers en hojas de cálculo de Google Sheets para automatizar todo tipo de tareas.
¿Qué es un trigger? (Activador)
OK, tenemos que comenzar explicando lo más fundamental: ¿qué es un trigger?
Un trigger (activador, en español) es una funcionalidad de Apps Script que permite ejecutar una función automáticamente dado un evento específico. Existen dos tipos de triggers: simples e instalables.
Los triggers simples vienen ya integrados como parte de Apps Script y los hemos visto muchas veces antes en otras guías: onOpen
y onEdit
son dos ejemplos muy claros. onOpen
se activa cada vez que se abre el documento, y es como obtenemos esos prácticos menús. onEdit permite realizar algo al detectar que se edita alguna celda. Son muy útiles, pero al mismo tiempo algo limitados, pues todavía requieren cierto nivel de interacción por parte del usuario.
Los triggers o activadores instalables también permiten ejecutar funciones automáticamente, pero con mucha mayor flexibilidad, pues pueden ser activados automáticamente cada cierto tiempo y por medio de código. Por ejemplo, podemos dejar la instrucción de que cierta función se ejecute solo una vez en una fecha futura específica, o que se ejecute cada día a cierta hora, cada hora o incluso cada minuto.
Automatizar agregar registros dependiendo del día del mes
OK, vamos a crear un ejemplo para ilustrar el funcionamiento de los triggers y al mismo tiempo terminar con un pequeño sistema automático de registro de transacciones basado en el día del mes en el que se deben agregar.
Primero, creamos un documento y le agregamos datos muy sencillos. En la primera hoja, que llamamos Registros, tenemos 3 columnas en donde registramos transacciones que van ocurriendo en una cierta fecha: Fecha, Concepto y Monto.
Luego tenemos una hoja que llamamos Programadas. Aquí tenemos 3 columnas: Día del mes, Concepto y Monto. Esta información la usaremos para saber cuándo se debe agregar una fila a Registros, dependiendo del día del mes que sea. Por ejemplo, si el cobro de una suscripción se hace siempre el día 10 de cada mes, esperaríamos que ese día se agregara una fila nueva a la hoja de Registros. Es un concepto realmente simple, pero que justamente requiere que alguien o algo recuerde registrar esa transacción cada vez que llegue el día 10 del mes. Este es un escenario perfecto para crear un trigger.
Código para registrar transacciones dependiendo del día del mes
Ahora necesitamos crear un poco de código que haga lo que queremos: revisar la hoja de transacciones Programadas, comparar el día del mes actual, y agregar las transacciones correspondientes. No te preocupes, no es mucho código ni muy complicado y todo lo explicaremos paso a paso.
Entonces vamos al menú Extensiones – Apps Script, borramos el código que vemos por default, y lo reemplazamos por este:
function agregar_registros() {
var sheet_registros = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Registros");
var sheet_programadas = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Programadas");
var range_programadas = sheet_programadas.getRange("A2:C");
var datos_programadas = range_programadas.getValues().map(
([dia_mes, concepto, monto]) =>
({dia_mes, concepto, monto})
).filter(d => (d.dia_mes == "" ? false : true));
// Recorremos los datos programados
datos_programadas.forEach((dato) => {
var fecha = new Date(); // fecha actual
var year = fecha.getFullYear(); // Obtenemos el año
var dia = fecha.getDate(); // Obtenemos el día del mes
var mes = fecha.getMonth() + 1; // +1 porque el num del mes empieza en 0 para getMonth
// Para obtener el formato de fecha YYYY-M-D sin minutos ni segundos
var fecha_simple = `${year}-${mes}-${dia}`;
// Si coincide el día de ejecución con el día del mes, agregamos la fila
if(dato.dia_mes === dia) {
sheet_registros.appendRow([fecha_simple, dato.concepto, dato.monto]);
}
});
}
Lenguaje del código: JavaScript (javascript)
En esta función de agregar_registros, primero creamos las variables necesarias para manejar las hojas Registros y Programadas.
function agregar_registros() {
var sheet_registros = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Registros");
var sheet_programadas = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Programadas");
Lenguaje del código: JavaScript (javascript)
Después obtenemos el rango de las transacciones mensuales programadas como A2 a C con getRange para asegurar los datos desde la segunda fila hasta cualquier número de filas hacia abajo, de nuestras 3 columnas.
var range_programadas = sheet_programadas.getRange("A2:C");
Lenguaje del código: JavaScript (javascript)
Luego, obtenemos los valores de este rango y los mapeamos a un arreglo de objetos con propiedades correspondientes a las 3 columnas: día del mes, concepto y monto. También filtramos los datos del día del mes que estén vacíos para solamente tener los datos que necesitamos y no más.
var datos_programadas = range_programadas.getValues().map(
([dia_mes, concepto, monto]) =>
({dia_mes, concepto, monto})
).filter(d => (d.dia_mes == "" ? false : true));
Lenguaje del código: JavaScript (javascript)
Ahora solamente recorremos cada fila de los datos de las transacciones programadas. Inicializamos una fecha, y la separamos en el día y el mes. Aquí necesitamos construir la fecha en el formato que la teníamos, es decir 4 dígitos de año, guión, mes (teniendo cuidado en que getMonth regresa el número de mes empezando en 0), guión y día, y lo llamamos fecha_simple
.
// Recorremos los datos programados
datos_programadas.forEach((dato) => {
var fecha = new Date(); // fecha actual
var year = fecha.getFullYear(); // Obtenemos el año
var dia = fecha.getDate(); // Obtenemos el día del mes
var mes = fecha.getMonth() + 1; // +1 porque el num del mes empieza en 0 para getMonth
// Para obtener el formato de fecha YYYY-M-D sin minutos ni segundos
var fecha_simple = `${year}-${mes}-${dia}`;
// Si coincide el día de ejecución con el día del mes, agregamos la fila
if(dato.dia_mes === dia) {
sheet_registros.appendRow([fecha_simple, dato.concepto, dato.monto]);
}
});
Lenguaje del código: JavaScript (javascript)
Ahora sí, con un simple condicional de if, comparamos el día del mes del dato de la fila que estamos considerando, con el día actual, y si coincide, usamos appendRow
para insertar una fila nueva a la hoja de registros. Si no coincide, simplemente no haremos nada. Un pequeño detalle que debes tomar en cuenta aquí es que este algoritmo solo funcionará para días de mes que todos los meses tengan, porque por ejemplo, no todos los meses tienen día 31. Entonces es preferible usar el 28 como último día. Podríamos ajustar el código para arreglar este detalle, pero se haría más complicado, y para efectos de esta demostración, no vale la pena, pero resolverlo es un buen ejercicio y reto que podrías ponerte.
Si ejecutamos la función de este código manualmente, funcionará como esperamos, solo debe agregar la transacción que coincida con el día. Pero, no queremos tener que hacer esto diario, ¿verdad? 😉. Entonces, vamos a instalar un trigger o activador para lograr que este código se ejecute todos los días al menos una vez, que es justo lo que necesitamos.
Instalar un trigger (activador)
Hay dos formas de instalar un activador o trigger: mediante la interfaz gráfica de Apps Script y mediante código. Vamos a demostrar la primera, que es la más sencilla.
En nuestro editor de código vamos al panel de iconos de la izquierda y elegimos la opción que tiene un reloj, llamada Activadores.
Aquí podremos ver los triggers o activadores que tengamos vigentes, así como el tipo de evento que los invoca, la función que llaman en el código y el porcentaje de errores que hayan sucedido en sus ejecuciones, si los hubiese.
Damos click en el botón de Añadir activador (en inglés, Add trigger). En la pantalla que nos aparece, debemos elegir qué función se va a ejecutar, en nuestro caso será agregar_registros. El despliegue o implementación se queda como Principal. La fuente del evento es la clave de todo esto, porque luego de elegir Según tiempo, podremos ver las opciones de cada cuánto tiempo se debe ejecutar nuestra función por sí sola.
Como seguro ya habrás adivinado, necesitamos seleccionar la opción de Temporizador por días. Esto nos permitirá seleccionr la hora del día también, y lo dejamos como 00:00 a 01:00 horas. Fíjate bien cómo nos marca la zona horaria también, que no podemos cambiar aquí pero sabemos que depende de nuestra configuración regional y del documento.
Guardamos nuestro trigger, y si dejamos pasar algunos días en donde el día del mes coincida con alguno de los datos que pusimos en la hoja de Programadas, debemos tener datos nuevos en la hoja de Registros, sin haber siquiera abierto el documento. ¡Genial!, ¿no? 😉
Si vamos al editor de código de nuevo, y en la parte izquierda elegimos la opción de Ejecuciones, veremos un registro de las veces en las que se ejecutó nuestro trigger, la hora a la que inició la ejecución y cuánto tardó en ejecutarse. También podremos ver si alguna de estas tuvo un error. Así podremos asegurarnos de que nuestro trigger está ejecutándose correctamente.
Instalar un trigger con código
Antes de terminar, quiero que revisemos brevemente cómo instalar el mismo trigger pero solamente usando código, por si quisiéramos instalar más de un trigger a la vez en varios documentos, porque en ese caso usar la interfaz gráfica será un poco tedioso.
En nuestro editor de código, agregamos esto abajo:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Triggers')
.addItem('Activar trigger registros', 'activar_trigger_registros')
.addToUi();
}
function activar_trigger_registros() {
if(checar_trigger("agregar_registros")) {
SpreadsheetApp.getUi().alert("El trigger ya estaba activado. No se creó uno nuevo.");
} else {
crear_trigger_registros();
SpreadsheetApp.getUi().alert("Trigger instalado correctamente");
}
}
function checar_trigger(funcion) {
var triggers = ScriptApp.getProjectTriggers();
var trigger_existe = false;
triggers.forEach((trigger) => {
if(trigger.getHandlerFunction() === funcion) {
trigger_existe = true;
}
});
return trigger_existe;
}
function crear_trigger_registros() {
ScriptApp.newTrigger("agregar_registros")
.timeBased()
.atHour(0) // a las 00:00 horas aproximadamente
.everyDays(1) // diario
.create();
}
Lenguaje del código: JavaScript (javascript)
Como puedes ver, estamos usando onOpen
para agregar un menú que ejecuta la función activar_trigger_registros. Esta función a su vez, revisa si ya existe un trigger para la función agregar_registros
con la función checar_trigger usando la clase ScriptApp
para obtener los triggers actualmente instalados. Si ya existe, solamente veremos un mensaje, pero si no existe, vamos a la función crear_trigger_registros y utilizando ScriptApp
y el método newTrigger
, le damos las mismas instrucciones que hace unos momentos sobre cada cuánto debe ejecutarse.
Documentación y cuotas relevantes a triggers (activadores)
Si quieres instalar los triggers por código, es muy conveniente revisar la documentación oficial de la clase Trigger y ClockTriggerBuilder para que puedas configurarlo correctamente, ya que permite hacer más cosas que la interfaz gráfica, como por ejemplo especificar la zona horaria en la que debe ejecutarse el trigger.
También es importante revisar la referencia de los límites y cuotas que aplican a los triggers, pues por ejemplo, al momento de publicar esta guía, el número máximo de triggers que se pueden instalar por usuario y por script es de 20, y el tiempo máximo acumulado que puede ejecutarse un trigger es de 90 minutos para una cuenta gratuita y hasta 6 horas para una cuenta de Google Workspace de empresa.
¡Y listo! Ahora ya sabes cómo usar los triggers para automatizar cualquier tarea mediante un temporizador que ejecutará la instrucción que quieras en los intervalos de tiempo que quieras.
Plantilla terminada para descargar
Guía en video
Si tienes dudas puedes ver esta misma guía explicada en video:
¡Espero que te haya sido útil esta guía! No olvides seguirnos en YouTube para más tips, trucos y guías de productividad.
Alekz es un apasionado de la tecnología y los videojuegos. Además de ser locutor comercial, disfruta de la expresión artística más sastisfactoria y técnica que existe: programar (y pintar algo de pixel art). Fundó Tesel para ayudar a empoderar a las empresas a desarrollar su máximo potencial mediante la tecnología. Es un absoluto nerd de Star Trek.
Alekz es un apasionado de la tecnología y los videojuegos. Además de ser locutor comercial, disfruta de la expresión artística más sastisfactoria y técnica que existe: programar (y pintar algo de pixel art). Fundó Tesel para ayudar a empoderar a las empresas a desarrollar su máximo potencial mediante la tecnología. Es un absoluto nerd de Star Trek.