onEdit Google script is not getting called [duplicate] - google-apps-script

This question already has answers here:
How can I test a trigger function in GAS?
(4 answers)
Closed 4 years ago.
I wanted to execute a function whenever a cell is edited or added in google spreadsheet.
I have the below function, but it is not working. please help. Also I wanted to call the function Start sync after X seconds. How to give a delay in calling the startSync()
function onEdit(e) {
var range = e.range;
range.setNote('Last modified: ' + new Date());
startSync()
}
whenever I edit a cell , a note (comment) is getting added to the cell , but the startSync is not getting called.
function startSync() {
//Get the currently active sheet
var sheet = SpreadsheetApp.getActiveSheet();
//Get the number of rows and columns which contain some content
var [rows, columns] = [sheet.getLastRow(), sheet.getLastColumn()];
//Get the data contained in those rows and columns as a 2 dimensional array
var data = sheet.getRange(1, 1, rows, columns).getValues();
syncMasterSheet(data);
}
Answer:
Installable Triggers helped me to call StartSync()

You can't use a simple onEdittrigger with most .set methods. You need to use an installed onEdit() trigger instead. See this answer for more information on triggers
To delay the start of the function use Utilities.sleep(milliseconds) before the call to the startSync() function. See more info about the Utilities class here

Related

Google Apps script on cell background change recalculation [duplicate]

I know this question has been asked before but the answers given are not valid for my case because it's slightly different.
I've created a formula that looks for sheets with a pattern in the name and then uses it's content to generate the output. For example
function sampleFormula(searchTerm) {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheets = spreadsheet.getSheets()
.filter(function(sheet) {
// If sheet name starts with DATA_SHEET_...
return sheet.getSheetName().indexOf('DATA_SHEET_') === 0;
});
const result = [];
sheets.forEach(function(sheet) {
// We get all the rows in the sheet
const rows = sheet.getDataRange().getValues();
rows.forEach(function(row) => {
// If the row it's what we are looking for we pick the columns A and C
if (row[1] === searchTerm) {
result.push([ row[0], row[2] ])
}
});
});
// If we found values we return them, otherwise we return emptry string
return result.length ? result : '';
}
The thing is I need this formula to be re-calculated when a cell in a sheet with a name starting with DATA_SHEET_ changes.
I see most answers (and what I usually do) is to pass the range we want to watch as a parameter for the formula even if it's not used. But in this case it will not work because we don't know how many ranges are we watching and we don't even know the whole sheet name (it's injected by a web service using Google Spreadsheet API).
I was expecting Google Script to have something like range.watch(formula) or range.onChange(this) but I can't found anything like that.
I also tried to create a simple function that changes the value of cell B2 which every formula depends on but I need to restore it immediately so it's not considered a change (If I actually change it all formulas will break):
// This does NOT work
function forceUpdate() {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet = spreadsheet.getActiveSheet();
const range = sheet.getRange(1, 1);
const content = range.getValue();
range.setValue('POTATO');
range.setValue(content);
}
So I don't know what else can I do, I have like a hundred formulas on multiple sheets doing this and they are not updating when I modify the DATA_SHEET_... sheets.
To force that a custom function be recalculated we could use a "triggering argument" that it's only taks will be to trigger the custom function recalculation. This triggering argument could be a cell reference that will be updated by a simple edit trigger or we could use an edit installable trigger to update all the formulas.
Example of using a cell reference as triggering argument
=sampleFormula("searchTerm",Triggers!A1)
Example of using an edit installable trigger to update all the formulas
Let say that formulas has the following form and the cell that holds the formula is Test!A1 and Test!F5
=sampleFormula("searchTerm",0)
where 0 just will be ignored by sampleFormula but will make it to be recalculated.
Set a edit installable trigger to fire the following function
function forceRecalculation(){
updateFormula(['Test!A1','Test!F5']);
}
The function that will make the update could be something like the following:
function updateFormula(references){
var rL = SpreadsheetApp.getActive().getRangeList(references);
rL.getRanges().forEach(function(r){
var formula = r.getFormula();
var x = formula.match(/,(\d+)\)/)[1];
var y = parseInt(x)+1;
var newFormula = formula.replace(x,y.toString());
r.setFormula(newFormula);
});
}
As you can imagine the above example will be slower that using a cell reference as the triggering argument but in some scenarios could be convenient.

Show/Hide Columns Using A Checkbox

