How to determine if the cell that has changed from a google sheet is in a list and how to put a trigger?

2

I am new to google scripts and event handling and I do not clarify with the API.

I'm looking to create a script that monitors certain cells in a specific sheet of a google sheet book. These cells contain a formula that depends on the content of a range of other cells that the user modifies manually. Thus, when the user edits the latter, the former change.

The idea is that if the value of any of the cells (C61: C66) changes above a pre-set threshold (0.25) ( the user does NOT modify them directly ) an e-mail is sent. Pej: cell C61 contains the formula:

=CONTAR.SI(D61:61, "No")/E$67

What is intended is that if after changing manually any cell of D61: 61 the value of C61 is greater than 0.25, the system sends a pair of e- mails The same would happen with cells C62: C66

For now what I have is:

function sheetTracker() {

// Version 2.0

var ss = SpreadsheetApp.getActiveSpreadsheet(); // Obtenemos a quehoja del libro pertenece la celda que ha cambiado
var cell = SpreadsheetApp.getActiveRange(); // Obtenemos la celda que ha cambiado
var celda = cell.getA1Notation(); // Obtenemos el nombre de la celda que ha cambiado

var currentSheet = ss.getActiveSheet();
var hoja = currentSheet.getName(); // Obtenemos el nombre de la hoja en la que ha cambiado la celda

var editRange = {top : 61,bottom : 66, column : 3}; // Celdas a verificar: C61:C66

// Si no se ha modificado una celda de la hoja de asistencia que toca salimos

if (hoja != "Mi hoja") return;  

// Si las celdas modificadas estan fuera de rango salimos
var thisRow = e.range.getRow();
if (Number(thisRow) < editRange.top || Number(thisRow) > editRange.bottom) return;

var thisCol = e.range.getColumn();
if (Number(thisCol) != editRange.column) return;

var range = e.range; // La celda que se ha cambiado
var columna = range.getColumn(); // La columna en la que esta la celda que ha cambiado
var fila = range.getRow(); // La fila en la que esta la celda que ha cambiado
var valor = Number(range.getValue()); // El nuevo valor de la celda
var valor = Number(ss.getActiveCell().getValue());

var alumno = range.offset(0,2);
var email = range.offset(0,-2);
var yes = range.offset(0,1);
var justified = range.offset(0,-1); 

if ( celda == 'C61' && valor > 0.25) {
   MailApp.sendEmail(email, subjecta, messagea); 
   MailApp.sendEmail(director, subjectd, messaged);
}

My questions are:

1) - Is it possible to define a list of cells to check such that ['C61', 'C62', 'C63', 'C64', 'C65', 'C66']

and do something like in python "cell in ['C61', 'C62', 'C63', 'C64', 'C65', 'C66']

2) -The "e.range" comes from trying to use an onEdit (e) function where "e" is an event. However, I am trying not to use an event. The use of triggers is not clear to me. It seems that there are "reserved" functions that are "auto-triggered" like "onEdit (e)" and "onChange (e)" when editing or changing a cell and others that do not, needing "external" triggers. What options do I have? ?

    
asked by isg 20.08.2018 в 12:01
source

2 answers

2

Short answer

From the rev 3 of the question

  

What is intended is that if after manually changing any cell of D61: 61 the value of C61 is greater than 0.25, the system sends a couple of e-mails. The same would happen with cells C62: C66

function onEdit(e){
  var fila = e.range.getRow();
  var columna = e.range.getColumn();
  if(columna < 3 && fila !== 61) return; // Salir cuando rango editado no sea D61:61 
  // Hacer lo que se tenga que hacer cuando el rango editado sea válido.
}   

Previous code

function onEdit(e){
  var celda = e.range.getA1Notation();
  var fila = celda.getRow();
  // Asumiendo que las celdas modificadas por el usuario a monitorear son
  var lista = ['C61','C62','C63','C64','C65','C66'];
  if(lista.indexOf(celda)){
    //Poner aquí lo que hay que hacer si la celda está en lista
  } else {
    // Poner aquí lo que hay que hacer si la celda no está enl a lista
  }
}

Broad response

With regard to what is indicated in the quote included above, you can use an activator when editing or changing to verify what happens in another part of the sheet, such as a calculation made by formulas

