Google App script trigger does not work on simple custom function - google-apps-script

I am very new to google app script while having some experience both in javascript and python.
I am trying to run a very simple script in this custom spreadsheet, see row 1.
I am using the custom function feature, no apps/services deployed and I have full read/write authorizations.
I am developing some time conversion and duration calculation functions for a personal project, while trying to experiment with triggers starting with very simple functions.
The code associated with the trigger is indeed very simple: check the value of a predefined cell ("A1" in this case) and return its value in the cell where the function is invoked. As simple as possible, just to experiment with app script triggers:
function zain(){
var sheet = SpreadsheetApp.getActiveSheet();
var a = sheet.getRange("A1").getValue();
return a;}
To the effect of updating the cell value whenever any cell in the sheet is changed, I installed an onEdit() trigger on the function "zain()".
Now, the problem is: it does not work. The trigger log shows that onEdit() is successfully being completed, but the value in the cell where the function is invoked does not change, at all. It only seems to work whenever I re-paste the function or change the code and save it. Otherwise nothing.
I looked through all possible issues related to triggers in this forum and, contrarily to other cases, I could not find any working solution. I checked issues with trigger objects, spreadsheet access, but none of these solutions seems to be working/apply to my case.
If someone could be so kind to help in this matter, it would be greatly appreciated.

Here is a onEdit(e) function that takes Celsius from A1 and calculates Fahrenheit in B1
function onEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == 'Sheet0' && e.range.columnStart == 1 && e.range.rowStart == 1 && e.value ) {
e.range.offset(0,1).setValue(e.value * (9 / 5) + 32);
}
}
function zain(a) {
return (a - 32) * 5 / 9;
}
in C1 put "=zain(B1)" then when B1 changes the value of A1 should end up in C1 but not because of the onEdit trigger it's because B1 has changed
Demo:

Related

Have an onEdit() function run whenever a cell value is changed in Google Sheets