I am a wanna-be developer who is trying to figure out how to hide a set of columns based off a checkbox being clicked.
Would anyone want to help with this code?
I have 12 different sheets(one for each month) and I would like to hide columns A-H with the checkbox in I being clicked.
Ideally I can implement on each individual sheet.
Link to spreadsheet
There are few ways one can do it.
Easiest and most recommended among all is to group those column and it will have pretty much same use which you're looking for.
If you're willing to use appscript for it. Here how it should be done:-
Open Script Editor from your spreadsheet.
Declare the onEdit simple trigger which will run every time when sheet will be edited.
So whenever you'll click on tickbox on I1 this function will trigger.
When a trigger fires, Apps Script passes the function an event object as an argument, typically called e.
For this object, we're gonna have the information we need to do our task, and also to restrict our operation to only to those months sheet and range belongs to it.
Here is the code, I tried my best to explain what happening in the code:-
function onEdit(e)
{
var rangeEdited = e.range; // This will us range which is edited
var sheetEdited = rangeEdited.getSheet().getName() // from range we can get the sheetName which is edited
var mySheets = ["Jan List","Feb List"] // Put all the month sheet name in this array where you want to have this functionality
var rowEdited = rangeEdited.getRow() // From Range we can get Row which is edited
var columnEdited = rangeEdited.getColumn() // From Range we can get Column which is edited
if(mySheets.indexOf(sheetEdited) > -1) // Now we want to only restrict the operation on those sheets,so if other sheet is edited, we shouldn't run our hide function
{
if(rowEdited === 1 && columnEdited === 9) // we're further restricting the range of operation to run this function when only I1 is edited that is Row:- 1 and Col:- 9
{
hideUnhide(sheetEdited) // calling our hide function within OnEdit and passing sheetName as an argument in it
}
}
}
function hideUnhide(sheetEdited) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ssname = ss.getSheetByName(sheetEdited) // accessing the sheet which is edited
var isItHidden = ssname.isColumnHiddenByUser(1) // checking if range is already hidden
if(isItHidden === false) // if No, hide that range
{
ssname.hideColumns(1, 6)
}
else // if Yes, unhide that range
{
var hideThisRange = ssname.getRange('A:H')
ssname.unhideColumn(hideThisRange)
}
}
Documentation:-
AppScript Events

onEdit function does nothing [duplicate]

This question already has answers here:
Google Sheets onEdit(e) TypeError: cannot read property
(2 answers)
Closed 2 years ago.
All the similar questions couldn't solve my issue.
I have a spreadsheet on google and I'm trying to write onEdit(e) function.
I've just typed a simple code to log some text and variables:
function onEdit(e){
Logger.log("Excuted");
var spreadsheet = e.source.getActiveSheet();
var activeCol = e.range.getColumn();
var activeRow = e.range.getRow();
Logger.log(activeRow + activeCol + spreadsheet);
}
Wherever I edit in the sheet nothing is logged.
I go to the editor and click run, the logger then shows this output:
Why the edit event is not triggered?
function onEdit(e){
const msg=Utilities.formatString('Row: %s, Col: %s SheetName: %s',e.range.rowStart, e.range.columnStart, e.range.getSheet().getName());
e.source.toast(msg);
}
Note: this function requires a onedit trigger event object so it cannot be run from menu or from the script editor. Just save it in the script editor and go edit some pages.

Trigger a function on selecting a cell

How to write a trigger which gets triggered everytime the user selects any cell. The trigger will call a function which would log the row number of the highlighted cell on Google Apps Scripts
I have already written a function which is doing that:
function getCell() {
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//get the current highlighted cell
var cell = sheet.getCurrentCell();
//get the row number
var row = cell.getRow();
//log the value
Logger.log(row);
}
But I don't know how to write the trigger. Currently, I have to run the script every time I click on some other cell.
strange, it worked the first time....
function onSelectionChange(e){
Browser.msgBox('cell selection change');
}
maybe things have changed since the question was posted, but landed here.
The available triggers are described on https://developers.google.com/apps-script/guides/triggers/. An alternative that could serve as a workaround is to use the "poll technique" described on How do I make a Sidebar display values from cells?

Update custom function in different cells

I have a spreadsheet with a custom function calling a web API like this:
function myFunction(value) {
var value = value
...
}
and I call this function in different cells in B column in this way:
=myFunction(A2)
=myFunction(A3)
=myFunction(A4)
...
so that the values change regarding the content of A column.
Now, I would like to update all these functions with a trigger, which could be every minute, or every hour, or at midnight. I used the built in trigger on Google Apps Script interface, like I did in the past with external scripts, but it doesn't work (I think because the trigger call the function without the "value" variable).
I was thinking to add an external triggered script that update the value of another cell (let's suppose "C1"), and then use the onEdit function to update the custom functions. I searched a lot about onEdit, but I really didn't understand how to make it works in my case.
Should the onEdit function recall myFunction? In what way?
Any help is appreciated, thank you
You can use this function for refreshing formulas in your column:
function updateColumnBFormulas()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('test');
var range = sheet.getRange(1, 2, sheet.getLastRow(), 1);
// get all formulas
var formulas = range.getFormulas();
for (var i = 0; i < formulas.length; i++)
{
// if there's formula in a cell
if (formulas[i][0])
{
// refresh it
sheet.getRange(i+1, 2).setFormula(formulas[i][0]);
}
}
}
Then set up trigger to run it every minute (Edit - Current project's trigger):
Ok, I solved with an external script that updates a cell, and then a dummy argument in my custon function that refers to that cell (as suggested by #RobinGertenbach)
This is the external triggered script:
function update() {
var number = Math.floor(new Date().getTime()/1000);
ss.getSheetByName("Data").getRange("A1").setValue(number);
}
and my custom function now looks like:
function myFunction(value, now) {
var value = value
var now = now
...
}
and then it is called in column B in this way:
=myFunction(A2, $A$1)
=myFunction(A3, $A$1)
=myFunction(A4, $A$1)
...
The solution with a function for refreshing formulas posted above was not doing the job, I don't know why. Formulas were refreshing but the values didn't get updated.
Thank you very much for your help!