Usando solo hojas de cálculo podemos crear nuestro propio sistema automático de recordatorios y avisos para hacerle saber a otros sobre cualquier tema futuro. Puede ser un aviso de pago de una renovación futura o un amigable recordatorio de asistir a la junta de padres de familia de la escuela. Hoy, usaremos Google Sheets para crear este útil sistema que una vez terminado, como por arte de magia enviará correos automáticamente en una fecha determinada usando triggers o activadores.
Preparando el documento con nuestros datos
Supongamos que queremos avisar por correo con anticipación sobre algún tema a algunas personas. La idea es que nosotros solo debemos ajustar la fecha en que se enviará el recordatorio futuro, escribir los mensajes correspondientes y la hoja de cálculo hará el resto.
Para lograrlo, vamos a preparar un documento con una hoja llamada Recordatorios con las siguientes columnas: Nombre, Correo, Fecha del recordatorio, Asunto y Mensaje. El nombre de la hoja y estas 5 columnas deben estar así y en este orden para que el código que usaremos después funcione. A la derecha podemos agregar más columnas con datos adicionales que pueden servir para incluir información en el mensaje. En mi ejemplo se puede ver una columna con una fecha de renovación y otra con datos sobre una ubicación para una junta de padres de familia, pero en realidad puede ser lo que tú quieras.
Triggers (activadores) y envío de correos
Para crear este proyecto en Google Sheets, necesitamos usar dos funcionalidades que ya hemos visto antes: triggers (activadores en español) y envío de correos usando código de Apps Script.
Recordemos que un trigger es una funcionalidad de Apps Script que permite ejecutar una función automáticamente dado un evento específico. En nuestro caso el trigger deberá ejecutarse automáticamente una vez todos los días, y cuando coincida el día actual con el día del recordatorio, deberá enviar el correo.
Código para automatizar envío de recordatorios y avisos por correo
Para lograr nuestro cometido, vamos a utilizar código en la plataforma de Apps Script, que es la forma en la que aumentamos las capacidades de nuestra hoja de cálculo mediante código.
Entonces vamos al menú Extensiones – Apps Script, borramos el código inicial que vemos, y lo reemplazamos por este. No te preocupes, no es mucho y lo explicaremos paso a paso 😉.
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Recordatorios')
.addItem('Activar recordatorios', 'activar_trigger_recordatorios')
.addItem('Desactivar recordatorios', 'desactivar_trigger_recordatorios')
.addToUi();
}
function activar_trigger_recordatorios() {
if(checar_trigger("enviar_recordatorios")) {
SpreadsheetApp.getUi().alert("Los recordatorios ya estaban activados.");
} else {
crear_trigger("enviar_recordatorios");
SpreadsheetApp.getUi().alert("Recordatorios activados");
}
}
function desactivar_trigger_recordatorios() {
if(checar_trigger("enviar_recordatorios")) {
borrar_trigger("enviar_recordatorios");
SpreadsheetApp.getUi().alert("Recordatorios desactivados");
} else {
SpreadsheetApp.getUi().alert("No hay recordatorios activados.");
}
}
function checar_trigger(nombre_trigger) {
var triggers = ScriptApp.getProjectTriggers();
var trigger_existe = false;
triggers.forEach((trigger) => {
if(trigger.getHandlerFunction() === nombre_trigger) {
trigger_existe = true;
}
});
return trigger_existe;
}
function crear_trigger(nombre_trigger) {
ScriptApp.newTrigger(nombre_trigger)
.timeBased()
.atHour(0) // a las 00:00 horas aproximadamente
.everyDays(1) // diario
.create();
}
function borrar_trigger(nombre_trigger) {
var trigger = ScriptApp.getProjectTriggers().filter(t => (t.getHandlerFunction() === nombre_trigger));
ScriptApp.deleteTrigger(trigger[0]);
}
function enviar_recordatorios() {
var sheet_recordatorios = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Recordatorios");
var range_recordatorios = sheet_recordatorios.getRange("A2:E");
var datos_recordatorios = range_recordatorios.getValues().map(
([nombre, correo, fecha_recordatorio, asunto, mensaje]) =>
({nombre, correo, fecha_recordatorio, asunto, mensaje})
).filter(d => (d.nombre == "" ? false : true));
datos_recordatorios.forEach((dato) => {
var fecha = new Date(); // fecha actual al momento de ejecutar
var fecha_aviso = dato.fecha_recordatorio;
// Si coincide la fecha actual con la fecha en que debemos avisar, avisamos
if( fecha.getDate() === fecha_aviso.getDate() &&
fecha.getMonth() === fecha_aviso.getMonth() &&
fecha.getFullYear() === fecha_aviso.getFullYear()) {
MailApp.sendEmail(
dato.correo,
dato.asunto,
dato.mensaje,
);
}
});
}
Lenguaje del código: JavaScript (javascript)
Lo primero que estamos haciendo es establecer una lógica para activar o desactivar los recordatorios. Usamos la función onOpen
para agregar un menú que llamará a los métodos que harán justo eso dependiendo de nuestra necesidad. Esos dos métodos a su vez, revisan si ya existe el trigger de nombre enviar_recordatorios
con el método checar_trigger
y llaman a la función correspondiente, ya sea para para crearlo o borrarlo. De esta forma podemos crear y borrar nuestro trigger programáticamente sin necesidad de usar la interfaz gráfica.
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Recordatorios')
.addItem('Activar recordatorios', 'activar_trigger_recordatorios')
.addItem('Desactivar recordatorios', 'desactivar_trigger_recordatorios')
.addToUi();
}
function activar_trigger_recordatorios() {
if(checar_trigger("enviar_recordatorios")) {
SpreadsheetApp.getUi().alert("Los recordatorios ya estaban activados.");
} else {
crear_trigger("enviar_recordatorios");
SpreadsheetApp.getUi().alert("Recordatorios activados");
}
}
function desactivar_trigger_recordatorios() {
if(checar_trigger("enviar_recordatorios")) {
borrar_trigger("enviar_recordatorios");
SpreadsheetApp.getUi().alert("Recordatorios desactivados");
} else {
SpreadsheetApp.getUi().alert("No hay recordatorios activados.");
}
}
function checar_trigger(nombre_trigger) {
var triggers = ScriptApp.getProjectTriggers();
var trigger_existe = false;
triggers.forEach((trigger) => {
if(trigger.getHandlerFunction() === nombre_trigger) {
trigger_existe = true;
}
});
return trigger_existe;
}
Lenguaje del código: JavaScript (javascript)
Fíjate bien en la función crear_trigger
, pues ahí es donde está la configuración del activador. Estamos diciéndole que será basado en tiempo (timeBased
), y que se debe ejecutar a las 00:00
horas cada 1
días. Como nota aquí, Google decidirá el minuto exacto en el que se ejecutará nuestro activador, es decir, cuando le decimos 00:00
horas, en realidad le estamos indicando “en algún momento entre las 12:00 AM y la 1:00 AM”.
function crear_trigger(nombre_trigger) {
ScriptApp.newTrigger(nombre_trigger)
.timeBased()
.atHour(0) // a las 00:00 horas aproximadamente
.everyDays(1) // diario
.create();
}
function borrar_trigger(nombre_trigger) {
var trigger = ScriptApp.getProjectTriggers().filter(t => (t.getHandlerFunction() === nombre_trigger));
ScriptApp.deleteTrigger(trigger[0]);
}
Lenguaje del código: JavaScript (javascript)
Código para el envío de correos
Ahora vamos a revisar la parte del código que envía el mensaje. Esto lo recordarás del tutorial para enviar correos con Google Sheets con archivos adjuntos, pues es muy similar.
En la función enviar_recordatorios()
, primero estamos obteniendo la información de la hoja Recordatorios y el rango de A2:E
, que es donde está la información que nos interesa. Luego, en el objeto datos_recordatorios
recopilamos toda esa información y mapeamos las propiedades que necesitaremos después, como nombre
, correo
, fecha_recordatorio
, asunto
y mensaje
. Filtramos también para no leer filas con datos incompletos, como el nombre.
Después, recorremos este objeto para procesar cada registro como un aviso de recordatorio. Creamos una variable con la fecha actual, y otra con la fecha indicada en el recordatorio correspondiente. Con un condicional comparamos el día, mes y año de ambas fechas, y si coincide usamos la clase MailApp para enviar el correo.
function enviar_recordatorios() {
var sheet_recordatorios = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Recordatorios");
var range_recordatorios = sheet_recordatorios.getRange("A2:E");
var datos_recordatorios = range_recordatorios.getValues().map(
([nombre, correo, fecha_recordatorio, asunto, mensaje]) =>
({nombre, correo, fecha_recordatorio, asunto, mensaje})
).filter(d => (d.nombre == "" ? false : true));
datos_recordatorios.forEach((dato) => {
var fecha = new Date(); // fecha actual al momento de ejecutar
var fecha_aviso = dato.fecha_recordatorio;
// Si coincide la fecha actual con la fecha en que debemos avisar, avisamos
if( fecha.getDate() === fecha_aviso.getDate() &&
fecha.getMonth() === fecha_aviso.getMonth() &&
fecha.getFullYear() === fecha_aviso.getFullYear()) {
MailApp.sendEmail(
dato.correo,
dato.asunto,
dato.mensaje,
);
}
});
}
Lenguaje del código: JavaScript (javascript)
Si guardamos nuestro código y lo ejecutamos una vez, nos pedirá aceptar los permisos de siempre para asegurar que el código que usamos pueda usar los datos de nuestra hoja de cálculo. Una vez hecho eso, vamos al menú que hicimos de Recordatorios – Activar recordatorios. Debe mostrarnos el mensaje que habíamos visto hace un momento en el código confirmando que se activó el trigger correctamente.
Si probamos la otra opción, deberá desactivarlos.
Por ahora los activamos de nuevo.
Ahora solamente resta esperar a alguna de las fechas de recordatorio para que se envíen los avisos correspondientes automágicamente. ¡Genial!, ¿no? 😉
Revisar si se enviaron los recordatorios
Ahora, para saber si se están enviando nuestros avisos por correo será muy útil que vayamos de nuevo a Extensiones – Apps Script, y del lado izquierdo en la sección de Activadores, primero revisamos si efectivamente está instalado nuestro trigger y si marca un porcentaje mayor a 0% de errores al ejecutarse.
De nuevo en el menú del lado izquierdo, ahora vamos a la sección de Ejecuciones. Ahí podemos ver todas las ejecuciones que se han hecho de nuestro código, con información sobre si se completaron o no. En la columna de Tipo vemos que cuando un trigger de tiempo invoca la ejecución, se marca como “A partir del tiempo”.
Documentación y limitaciones
Recuerda revisar la documentación correspondiente a los triggers si es que quieres hacer cambios al código:
También será útil que revises la referencia de los límites y cuotas que aplican a los triggers y al número de correos que se pueden enviar por día.
¡Y listo! Ahora ya sabes cómo crear un sistema de recordatorios o avisos futuros por correo para cualquier necesidad que tengas. Lo mejor es que como usamos hojas de cálculo de Google Sheets, podrás ahorrarte mucho tiempo de redactar y programar mensajes muy parecidos, pues ya no tendrás que hacerlos uno por uno.
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.
el codigo tiene un error cuando valida la igualdad de las fechas, en el mes, faltan parentesis al metodo fecha.getMonth
¡Hola! Muchas gracias por la corrección, tienes toda la razón. Ya está actualizado el código. ¡Un saludo! 😃