trigger - on change - stops after first action - google-apps-script

I am attempting to have my trigger do multiple actions in my google sheet after an automated form from slack inputs a row into my sheet. The actions that I want it to do are:
insert todays date in a certain column
Fill formula down on column k
Fill formula down on column l
Fill formula down on column m
So far I am only getting the first behavior - Here is my code:
function setUpTrigger() {
ScriptApp.newTrigger('onEdit')
.forSpreadsheet('1QOx3H-NsK52bojXv1J-bq-9jt2ZJKG8RaiiAdcDAx4w')
.onChange()
.create();
}
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Sheet1" ) { //checks that we're on Sheet1 or not
var r = s.getActiveCell();
if( r.getColumn() == 1 ) { //checks that the cell being edited is in column A
var nextCell = r.offset(0, 1);
if( nextCell.getValue() === '' ) //checks if the adjacent cell is empty or not?
nextCell.setValue(Utilities. formatDate(new Date(), "GMT-5:00", "''MM-dd-yyyy"))
var lr = s.getLastRow();
var fillDownRange1 = s.getRange(2,11,lr-1);
var fillDownRange2 = s.getRange(2,12,lr-1);
var fillDownRange3 = s.getRange(2,13,lr-1);
s.getRange(K2).copyTo(fillDownRange1);
s.getRange(L2).copyTo(fillDownRange2);
s.getRange(M2).copyTo(fillDownRange3)
} }
}
How do I get the values to fill down from my formulas when new rows are added?
`

I noticed that I get two entries in my executions log with that kind of a trigger. The first is a simple trigger and the second is an installable trigger. And I also get inconsistent results. Sometimes the function I wrote works and sometimes the code keeps on running until it times out. Personally, I'd avoid doing such a thing. It's okay to create an onChange installable trigger but don't name it onEdit(e) because that's the default for a simple onEdit trigger. At first I thought it might be an interesting way to get e.range when using an onChange trigger but I think it would cause more problems than it's worth.

Related

Creating multiple function onEdit(e) to work in one script

My script below works as an independent script - It will add a date and a time in a cell/column opposite the trigger cell/ column. I.e. Any cell in Column A stating TRUE will have in its adjacent Column B cell stating the exact date & time, at any moment the cell in Column A is deemed to be TRUE. The script keeps this as as one single change. If I were to delete TRUE or change it to any other text, the data in column B would remain the same, until I write TRUE again - This will force the cell(s) in Column B to overwrite the previous date/time with the latest date/time the moment the new "TRUE" statement was issued in Column A.
Now, I would like to add another onEdit function where it works on Sheet 2, but the column reference numbers are not 1 (as you will see below, all numbers are 1, whether positive or negative), but will be 2. I do not know how to get the two separate functions to work as when I list them separately, with an identical script structure, only the last script in the sequence works, and the first one does not.
I hope I have made this clear enough; I am not a coder by any means, and I have done my best with tutorials, forums, etc before posting this question. I can learn better by reverse-engineering someone else's work rather than being given the building blocks and told to create something, but I appreciate any education on this so I can learn for the future.
function onEdit(e) {
var aCell = e.source.getActiveCell(), col = aCell.getColumn();
if(col == 1) { //number of column(s) where you have a data
var adjacentCell = aCell.offset(-1,-1);
var newDate = Utilities.formatDate(new Date(),
"GMT+1", "dd/MM/yyyy hh:mm:ss");
adjacentCell.setValue(newDate);
}}
function onEdit(e){
var ss = SpreadsheetApp.getActiveSheet();
//change to be your sheet name so the script only triggers on that sheet
if( ss.getName() == "Sheet1" ) { //checks that we're on the correct sheet
var r = ss.getActiveCell();
if(e.value != "TRUE") return;
e.source.getActiveSheet().getRange(e.range.rowStart,e.range.columnStart+1).setValue(new
Date());
}
}
I don't think that you have specified sufficient conditions for this to work correctly but this is what you have so far:
function onEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == 'Sheet1' && e.range.columnStart == 1) {
e.range.offset(-1,-1).setValue(Utilities.formatDate(new Date(),"GMT+1", "dd/MM/yyyy hh:mm:ss"));
}
if(sh.getName() == 'Sheet1' && e.value == "TRUE") {
e.range.offset(0,1).setValue(new Date())
}
}
I imagine you will need further debugging to get this to work.

Apps Script to update Timestamp when data is inserted automatically in google sheet

This code works fine when data is edited in Column 3 or being copy-pasted but if the cursor remains at column 1 at the time of the whole row being copy/pasted, it won't update and secondly, if salesforce sends data to column 3, it doesn't work that time too, please help me here.
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
var sName = s.getName();
var r = s.getActiveCell();
var row = r.getRow();
var ar = s.getActiveRange();
var arRows = ar.getNumRows()
// Logger.log("DEBUG: the active range = "+ar.getA1Notation()+", the number of rows = "+ar.getNumRows());
if( r.getColumn() == 3 && sName == 'Sheet1') { //which column to watch on which sheet
// loop through the number of rows
for (var i = 0;i<arRows;i++){
var rowstamp = row+i;
SpreadsheetApp.getActiveSheet().getRange('F' + rowstamp.toString()).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm"); //which column to put timestamp in
}
}
}//setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm:ss");
Explanation:
Three important things to know:
As it is also stated in the official documentation, the onEdit triggers are triggered upon user edits. This function won't be triggered by formula nor another script. If salesforce or any other service except for the user, edits column C the onEdit trigger is not going to be activated. Workarounds exist, but these workarounds depend on the context of your specific problem. I would advice you to search or ask a specific question about it.
Regarding the other issue you have, you should get rid of active ranges and take advantage of the event object. This object contains information regarding the edit/edits user made.
As it is recommended by the Best Practices you should not set values in the sheet iteratively but you can to that in one go by selecting a range of cells and set the values. In your case, you want to set the same value in all of the cells in the desired range, hence setValue is used instead of setValues. But the idea is to get rid of the for loop.
Solution:
function onEdit(e) {
var s = e.source.getActiveSheet();
var sName = s.getName();
var ar = e.range;
var row = ar.getRow();
var arRows = ar.getNumRows()
if( ar.getColumn() == 3 && sName == 'Sheet1') {
s.getRange(row,6,arRows).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm");
}
}
Note:
Again, onEdit is a trigger function. You are not supposed to execute it manually and if you do so you will actually get errors (because of the use of the event object). All you have to do is to save this code snippet to the script editor and then it will be triggered automatically upon edits.

Set an installable edit trigger to fire for a selected cell or range only

What I mean is something like this except this one works for simple triggers:
function onEdit(e)
{
var range = e.range;
var columnOfCellEdited = range.getColumn();
var rowOfCellEdited = range.getRow();
if ( columnOfCellEdited === 2 && rowOfCellEdited === 1 )
{
doSomething();
}
};
What I could think of is
saving the recent value of the given cell into another cell by every occasion the sheet
is edited and check if the value has changed since the last call.
However this solution is pretty far from classy.
Also do you know any more appropriate ways to restrict the range of the function which is called by an installable trigger?

Google script works only for data manually entered and not for data brought in through importrange in spreadsheet

I have this script to hide those rows which contains the word - 'Matured' (in column F)
function onEdit(e) {
var sheet = e.source.getActiveSheet();
var r = e.source.getActiveRange();
if (sheet.getName() == "Follow-ups LAPL" && r.getColumnIndex() == 6 && r.getValue() == "Matured")
sheet.hideRows(r.getRowIndex(),1);
The problem is - the script does the job of hiding the row only when the 'Matured' is entered MANUALLY (in column F), but it does not work if the same is brought in through importrange (in same column F).
Is it by design, or is there any workaround?
Thanks for help!
It is by design. You may trigger the onchange event rather than the onEdit event for your use case or you may trigger both. See if onChange works in both cases, if so you may trigger only that. If it doesn't then you may trigger both events at the same time.
You may trigger multiple events on the same function by going to the Current Project's trigger as shown below:
You can create your own function and trigger every minute. But make sure in master spreadsheet (Spreadsheet id which you included in importrange) you delete empty cells or else in below loop sheet.getLastRow() will count empty cells too which will result in unnecessary iteration.
function onModified() {
var ss = SpreadsheetApp.openById('SPREADSHEET ID');
var sheet = ss.getSheetByName("Follow-ups LAPL");
var getData = sheet.getRange(1, 6, sheet.getLastRow(), 1).getValues();
Logger.log(getData.length);
for (var i = 0; i < getData.length; i++) {
if (getData[i][0] == "Matured") {
sheet.hideRows(i+1,1);
} else {
sheet.showRows(i+1, 1);
}
}
}

Formula-based cell changes in Google Sheets is not firing onEdit script

I'm completely new to Google script writing, but I've used various posts here to piece together what I need: something that will add a time stamp to a row when a certain column changes. Here's what I'm currently using:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "test" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() == 16 ) { //checks the column
var nextCell = r.offset(0, 1);
if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(new Date());
}
}
}
This works perfectly when I manually change the data; however, the column that the script is monitoring pulls data from another sheet and this fails to fire the trigger/script. How can I get around this so that cells with formulas (that reference other sheets) will still fire my script?
Any help is greatly appreciated. Thanks!
The onEdit trigger works only when an actual user edits the spreadsheet. Depends of your use case, but you can be use a Time-driven trigger and set it in a recurring interval and with a function monitor the column for changes, here's an example:
function monitorColumn() {
// Add the trigger from the Resources menu in the Script Editor
// Script Editor > Resources > Current oroject's triggers > Add trigger
// [monitorColumn] - [Time-driven] - [Hour timer] - [Every hour]
var s = SpreadsheetApp.getActiveSpreadsheet();
var ss = s.getSheetByName("test"); // Get the sheet by name
// Get the values of the columns P & Q with getRange(row, column, numRows, numColumns)
var columnValues = ss.getRange(1, 16, ss.getLastRow(), 2).getValues();
// Loop through the values
for (var i = 0; i < columnValues.length; i++) {
// If cell in column P is empty and cell in column Q is not empty set todays date
if(columnValues[i][0] != "" && columnValues[i][1] == ""){
// While a range index starts at 1, 1, the JavaScript array will be indexed from [0][0].
ss.getRange(i+1,17).setValue(new Date());
}
}
}