Bueno, continuando con nuestro ejemplo del menú, hoy vamos a aprender cómo agregar registros nuevos en una hoja de cálculos.
Método appendRow()
Para esto debemos usar el método appendRow(), al cual tenemos que pasarle un array, que va a representar la fila y en cada posición de ese array la columna.
Algo así:
let ws = SS.getSheetByName("Hoja");
ws.appendRow([
'columna1',
'columna2',
'columna3'
]);
El ejemplo consistirá en guardar filas con la siguiente información:
- Un id del ítem del menú. Aunque esto no es una base de datos tradicional, me gusta trabajar con este tipo información que permite identificar un registro.
- El nombre del ítem.
- Descripción de lo que contiene el ítem.
- La categoría.
- La fecha de creación.
- La fecha de modificación.

Vamos a ir a nuestro archivo GAS y vamos a crear una función para generar el id. Aunque como dije, esto es necesario, es a gusto del desarrollador.
function getIdDinamico(){
return new Date().getTime() + '-' + (Math.floor(Math.random() * 100) + 1);
}
Y finalmente la función que va a agregar el registro:
function addItemMenu(p_item){
let ws = SS.getSheetByName("Menu");
let date = new Date();
ws.appendRow([
getIdDinamico(),
p_item.nombre,
p_item.descripcion,
p_item.categoria,
date,
date
]);
}
Como vemos en el código anterior, a las funciones de GAS, como a cualquiera, podemos agregarle parámetros, por ejemplo un JSON. Al completar la información del ítem del menú el usuario debe ingresar un nombre, una descripción y la categoría.
El resto de los parámetros son: un id que obtenemos de la función getIdDinamico(), que es el primero, y la fecha de alta y modificación, que son los dos últimos.
Listo con esto es suficiente para agregar nuevas filas desde al backend. Sólo nos falta el código en el frontend.
Para eso vamos al HTML y creamos un JSON con los datos de nombre, descripción y categoría. Esta información se va a completar con la información que un usuario escriba en el ítem nuevo:
item_menu_temp: {
nombre: '',
descripcion: '',
categoria: ''
}
También un método para enviar esta información al backend:
addItemMenu: function(){
let that = this;
google.script.run.withSuccessHandler(function(){
alert("El registro se ha guardado en el menú.");
that.item_menu_temp.nombre = "";
that.item_menu_temp.descripcion = "";
that.item_menu_temp.categoria = "";
}).addItemMenu(that.item_menu_temp);
}
Como podemos ver, el proceso es igual que en la publicación anterior. Lamamos al método withSuccessHandler(), y le pasamos como parámetro la función que se va a disparar cuando vuelva la respuesta del servidor. Y también el método addItemMenu(), igual que como se llama en el código GAS. Sin embargo este último tiene un parámetro, porque la función espera recibir un JSON con los datos que ingresa el usuario.
También vamos a agregar en el frontend un método para validar que los datos ingresados sean correctos.
validarItemMenu: function(p_item){
return (
p_item.nombre.split(" ").join("") != "" &&
p_item.descripcion.split(" ").join("") != "" &&
p_item.categoria.split(" ").join("") != ""
);
}
Este último nos va a servir tanto para agregar como para modificar (que lo vamos a ver en otra publicación)
Finalmente podemos reemplazar la columna de nuestra tabla, la que agregaba los nuevos ítem, con este código:
<tr>
<td>
<input type="text" class="form-control" placeholder="Ingrese el nombre" v-model="item_menu_temp.nombre" />
</td>
<td>
<input type="text" class="form-control" placeholder="Ingrese una descripción" v-model="item_menu_temp.descripcion" />
</td>
<td>
<select class="form-control" v-model="item_menu_temp.categoria">
<option value=""> Ingrese la categoría </option>
<option v-for="c in categorias" v-bind:value="c[0]"> {{ c[0] }} </option>
</select>
</td>
<td>
<button type="button" class="btn btn-primary" v-on:click="addItemMenu()" v-bind:disabled="!validarItemMenu(item_menu_temp)"> Agregar </button>
</td>
</tr>

El código GAS quedará de la siguiente forma:
const SS = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/[ID-DE-TU-HOJA-DE-CALCULOS]/edit#gid=0");
function doGet() {
let layout = HtmlService.createTemplateFromFile("layout");
return layout.evaluate();
}
function getCategorias(){
let ws = SS.getSheetByName("Categorias");
let data = ws.getRange(
1,
1,
ws.getLastRow(),
1
).getValues();
return data;
}
function addItemMenu(p_item){
let ws = SS.getSheetByName("Menu");
let date = new Date();
ws.appendRow([
getIdDinamico(),
p_item.nombre,
p_item.descripcion,
p_item.categoria,
date,
date
]);
}
function getIdDinamico(){
return new Date().getTime() + '-' + (Math.floor(Math.random() * 100) + 1);
}
Y el código HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<title> Prueba de Google App Script </title>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<!-- Vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="app" class="container">
<h1> Menú </h1>
<table class="table">
<thead>
<tr>
<th> Nombre </th>
<th> Descripción </th>
<th> Categoría </th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="text" class="form-control" placeholder="Ingrese el nombre" v-model="item_menu_temp.nombre" />
</td>
<td>
<input type="text" class="form-control" placeholder="Ingrese una descripción" v-model="item_menu_temp.descripcion" />
</td>
<td>
<select class="form-control" v-model="item_menu_temp.categoria">
<option value=""> Ingrese la categoría </option>
<option v-for="c in categorias" v-bind:value="c[0]"> {{ c[0] }} </option>
</select>
</td>
<td>
<button type="button" class="btn btn-primary" v-on:click="addItemMenu()" v-bind:disabled="!validarItemMenu(item_menu_temp)"> Agregar </button>
</td>
</tr>
<tr>
<td colspan="3">
<input type="text" class="form-control" placeholder="Buscar" />
</td>
<td>
<button type="button" class="btn btn-secondary"> Buscar </button>
<button type="button" class="btn btn-secondary"> Traer todo </button>
</td>
</tr>
</tbody>
</table>
</div>
<script>
new Vue({
el: '#app',
data: function(){
return {
categorias: [],
item_menu_temp: {
nombre: '',
descripcion: '',
categoria: ''
}
}
},
created: function(){
this.getCategorias();
},
methods: {
getCategorias: function(){
let that = this;
google.script.run.withSuccessHandler(function(categorias){
that.categorias = categorias;
}).getCategorias();
},
addItemMenu: function(){
let that = this;
google.script.run.withSuccessHandler(function(){
alert("El registro se ha guardado en el menú.");
that.item_menu_temp.nombre = "";
that.item_menu_temp.descripcion = "";
that.item_menu_temp.categoria = "";
}).addItemMenu(that.item_menu_temp);
},
validarItemMenu: function(p_item){
return (
p_item.nombre.split(" ").join("") != "" &&
p_item.descripcion.split(" ").join("") != "" &&
p_item.categoria.split(" ").join("") != ""
);
}
}
});
</script>
</body>
</html>
Anterior: Google Apps Script, parte 4: Recuperar información de una hoja de cálculos
Siguiente: Google Apps Script, parte 6: Buscar filas en una hoja de cálculos