function onEdit not working with =query(importrange( - google-apps-script

I use the following code for an appscript
function onEdit(e) {
var range = e.range;
var reportSheet = range.getSheet();
if (reportSheet.getSheetName() != "CHRankingsRohdaten" || range.rowStart != 1 || range.columnStart != 1) return;
var ss = e.source;
var recordsSheet = ss.getSheetByName("CHDatabase")
var saveData = reportSheet.getRange("A1:F").getValues();
var lastRow = recordsSheet.getLastRow();
recordsSheet.getRange(lastRow + 1, 1, saveData.length, 6).setValues(saveData);
}
The values that triggers the onEdit() function are loaded from another sheet by =query(importrange( function and this does not seem to work, because the trigger is not fired. Only if I enter data by hand, then the trigger is fired. How can I run the onEdit() function with the imported data from the =query(importrange( function?

That is the way that edit, simple and installable, triggers works, but the installable change trigger is triggered when a importrange changes its results with the event property changeType value equal to 'OTHER' (I only tested this using "closed "references like A1:A10 not with "open" references like A:A.
In order to be able to use the change trigger you should change a bit your script
Change the function name
Instead of
var range = e.range;
var reportSheet = range.getSheet();
try
var reportSheet = SpreadsheetApp.getActiveSheet();
This might work under certain circumstances. If it doesn't you might have to use a "witness" cell or range to detect if the formula result was updated.
You should change this line if (reportSheet.getSheetName() != "CHRankingsRohdaten" || range.rowStart != 1 || range.columnStart != 1) return; (there aren't enough details to suggest something without guessing several things)
1 as a good practice (use reserved functions name only for the corresponding trigger).
2 and 3 are because change event object doesn't include range property.
Related
Why do both onChange and onEdit triggers fire at the same time?
Google Sheet: How to get the actual change when onChange event fires?

Related

How to make onEdit() only restricted to edition in specific range?

I tried to make onEdit function only respond to the specific range.
my onEdit function as bellow:
function onEdit(e){
var range = e.range;
var sheetName = e.source.getActiveSheet().getSheetName();
if (//trigger only when the cells from column A:H is edited
sheetName == "Email list" &&
range.rowStart >= 2 &&
range.columnStart >= 1 &&
range.columnStart <= 8
) {
sendMail()
}
}
function sendMail() {.... //the main function here
I have also deployed installable trigger using function onEdit. But I got TypeError: Cannot read property 'range' of undefined. Not sure which part is wrong or how should I define the variable within onEdit? Thank you.
Try following sample script:-
function onEdit(e)
{
const range = e.range
const sheet = range.getSheet();
const row = range.getRow();
const column = range.getColumn();
if (//trigger only when the cells from column A:H is edited
sheet.getName() == "Email list" &&
row >= 2 &&
column <= 8 // not taking 1 into consideration
) {
sendMail()
}
}
If you run the function directly, it will throw an error TypeError: Cannot read property 'range' of undefined, remove Edit installable trigger, as onEdit() is simple trigger
I believe your goal is as follows.
You want to run your onEdit by not only OnEdit simple trigger but also the standalone without the simple trigger.
In this case, how about the following modification?
Modified script:
function onEdit() { // If you want to use this function as the installable trigger, please rename the function name.
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveRange();
var sheetName = sheet.getSheetName();
if (//trigger only when the cells from column A:H is edited
sheetName == "Email list" &&
range.rowStart >= 2 &&
range.columnStart >= 1 &&
range.columnStart <= 8
) {
sendMail()
}
}
By this modification, you can directly run onEdit. And also, you can run onEdit by OnEdit trigger.
Note:
When you want to use your onEdit using the installable trigger, please rename the function name. About this, I thought that this thread might be useful.
Adding The data into another spreadsheet

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.

onEdit specific cell copy data from one google sheets to another

In google sheets, I am trying to get one data to copy from one sheet to another.
I have this code which is working however I would like it to run onEdit when changing cell E4 in Googlesheet1. I am new at this and doesn't seem to get it to quite work with the solutions I found online.
function ExportRange() {
var destination = SpreadsheetApp.openById('googlesheet1');
var destinationSheet = destination.getActiveSheet();
var destinationCell = destinationSheet.getRange("AC3");
var cellData = '=IMPORTRANGE("https://docs.google.com/spreadsheets/googlesheet2", "AE10:AE9697")';
destinationCell.setValue(cellData);
}
Chose between a simple and installable onEdit trigger, depending on your requirements
For most applciaitons a simple onEdit trigger is sufficient, to use it you just need to rename your function ExportRange() to onEdit()
Take advantage of event objetcs that give you informaiton about the event that fired the trigger
So, the trigger onEdit can give you among others information about the event range - that is the range that has been edited
Now you can implement an if statement to specify that the rest of the funciton shall only be run if the event range and the corresponding sheet are as required
Sample:
function onEdit(event) {
var range = event.range;
var sheet = range.getSheet();
if(range.getA1Notation() == "E4" && sheet.getName() == "Googlesheet1"){
var destination = SpreadsheetApp.openById('googlesheet1');
var destinationSheet = destination.getActiveSheet();
var destinationCell = destinationSheet.getRange("AC3");
var cellData = '=IMPORTRANGE("https://docs.google.com/spreadsheets/googlesheet2", "AE10:AE9697")';
destinationCell.setValue(cellData);
}
}
Please note that this function can only be fired by the trigger in
case of an edit. If you try to run it manually, it will give you an
error because event (and thus event.range) will be undefined if
the funciton was not called by an edit event.

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);
}
}
}