I have a Sheet that has the following:
ID ROW STATUS ......
3588053 4 NEW
The Data for ID and ROW are coming from an External Spread Sheet called KDCAlerts
The STATUS filled is changed with an onEdit command (or in this case onMyEdit) that executes when there are changes on KDCLog
The ID and ROW changes each time the External spreadsheet changes (ex: adding / deleting rows, etc.)
What I need to do is to fix this so that when ID or ROW changes, the onMyEdit function is ran.
How can I do this? Below is the code currently being used now.
Any help, hints or advice would be greatly appreciated.
TIA
function creatTrigger() {
if(ScriptApp.getProjectTriggers().filter(t => t.getHandlerFunction() == "onMyEdit").length == 0) {
ScriptApp.newTrigger("onMyEdit").forSpreadsheet(SpreadsheetApp.getActive()).onEdit().create();
}
}
function onMyEdit(e) {
var sh = e.range.getSheet();
if (sh.getName() == "KDCLog" ) {
var extSS = SpreadsheetApp.openById("1b5qiNxxxxxxxxxRuLf-8dTBgRU9cHLBbd2A");
var extSH = extSS.getSheetByName("KDCAlerts");
} else { return; }
....
....
UPDATE:
#doubleunary - thanks for the response.
It is unclear how the values in the ID and ROW columns get written to the spreadsheet,
There are 2 Files: KDCLog and KDCAlerts.
KDCLog!ID is populated as follows:
=IF ( ISERROR( INDEX(SORTN(FILTER({KDCAlerts!E:E,KDCAlerts!H:H, KDCAlerts!A:A}, KDCAlerts!D:D=E7),1,,2,FALSE),,3) ), -1, INDEX(SORTN(FILTER({KDCAlerts!E:E,KDCAlerts!H:H, KDCAlerts!A:A}, KDCAlerts!D:D=E7),1,,2,FALSE),,3) )
So, it is "pulling" from KDCAlerts using a function (being executed in the KDCLog worksheet).
Whenever the KDCAlerts change, the Value in KDCLog!ID also changes (without manual intervention - the KDCAlerts changes with the adding of rows).
If you are using another script to write to the spreadsheet, it is
likely that no events get sent.
For the STATUS column, it is populated with an onEdit funciton (seen above)
trigger events that can be monitored with an installable on change
trigger.
Is there a sample on how this could work
You cannot use on edit trigger here, because it fires only when the spreadsheet is manually edited by a user, regardless of whether you are using a simple trigger or an installable trigger.
It is unclear how the values in the ID and ROW columns get written to the spreadsheet, which is what actually determines whether you can catch those updates. If you are using another script to write to the spreadsheet, it is likely that no events get sent.
If you are using another integration tool, it may trigger events that can be monitored with an installable on change trigger.

Modifying e.range.getA1Notation() to accept wider range of inputs in Google Apps Script

I'm using a Google Apps script to update the active sheet's name with a cell (C6) value when another cell (I16) is updated. Currently, the script works fine when I16 is updated and the sheet is renamed as intended.
However, I would like the range of inputs to be much wider, like an A:J kind of range, or at least A1:J104. How can I achieve this?
I have also read this thread but I'm unsure of how to extract that info specific to this scenario.
The script I'm using is as follows:
function onEdit(e) {
if(e.range.getA1Notation() !== 'I16') return;
var s = e.source.getActiveSheet();
s = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().setName(s.getRange('C6').getValue());
}
Any assistance will be much appreciated. Thank you in advance!
EDIT: With the script, the following happens:
Upon editing cell I16, the contents of cell C6 changes via a formula. For example, when I enter "002" into cell I16, cell C6 updates to "Report-002", and so on.
At the same time, the script extracts the string in cell C6 and updates the name of the current sheet accordingly (i.e. the sheet is now named "Report-002".
The script works well for this specific scenario. However, I would like to trigger the script when I update a wider range of cells, and not just cell I16. Ideally, I'd like the script to run if I updated any cell in the sheet.
Does that help to clarify what I'm trying to achieve?
Try
function onEdit(e) {
e.source.getActiveSheet().setName(e.source.getActiveSheet().getRange('C6').getValue());
}
Change the if condition to account for bounds:
const [/*actual row*/ar, ac] = ['rangeStart','columnStart'].map(s => e.range[s])
const [/*row start*/rs, re, cs, ce] = [1,2,3,4];//C1:D2
if(ar >= rs && ar <= re && ac >= cs && ac <= ce){
// do stuff
}

Date stamp script not working with arrayformula

I'm trying to use a simple date stamp script in Google Sheets that will input today's date upon edit of another column but then will not change thereafter. I also have an array formula set on the column the script is looking at for the edits and it appears the array formula is preventing the script from working properly. Here is the formula:
={"Triggered";arrayformula(IFS(E2:E="","",C2:C>=E2:E,"✅",TRUE,""))}
And this is the script:
function onEdit(e) {
var sh = e.source.getActiveSheet();
if(sh.getName() !== "Watchlist" || e.range.columnStart !== 8) return;// 1 is A, 2 is B, 3 is C, etc
var o = e.range.offset(0, 1)
if(!o.getValue()) o.setValue(new Date())
}
Any help with what I'm doing wrong is appreciated. Thanks.
Unfortunately, according to the official documentation :
An installable edit trigger runs when a user modifies a value in a
spreadsheet.
Even when the output of the arrayformula is updated, the cell still contains the same formula. Therefore, the onEdit trigger won't fire since there wasn't any edit action by the user.
Read also the discussion here.

Convert onEdit script to manually running script

The script has the purpose of writing the datetimestamp to a specific cell the moment when a cell in column 4 has the text Assign.
I have a script that theoretical works but I'm getting my data from Appsheet. The problem with this is that Appsheet writes data into my sheet but the script wont see it as edited cells, so it wont write the time stamp.
But my knowledge about Apps Scripts is pretty bad. And I am getting errors with the source line and the col, val lines.
function onEdit(e) {
var sh = e.source.getActiveSheet();
var row = e.range.getRow();
var col = e.range.getColumn();
var val = sh.getRange(row, 4).getValue();
//check if sheet is 'Blad1' & value is 'Assign'
if (sh.getSheetName() === 'Blad1' && val == 'Assign') {
var tz = e.source.getSpreadsheetTimeZone();
var date = Utilities.formatDate(new Date(), tz, 'dd-MM-yyyy hhmmss');
//set date in column 14 for same row
sh.getRange(row, 14).setValue(date);
}
}
I want to convert my script to a manually run script with a time-based trigger of 1 min. That way I hope the script will see the changed cell to Assign.
The problem is rooted in apps script triggers restrictions, specifically in their inability to listen to script-based events. I would suggest deploying your script as a WebApp with doGet() / doPost() functions to listen to API requests and, if I am correct in assuming that AppSheet works similarly to Zapier, etc., add a step that calls your WebApp after making changes to your Spreadsheet.
Please, see this guide on WebApps, its pretty straightforward to follow.
P.s. Btw, refrain from creating triggers acting as event listeners, you will easily cap your quotas!

Google Apps Script - Spreadsheet run script onEdit?

I have a script that I use in my spreadsheet. It is at cell B2 and it takes an argument like so =myfunction(A2:A12). Internally the function gets info from a large range of cells.
Nothing seems to work. I tried adding it to
Scripts > Resources > Current Project Triggers > On edit
Scripts > Resources > Current Project Triggers > On open
How can I have this function update the result with every document edit?
When you are making calls to Google Apps services inside your custom function (like getRange and getValues etc), unfortunately there is no way of updating such custom functions with each edit, other than passing all of the cells that you are "watching" for editing.
And, perhaps even more frustratingly, the workaround of passing say a single cell that references all of your "watched" cells with a formula doesn't trigger an update - it seems that one needs to reference the "watched" cells directly.
You could pass GoogleClock() as an argument which will at least update the function output every minute.
But the advice from many members on this forum (who have much more knowledge about this stuff than me) would simply be: "don't use custom functions".
I am not sure if this exact code will work but you can try something like this...
function onEdit(event){
var activeSheet = event.source.getActiveSheet();
if(activeSheet.getName() == "ActiveSheetName") {
var targetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TargetSheetName");
targetSheet.getRange(2,2).setValue("=myfunction(A2:A12)");
}
}
Assuming that B2 cell in on the sheet "TargetSheetName" and assuming that the edited cell is on the sheet "ActiveSheetName", the function onEdit will trigger when you edited any cell in any sheet. Since there is an if statement to check if that edited cell is on the sheet "ActiveSheetName" it will trigger only if the edited cell is on that sheet and it will set the B" cell to the value =myfunction(A2:A12), forcing it to update (i guess).
hope that i am correct and that i was helpful
I had a similar issue, for me I wanted to "watch" one particular cell to trigger my function.
I did the following (pretending A1 is the cell i am watching)
IF(LEN(A1) < 1, " ", customFunction() )
This successfully triggered if I ever edited that cell. However:
"Custom functions return values, but they cannot set values outside
the cells they are in. In most circumstances, a custom function in
cell A1 cannot modify cell A5. However, if a custom function returns a
double array, the results overflow the cell containing the function
and fill the cells below and to the right of the cell containing the
custom function. You can test this with a custom function containing
return [[1,2],[3,4]];."
from: https://developers.google.com/apps-script/execution_custom_functions
which makes it almost useless, but it might work for your case?
If the custom function is assigned to a project trigger it has more power so personally I ended adding it to "Scripts > Resources > Current Project Triggers > On edit"
and basically "watched a column" so it only did things if the current cell was within the "edit range". This is a bit of a bodge and requires some hidden cells, but it works for me at the moment
var rowIndex = thisspreadsheet.getActiveCell().getRowIndex();
var colIndex = thisspreadsheet.getActiveCell().getColumn();
//clamp to custom range
if(rowIndex < 3 && colIndex != 5)
{
return 0;
}
//check against copy
var name = SpreadsheetApp.getActiveSheet().getRange(rowIndex, 5).getValue();
var copy = SpreadsheetApp.getActiveSheet().getRange(rowIndex, 6).getValue();
if(name != copy )
{
///value has been changed, do stuff
SpreadsheetApp.getActiveSheet().getRange(rowIndex, 6).setValue(name);
}