NOTE: One must keep in mind the asynchrony between the event and the recalculation. When they are simple calculations it is very likely that they are faster than Apps Script. You can use SpreadsheetApp.sleep (milliseconds) to wait a certain time or you could save the previous values in properties and use something like "exponential backoff" to have a certain degree of tolerance to what delays the recalculation.

About the code, the variable e is not defined. It's not clear how you pass that variable from an onEdit (e) function, but it's probably not really relevant to the questions you ask.

  

1) - Is it possible to define a list of cells to check such that   ['C61', 'C62', 'C63', 'C64', 'C65', 'C66']

     

and do something like in python "cell in   ['C61', 'C62', 'C63', 'C64', 'C65', 'C66']

On the one hand Google Apps Script is based on JavaScript, so you can define the list of cells to check as an array of references practically as you have written

var lista = ['C61','C62','C63','C64','C65','C66'];

Then you can use getRangeList (a1Notations) to get an object RangeList or you can use Array methods like indexOf, each, some, every, map or use loops as for and while along with some of the getRange(a1Notation) , either from Class Sheet or from Class Spreadsheet to do things with items in the list.

  

2) -The "e.range" comes from trying to use an onEdit (e) function where "e"   It is an event. However, I am trying not to use an event. I do not   The use of triggers is clear. It seems that there are functions   "reserved" that are "self-triggered" as "onEdit (e)" and "onChange (e)"   when you edit or change a cell and others that do not, in need of   "external" triggers, what options do I have?

Reserved role names are indicated in link . These are used for simple triggers . onChange is not one of them. The installable activators are configured from the Edit menu from where you can select any function of the global scope of the project being edited.

Installable indicators are indicated in link .

In spreadsheets to execute a function when editing a function you can use a simple trigger onEdit , or an installable trigger when editing or when changing a spreadsheet.

Notes:

  • Avoid using the onEdit name for an installable trigger because it could be executed doubly, when triggered as a simple trigger and as an installable trigger.
  • Your installable trigger when changing can call a function named onChange or with any other name, but avoid calling a function called onEdit as indicated in the previous note.
  • The activators when editing or changing are only triggered by cell editions or the spreadsheet made by the user as the case may be. Changes in values due to recalculation do not trigger these triggers. If this is what you are looking for, you should use a time-driven trigger or a function from a sidebar, dialog or something external that is monitoring the changes and acting accordingly.
  • answered by 20.08.2018 в 14:51
    0

    I think I already have a more refined version of what I want to do:

    function sheetTracker() { 
    
    // Version 2.0
    
    var libro = SpreadsheetApp.getActiveSpreadsheet(); // Obtenemos a que libro pertenece la celda que ha cambiado
    var hoja = libro.getActiveSheet().getName(); // Obtenemos el nombre de la hoja en la que ha cambiado la celda
    var lista = ['C61','C62','C63','C64','C65','C66']; // Celdas a monitorizar
    var celda = libro.getActiveCell().getA1Notation(); // Obtenemos el nombre de la celda que ha cambiado
    var valor = Number(libro.getActiveCell().getValue()); // El nuevo valor de la celda
    
    // Si no se ha modificado una celda de la hoja de asistencia que toca salimos
    
    if (hoja != "Mi hoja") return; 
    
    if (lista.indexOf(celda) && valor > 0.25) { 
           var fila     = libro.getActiveCell().getRow();
           var columna  = libro.getActiveCell().getColumn();
           var persona  = libro.getRange(fila,columna+2).getValue().toString();
           var email    = libro.getRange(fila,columna-2).getValue().toString();
           var yes      = libro.getRange(fila,columna+1).getValue();
           var justfied = libro.getRange(fila,columna-1).getValue();
    
           MailApp.sendEmail(email, subjecta, messagea); 
           MailApp.sendEmail(director, subjectd, messaged);
    
    
    } else {
          return;
    }
    }
    

    In the end, I opted for an installable trigger (discarding the use of the "onEdit (e)" function and its event e). To install the activator I would install an activator: on edit (go to resources> current sheet> activators> add new trigger) and authorize the script.

    But the following question arises: is it correct to move to another cell to define the variables: person, email and justified, or should I use the offset () function?

        
    answered by 22.08.2018 в 11:48