Introducción a Google Apps Script
Introducción a Google Apps Script
G.A.S.
Editor de Comandos.
La forma más adecuada para ver ejemplos de Google Script tal vez sea las hojas de cálculo. Dentro de nuestra cuenta
de Google , vamos a Drive y creamos un nuevo documento del tipo "Hojas de Cáculo".
1 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
Nos aparece el nuevo documento sin nombre, y al desplegar el menú Herramientas , elegimos "Editor de secuencias
de Comandos", de la nueva ventana elegimos "Proyecto en Blanco" ( ver figura siguiente)
En la imagen inferior muestra el Editor de comandos. Nos indica "Proyecto sin titulo" que podemos nombrar haciendo
clic y nombrando el [Link] proyecto consta como mínimo de un archivo de código , que por defecto se nombra
como "Có[Link]"; pero se puede cambiar; basta con hacer clic en el desplegable a la derecha del nombre Có[Link] ,
y el menú emergente nos da tres opciones: Eliminar, Hacer una copia , y Cambiar nombre. En la parte de la derecha
iremos escribiendo el código de nuestro script, que por defecto nos da el inicio function myFunction(){.....
En la parte superior tenemos la barra de menús: Archivo Editar Ver Ejecutar Publicar Recursos Ayuda. Debajo
del menú aparecen iconos de acciones concretas.
• En el menú Archivo están las acciones típicas : Guardar, Borrar, Nuevo, Abrir, Revisiones, etc
• En Editar , tenemos : Deshacer, Rehacer, Seleccionar, Buscar y reemplazar, etc. Aquí tenemos la opción de
activar "Asistencia de contenido", que nos ayudará al hora de escribir el código, ya que nos adelanta las
siguientes opciones que podemos tomar sin necesidad de escribir el comando.
• En Ver , existe: Transcripción de la ejecución ( nos indica todos los estados por los que va pasando el programa
en los sucesivos pasos) ; y Registros ( se utiliza cuando estamos haciendo pruebas de ejecución o
depuramiento).
• En Ejecutar : nos da la opción de ejecutar algún archivo de código que tengamos.
• En Publicar : tenemos la opción de "publicar" nuestro script en la red y se ejecutará accediendo a él mediante su
URL publicada.
• Recursos : desde aquí podemos programar en el tiempo la ejecución del script , mediante ciertos eventos.
• En el menú Ayuda : información relacionada con el tema
Como se ve el menú es similar al de cualquier documento de Google. Como se menciona anteriormente, la opción de
Asistencia de contenido es una muy buena herramienta; por ejemplo en el script en que estamos , nos situamos
2 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
debajo de la primera linea y empezamos a escribir var a = ; si después del = pulsamos CTRL+Barra esp. , veremos
que nos muestran las posibilidades de elegir lo que podríamos poner a continuación.
La opción de Asistencia de Contenido es un buen método de escritura para evitar errores en el texto del código, pero
sobre todo nos facilita , en cada momento, los métodos posibles.
Por ejemplo, imaginemos que en una linea tenemos que teclear el siguiente código :
[Link]().deleteActiveSheet() ; sería probable cometer algún error ortográfico y
fallar la ejecución. En el Proyecto sin titulo anterior, en la linea 2 empezamos a escribir una s y pulsamos CTRL+
BarraEsp., aparece una ventana emergente con las sugerencias de lo que puedo escribir (Figura izquierda). Hay que
recordar que se diferencian mayúscula y minúsculas ; Por ejemplo, getActivespreadsheet() , será una función
desconocida y no se ejecutaría el código
Entre las sugerencias aparece la "palabra" SpreadsheetApp ; la seleccionamos haciendo clic sobre ella . Al escribir el . (
punto) ,nos muestra las siguientes sugerencias,que son los métodos de la clase SpreadsheetApp ( Fig central);
seleccionamos el método que necesitamos, y así sucesivamente
Primer Script
Como primer ejemplo vamos a escribir el siguiente código, ( primero borramos las tres lineas del código existente)
Se trata de un código de 4 lineas; empieza con la palabra reservada function , con el nombre que damos a la función
seguida de () - o bloque de código- , una llave de apertura { , para indicar las lineas de código que conforman el bloque,
2 lineas de código que terminan en un un ; , y la llave de cierre }.Esta es la estructura básica de un bloque .
En la linea 2 se define una variable con la palabra reservada var y de nombre valor , con el signo = le asignamos un
valor a esa variable , que se empieza a construir a partir de la API (clase del lenguaje) SpreadsheetApp; de esa clase
se toma su método getActiveSpreadsheet(), que hace relación a documento de Hoja de cálculo abierto, y de ese
documento se toma la hoja activa , mediante le método getActiveSheet() , , y de esa hoja se define el rango formado por
la celda A2 , y se toma el valor de esa celda: todo eso para indicar que el valor de la celda A2 de la hoja activa del
documento activo del tipo Hoja de cálculo se pasa a la variable valor .
A la vez que se va escribiendo el código, Google hace un recorrido a través del mismo para indicar si hay errores de
sintáxis . Si no se indican , no es señal que el código sea correcto o que se produzcan los resultados que deseamos
La linea 3 indica que haga uso del método log de la clase Logger , para que ponga el valor de la variable valor en los
registros - o lugares que sean visibles para nosotros-
3 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
Si se observa la existencia de un asterisco rojo al lado del nombre del fichero de código: significa que debemos
guardar el fichero . Para guardar Archivo > Guardar , o bien CTRL +S . o bien clic en el icono :
Si queremos ejecutar el código pulsamos el botón de ejecutar- segundo de los anteriores- nos pedirá autorización,
aceptamos .Para ver que el código produce algo , deberemos ir a la hoja de cálculo e insertar algo en la celda A2.
Si ejecutamos el script veremos que el valor de la celda A2 de la hoja de cálculo se ha recogido en el registro , como
se comprueba al ir a Ver > Registros . Con este pequeño ejemplo ,se ve cómo se puede manipular la información de
uno de los servicios de Google, como son los Hojas de cálculo.
• es un bloque de código de lineas JavaScript englobado entre dos {.... código ... }
• empieza con la palabra reservada function , y seguido del nombre de esa funcion
• cada linea termina en un ;
• Utiliza APIs con sus métodos unidos mediante .
• El editor nos detecta los errores de sintaxis, pero pueden existir errores en tiempo de ejecución.
• Apps Script está basado en el lenguaje JavaScript , y no se ejecuta en el navegador del cliente ( salvo el código
basado en la API HTML services) . Podrá utilizar instancias de objetos tales como Array, Date,.. ( ver aquí )
Tipos de scripts:
• Standalone : este tipo de código se ejecutan de manera manual, y está asociado a los documentos de Drive.
También tienen la posibilidad de "publicar" , en el sentido que se puede acceder a ese código mediante una URL; en
estos casos se necesitan permisos para acceso a las aplicaciones que el código maneja y también para los usuarios
que vaya a utilizar ese código. El ejemplo anteriormente explicado sería de ese tipo: requiere de una acción manual
para su ejecución
• Integrados ( container bound script) en aplicaciones como Formularios, Hojas de cálculo, Google Documents . Se
utilizan para dar una mayor funcionalidad a esas aplicaciones.
A medida que escribimos el código el editor nos informa de los errores sintácticos, indicando el tipo de error y en qué
linea , mediante un mensaje con fondo rojo en la parte superior del Editor . Pero pueden existir errores solo detectados
cuando se ejecuta el código o bien no hay errores pero no se producen los resultados esperados, por eso es necesario el
proceso de depuración. Abrimos nuestro script y escribimos el siguiente código
function errores(){
var hc = [Link]().getActiveSheet();
var x = dato;
[Link](6, 2).setValue(x);
}
Veremos que el editor no nos informa de ningún error,pero si se ejecuta nos informa de que hay un error , la variable
dato no está definida .Si queremos más información de los fallos de código , se elige la función y se pulsa el botón de
depurar.
Para tratar los errores se utiliza el par de sentencias try/catch . Modificamos el código anterior por el siguiente:
function errores(){
var ss = [Link]().getActiveSheet();
try{
var x = dato;
[Link](2, 6).setValue(x);
}catch(e){
[Link]([Link]+' en la linea :'+[Link]+'=>'+[Link]);
}
4 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
Al ejecutar no da error , no se cumple el propósito que era poner un valor en la celda (F,2) el valor de la variable [Link] da
aviso de error ya que este ha sido capturado en la parte catch . Ya que se utiliza el método log , tendremos información del
error en el Registro. En este caso bastaría darle a x un valor. Si ejecutamos la función errores() , ya nos hay errores , es
decir se ejecuta el bloque try
Activadores de scripts.
Los ejemplos de funciones anteriores requerían una acción manual para su ejecución, pero existe la posibilidad de que se
ejecuten de manera automática, según qué tipo de eventos sucedan. Por ejemplo, más adelante se utilizará la función
onOpen() , que se ejecutará de manera automática al abrir la hoja de cálculo que integrante del scrip que incluya esa
funció[Link] más funciones que responden a eventos concretos:
Como estas funciones se activan cuando suceden los eventos - abrir hoja, hacer cambios, ejecutar script, cargar una
web ,..- y no se pregunta por la autorización tiene que cumplir una serie de restricciones : estar asociadas a una documento
del tipo Hoja de Cálculo, Documento o Formulario; no podrán acceder a servicios que requieran autorización ( gmail,
drive,..); tiene un tiempo limite de ejecución de 30 seg, ....
Aparte de estos Activadores de las funciones anteriores , existen otros para las funciones definidas en general. En el
Editor vamos a Recursos > Activadores del proyecto activo ; si es la primera vez nos indica que no se ha
configurado ningún activador. Hacemos clic y nos aparece la opción de configuralos
Podemos agregar más activadores para otras funciones. Tenemos que pulsar Guardar para la programación de la
ejecución quede archivada.
Scripts en Spreadsheets.
Añadir menú a una hoja de cálculo
Como anteriormente he comentado la mejor forma de ver la aplicación de los scripts es aplicándolos a las Hojas de
Cálculo (o Spreadsheets) utilizando la API SpreadsheetApp , cuya documentación podemos ver
5 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
[Link]
• Creación de un menú : en el ejemplo siguiente se creará un menú que se añadirá a la barra de herramientas de
una hoja de cálculo. Abrimos la hoja de cálculo, y vamos Herramientas > Editor de secuencias de comandos..., y
escribimos el siguiente código :
Si ejecutamos esta función y vamos a la hoja de cálculo veremos el nuevo menú . En este caso no hay ninguna acción
que vaya a realizar porque no se ha añadido, esto se haría cerando las funciones de nombres accion1 , acciojn2 y
accion3 .
Si nos fijamos en la documentación de la clase SpreadsheetApp , vemos que permite crear submenús con el método
addSubMenu() , e intercalar, opcionalmente , un separador con el método addSeparator()
El ejemplo solo muestra la creación de menú, no hay acciones asociadas a los items , además no es nada práctico ya
que para que aparezca el menú debemos lanzar manualmente el código. Podemos hacer que el menú aparezca
siempre que se abra la hoja de cálculo, sin intervención manual utilizando la función de nombre especial onOpen() , en
lugar del nombre menuNuevo() : la función onOpen() , , se ejecuta cada vez que se abre la hoja de cálculo.
Cuando se trabaja en una spreadsheet , puede ser necesario mostrar/ solicitar información al usuario, y se consigue
mediante varias formas:
• 1.- Usando la clase Logger : en el primer scrip antes mencionado se muestra un ejemplo, utilizando el método
log de dicha clase; suele utilizarse en procesos de depuración de código para ver estados del programa , por
tanto no se restringe solo al caso de hojas de cálculo . Los resultados se muestran en "registros".Como se puede
ver en su documentación la clase dispone de 4 métodos:
• 2.- Mediante la clase Browser ( solo para hojas de cálculo). Más información aquí . Como se ve en la
documentación dispone de dos métodos:inputBox() para recabar información y msgBox() para mostrarla, en
ambos cabe la posibilidad de agregar "botones" de información , basados en el "tipo" enumerado ButtonSet . Por
ejemplo el código [Link]('Hola', [Link].OK_CANCEL); produciría el siguiente mensaje.
6 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
En la imagen superior , se ha añadido la linea 15 al bloque de código del apartado anterior, y el nombre de la función, tal
como se comentó, pasa a ser onOpen() para que se ejecute al abrir la hoja. Se ve como el texto de msgBox() se muestra
en la ventana emergente, y además se ha añadido el botón de Cancelar Para el caso de inputBox() se define una variable
que recoja el valor introducido.
• 3.- Mediante el comando throw() , válido no solo en el contesto de las hojas de cálculo tal como sucede con la clase
Logger. Si en la ventana del editor ejecutamos la linea de código throw('el valor de la variable dia es :'+fecha)
; nos aparecería en la parte superior el siguiente mensaje:
• 4.- Mediante el método show() de la API SpreadsheetApp, que nos mostrará en el centro de la pantalla la Interface
gráfica especificada . La generación de Interface Gráficas se verá más adelante
• 5.- Usando el método toast() de la clase SpreadsheetApp. toast() , admite o bien dos parámetros , o bien tres ; en
este caso con el tercero se indica el tiempo en segundos que permanecerá visible la ventana emergente. Si
especificamos un número negativo , la ventana permanecerá abierta hasta que manualmente la [Link] método
toast() de la clase Spreadsheet tiene la siguiente sintaxis: toast(msg, title, timeoutSeconds)
Mediante el código Google Apps Script , podemos manejar la información de una hoja de cá[Link] procedimiento
resumido es el siguiente.
7 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
DocumentApp ) .
• Hacer mención a la hoja del documento abierto , con la que queremos trabajar, utilizando los métodos
getActiveSheet(), o getSheetByName()
• Crear el rango de [Link] posibilidad es mediante el método getSheetValues(startRow, startColumn,
numRows, numColumns), que nos devuelve una matriz bidimensional en la notación JavaScript : matriz[indice]
[indice].; otra forma es utilizando el método getRange()
• Recorrer la matriz creada de valores mediante el comando de iteración for para acceder a cada celda.
• Utilizar los comandos getValue() y setValue() para recoger o asignar valor de las celda.
Siguiendo con nuestro script empezado, lo modificamos con los siguientes cambios:
function onOpen(){
[Link]()
.createMenu('MiMenu')
.addItem('Item1', 'rellenaCeldas')
.addSeparator()
.addItem('Item2', 'accion2')
.addItem('Item2', 'accion3')
.addToUi();
//var dia = 12;
//throw('el valor de la variable dia es = ' + dia);
function rellenaCeldas(){
var hc = [Link]().getActiveSheet();
for(var fila=1 ; fila<=20; fila++){
[Link](fila, 1).setValue('El valor de la celda es '+fila);
}
}
• Se codifica una función que llamamos rellenaCeldas() , y se asocia con la primer entrada del menú creado,
MiMenu.
• Los caracteres // , permiten crear comentarios para documentar el código, cuando éste es largo y
de difícil comprensión; por lo tanto las dos lineas que empiezan con // no se ejecutan ,
• La variable hc hace referencia a la hoja activa del documento Hoja de Cálculo que integra el código ( bound-
script )
• Con el método getRange (fila,1) , hacemos referencia a cada una de las 20 primeras celdas de la columna 1
• Con el método setValue(), damos valores a esas [Link] valor que se introduce en las celdas es la cadena de
texto formada por El valor de la celda es concatenada, mediante el operador +, con el valor de la variable fila . El
operador + está 'sobrecargado' es decir por ejemplo 7+8 nos devuelve 15 , pero 7+' casas' nos devuelve 7 casas
Como he expresado, los comentarios de linea se crean con los caracteres // , por ejemplo , en la siguiente linea de
código [Link](fila, 1).setValue('El valor de la celda es '+fila); // se inserta el valor en la celda , el texto //se inserta
el valor en la celda no sería código ejecutable, sino solamente un comentario. Se pueden añadir bloques de lineas de
texto no ejecutable mediante los caracteres /* y */ . Todas las lineas encerradas entre esas dos marcas no se interpretan
por el servidor.
En la función rellenaCeldas() , se accede durante 20 veces diferentes a la variable hc, es decir hay que hacer 20
peticiones de acceso al servidor , y esto tiene un coste en el tiempo. Supongamos el caso en el que debemos poner en
un rango de celdas un mismo valor : se podría utilizar una función similar a rellenarCeldas() , o bien utilizando la
siguiente funcion rellenaCeldas2() como vemos en el código siguiente:
function onOpen(){
[Link]()
.createMenu('MiMenu')
.addItem('Completa celdas una a una', 'rellenaCeldas')
.addItem('Completa bloque', 'rellenaCeldas2')
.addSeparator()
.addItem('Item2', 'accion3')
8 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
.addToUi();
//var dia = 12;
//throw('el valor de la variable dia es = ' + dia);
/*
var iG = HtmlService
.createHtmlOutput('<p><b>Mensaje importante<b></p>')
.setSandboxMode([Link])
.setTitle('Ejemplo de Aplicación')
.setWidth(250)
.setHeight(250);
[Link]().show(iG);
*/
function rellenaCeldas2(){
var inicio =new Date().getTime();// defino la misma variable que en la función anterior, pero son
diferentes: una variable desaparece cuando nos salimos del bloque en el que se define
var hc = [Link]().getActiveSheet();
[Link](1,2,200,1).setValue('Celdas columna-2');// accedo solo una vez a todo el rango, y le
pongo valores
[Link](1,4).setValue(new Date().getTime()-inicio);
Explicaciones:
• En el menú, he cambiado el nombre de las dos primeras entradas, y he agregado la función asociada a la
segunda entrada del menú
• Existe un bloque de código comentado , encerrado entre /+ y */ , por tanto no se ejecuta ( Si se descomenta ,
podremos ver su efecto)
• Se declara una variable del tipo Date() y se recoge el tiempo en inicio . Al final del for , se vuelve a recoger el
tiempo en ese instante, se resta con el valor de inicio , y se coloca la diferencia en la celda (C,1).
• Las variables definidas dentro de un bloque solo existen mientras la ejecución está en ese bloque, es decir ,
inicio o hc de la primera función y de la segunda tienen valores diferentes.
• En la segunda función se accede de una vez al rango, solo hay una petición al [Link] tiempo de ejecución se
recoge en la celda (D, 1).
9 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
Vemos que el tiempo de ejecución en el segundo caso , en esta ocasión ya que dependerá del tráfico en la linea , ha
sido casi 5 veces [Link] que tener en consideración estos hechos, sobre todo porque tenemos una limitación de 5-6
minutos para ejecutar nuestro código. Podemos seguir las recomendaciones de buenas prácticas en la siguiente
dirección .
El servicio GMail
Con toda seguridad el servicio de correo sea , si no el más utilizado , el primero que se empieza a utilizar. Google,
para el manejo del correo, presenta una interface bastante clara y con posibilidades como las diferentes
bandejas,posibilidad de crear filtros, con un editor que permite crear textos con formato , etc. Aunque Google Apps
Script no ofrece una gran variedad de nuevas posibilidades, con la API GmailApp podremos sacar más provecho en la
gestión de correos. Mediante la clase GmailApp podremos acceder acceder a nuestra cuenta de Gmail y hacer
mediante código las operaciones que desde la inteface se podían realizar: acceder a los correos,crear etiquetas y enviar
[Link] existen otras clases como GmailAttachment , con la que podemos obtener información de los archivos
adjuntados a los correos, GmailLabel para manejar las etiquetas, por ejemplo podemos generar una relación de los
correos no leídos etiquetados con una cierta etiqueta; GmailMessage que nos permite recabar información del propio
mensaje , por ejemplo si es un borrador, si ha sido leído, etc, y la API GmailThread , que permite gestionar los "hilos"
de los correos.
API GmailApp.
Esta clase, mediante sus métodos, nos permite acceder a los hilos de correo, a los mensajes de estos hilos y a las
etiquetas. Tenemos información sobre esta clase en la siguiente dirección . Es importante saber qué objeto "devuelve"
cada uno de los métodos de esta API; por ejemplo el método createLabel("nombreEtiqueta") nos devuelve un objeto
de la clase GmailLabel y por tanto se le podrán aplicar los métodos de dicha clase, o el
método getInboxUnreadCount() nos devuelve un tipo nativo INTEGER , que podré sumar con otro entero,o el método
getAliases() , nos devuelve un array donde sus elementos son los alias de la cuenta.
Veamos algunos métodos:
• getDraftMessages()
En el scr
getDraft
nos devu
del
recogem
variable
este arra
serie de
utilizamo
Asistenc
10 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
, nos los
editor]; q
utilizar :
• sendMail()
Con este método podemos enviar correos. En el método podemos explicitar 3 o 4 parámetros; los obligatorios son :
receptor, asunto y body , y en el cuarto permite opciones [Link] sintaxis básica será : [Link](eMail,
asunto,body), en donde eMail, asunto y body serán cadenas de texto, o variables cuyos valores sean texto. El texto del
correo no puede exceder de 20kB( no se tienen en cuenta el tamaño de los adjuntos)
11 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
cadenas de texto,
variables cuyos va
sean [Link] cad
texto se asignan e
comillas, por ejemp
ejemplo= 'esto es
cadena de texto',
La opción del cuar
parámetro nos per
ejemplo, añadir un
añadir una imagen
los campos cc y bc
indicar la opción no
enviar un texto con
etiquetas HTML lo
enriquece el forma
texto, y algunas m
Vamos a ver como enviamos un correo con un fichero adjunto del tipo .pdf, utilizando la opción attachments .
12 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
Como se ha comentado en la función sendMail() ,mediante la cuarta opción podemos expresar una lista de parámetros,
uno de ellos es la posibilidad de adjuntar un documento a un correo; otra es la de enviar como body un texto con marcas
HTLM. Para esto utilizaremos la opción htmlBody de la anterior función y la API HtmlService . Esta clase se utiliza
para que un script pueda producir código HTML para ser enviado al navegador ( por motivos de seguridad no se puede
enviar código desde un script al navegador). La clase a través de sus métodos, filtra el código html producido y evita
código malicioso . Además necesitaremos una plantilla, que será un fichero .html, que se utilizará como base del body
del correo.
El fichero plantilla , lo creamos desde el Editor : Archivo > Nuevo > Archivo HTML .
Para crear la plantilla utilizaremos la siguiente linea de código : var plantilla =
[Link]('nombre del fichero html creado'); Se indica en la siguiente función
enviaCorreo3():
Podemos incluir también estilos CSS , situándolo entre las etiquetas <style> y </style>.
Tambien podemos crear un "fichero de estilo" externo .El fichero .css se crea de lamisma manera que el .html. Si el
fichero .css creado tiene por nombre [Link] podemos invocarlo desde el fichero .html con la siguiente linea:
<?!=[Link]('estilo').getContent();?>
Dicha linea es sustituida por el contenido del fichero especificado al ejecutarse el código
function enviaCorreo3(){
var nombre=" Tu nombre y apellidos";
var template = [Link]('ejemplo'); // ejemplo es el nombre del
fichero html creado
// [Link]=nombre;// en el caso que haya
//[Link]([Link]().getContent()); // para probar código
[Link]('ticIKT@[Link]', "Prueba con plantilla","",
{htmlBody:[Link]().getContent()})
}
Mediante ese código podemos dar un formato más versátil al correo, por ejemplo las etiquetas <div> o <table> nos
proporcionan un buen método para maquetar el texto si se les aplica un estilo adecuado.
13 de 14 19/07/2022, 8:47 a. m.
Firefox [Link]
14 de 14 19/07/2022, 8:47 a. m.