App Script: How to combine 2 onEdit functions? [duplicate] - javascript

This question already has answers here:
How to run multiple onEdit functions
(2 answers)
Best Practices for Multiple OnEdit Functions
(1 answer)
Closed last month.
I have 2 functions that I can get to work individually, but I have know idea how to combine them and have them work concurrently.
The first function pulls the value from A1 (which references a cell in another sheet) and returns it to B1. The second takes the value form B1 and renames the tab.
function onEdit(e){
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var sh = activeSheet = ss.getActiveSheet();
var newName = activeSheet.getRange(1,1).getValue();
activeSheet.getRange(1,2).setValue(newName);
}
function onEdit(e) {
if(e.range.rowStart === 1 && e.range.columnStart === 2) {
e.source.getActiveSheet().setName(e.value);
}
}
From what I've found online, I'm guessing an if statement would help but I'm not sure how to implement it.

function onEdit(e) {
var sh = e.range.getSheet();
sh.getRange(1, 2).setValue(sh.getRange(1, 1).getValue());
if (e.range.rowStart == 1 && e.range.columnStart == 2) {
sh.setName(e.value);
}
}

Related

Is there a way to track nonadjacent ranges in Google Apps Script on an onEdit trigger?

I have been through several other answers, but none of the code is working as expected. I'm trying to track input into a specific range when there are edits to add points to a chart. When people paste into a range, the event only fires once.
The change I have been testing to track multiple inputs is the following:
const sheet = SpreadsheetApp.getActiveSheet();
let selection = sheet.getActiveRangeList();
let ranges = selection.getRanges();
for (let i = 0; i < ranges.length; i++) {
console.log('Active ranges: ' + ranges[i].getA1Notation());
}
The console only shows the A1 notation for the first cell that was selected in the range. I have seen the bug report from four years ago, but I'm really hoping my implementation is the problem.
Here's a couple of functions with the method .getActiveRangeList()
function onEdit(e) {
e.source.toast("Entry");
Logger.log(JSON.stringify(e));
const sh = e.range.getSheet();
if(sh.getName() == "Sheet0") {
e.source.toast("Gate1")
sh.getActiveRangeList().getRanges().forEach(rg => {
Logger.log(rg.getA1Notation());
rg.setBackground("yellow");
});
}
};
function getActiveRangeList() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
sh.getActiveRangeList().getRanges().forEach(r => {
Logger.log(r.getA1Notation());
})
}
If I copy something into the clipboard and then make 3 non overlapping selections while holding down the control key and then hit control V it pastes in all three of the selected ranges but the Logger.log() only returns the first selected range from the onEdit() function. However, if I run the other function immediately after that the Logger.log function returns the three A1Notations for all three ranges.

Google Apps Script multiple IF statements in an onEdit function

Background
I'm trying to write a script that will check two different cells to see if the checkbox has been checked. So, it would first check one cell (AL4) to see if the value is true, and then a different cell (Q4) to see if the value is true. If the value is true, then it will run a different function.
Both of the cells I am checking are in the same sheet, "Dashboard", so it doesn't have to find different sheet names. I've been different ways to get it to check the different cells by using .getcolumn and .getrow commands but I've had some trouble with that too. I've also run into some problems where it will ignore the if statement and run the function on every edit and not just when the two cells are checked.
How can I get an if and else if statement to work in the same onEdit function?
Current Script
function onEdit(e) {
const sheetName = "Dashboard"
var range = e.range;
if (range.getSheet().getSheetName() != sheetName || range.getA1Notation() != "AL4" || !range.isChecked()) {
return;
RefreshCheckmark2();
} else if (range.getSheet().getSheetName() != sheetName || range.getA1Notation() != "Q4" || !range.isChecked()) {
return;
InverseYieldRefresh();
}
}
Also, the above code is completely functional if you remove the else if statement and the brackets after the first If statement.
Ideally I would like to be able to add more else if statements so that it can check more cells because I like to have checkboxes run commands and if my understanding is correct, you can't have more than one onEdit function in a single spreadsheet.
Thank you for any insight!
I think what you are trying to do right now is to check if it is not AL4 or Q4 rather than checking if it is AL4 or Q4. Also, in your current code, you use return; before running any function so it would really skip running the function even if it goes in your if-statement. You can try this code below:
function onEdit(e) {
const sheetName = "Dashboard"
var range = e.range;
if (range.getSheet().getSheetName() == sheetName && range.getA1Notation() == "AL4" && range.isChecked()) {
RefreshCheckmark2();
}
else if (range.getSheet().getSheetName() == sheetName && range.getA1Notation() == "Q4" && range.isChecked()) {
InverseYieldRefresh();
}
}
I only changed the conditions to make it check if it is AL4 or Q4 then removed the return; to make the functions inside the if-statements run once conditions are satisfied.
Let me know if this solves your problem.

Merging or Combining two onEdit trigger functions

I have script for Google Sheets that I collected on interwebs and got some help here. No I have 2 onEdit in conflict. I overcome that by creating script Trigger for onEdit2. It works but I don't think it is the best solution. Could you help get those two separated onEdit with if functions into one, please?
//Dependent Dropdown list
function onEdit(e){ // Function that runs when we edit a value in the table.
masterSelector(master1,master2,master3,master4);
var activeCell = e.range; // It returns the coordinate of the cell that we just edited.
var val = activeCell.getValue(); // Returns the value entered in the column we just edited.
var r = activeCell.getRow(); // returns the row number of the cell we edit.
var c = activeCell.getColumn(); // returns the column number of the cell we edit.
var wsName = activeCell.getSheet().getName();
if (wsName === masterWsName && c === firstLevelColumn && r > masterNumberOfHeaderRows) { // the if delimits the section sensitive to modification and action of the onEdit.
applyFirstLevelValidation(val,r);
} else if (wsName === masterWsName && c === secondLevelColumn && r > masterNumberOfHeaderRows){
applySecondLevelValidation(val,r);
}
} // end of onEdit
// addRow by checkboxes
function onEdit2(e) {
masterSelector(master1,master2,master3,master4);
//IF the cell that was edited was in column 4 = D and therefore a checkbox AND if the cell edited was checked (not unchecked):
if (e.range.columnStart === 4 && e.range.getValue() === true) {
var sheet = SpreadsheetApp.getActiveSheet(),
row = sheet.getActiveCell()
.getRow(),
//(active row, from column, numRows, numColumns)
rangeToCopy = sheet.getRange(row, 1, 1, 30);
sheet.insertRowAfter(row);
rangeToCopy.copyTo(sheet.getRange(row + 1, 1));
//Reset checked boxes in column 4
sheet.getRange(row,4,2,1).setValue(false);
}
}
Whole script is here, if needed.
A script cannot contain two functions with the same name. Rename your first onEdit function to onEdit1 (actually it will be better to assign a descriptive name) and the second function as onEdit2, then put them both in one function named onEdit and pass the parameter e to both of them:
function onEdit(e){
onEdit1(e);
onEdit2(e);
}
Related:
Two OnEdit functions not working together
Best Practices for Multiple OnEdit Functions
How to run multiple onEdit functions in the same google script (google sheets)?
Bracketing multiple onEdit functions

google apps script not working

I have this code that works for restricting data in all cells to 5 characters. I like that it shortens the data back to 5 characters if you put more that 5 in.
function onEdit(e) {
var limit = 5;
if(e.value.length > limit) {
e.range.setValue(e.value.substring(0, limit));
}
}
If I click the Run button it does show an error.
TypeError: Cannot read property "value" from undefined. (line 3, file "Code")
But it seems to work fine.
I would like to have the script work on a certain range of cells only. Say C3:C100. So I had to reference the sheet and cells, so changed the script to this.
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("C3:C100");
var limit = 5;
if(e.value.length > limit) {
e.range.setValue(e.value.substring(0, limit));
}
}
This script does not work on any of the cells, let alone the selected ones.
Can anyone help me please? What have I missed?
A onEdit script is triggered by any edit in a spreadsheet. It 'captures' the edit in what is called an event object. The event object can be passed as an argument to the function. In that case you'll see onEdit(e) or onEdit(event) as the function name. That object has some parameters attached to it: e.range (the edited range), e.value (the value of the edit), e.source (the spreadsheet where the edit is done), etc..
Now when you run the function from the script editor (by clicking the play button) no actual edit is taking place in the spreadsheet. Therefore no event object will be created and all parameters of that object will be undefined.
If you want to 'limit' the scope of the script to the range C3:C100, you can change the script as follows:
function onEdit(e) {
var limit = 5;
if (e.value.length > limit && e.range.rowStart > 2 && e.range.rowStart < 101 && e.range.columnStart == 3) {
e.range.setValue(e.value.substring(0, limit));
}
}
Note that currently the script will work on every tab/sheet inside your spreadsheet/workbook. If you want to further limit the script to work on only one sheet (e.g. 'Sheet1'), you can try something like
function onEdit(e) {
var limit = 5;
if (e.source.getActiveSheet().getName() == 'Sheet1' && e.value.length > limit && e.range.rowStart > 2 && e.range.rowStart < 101 && e.range.columnStart == 3) {
e.range.setValue(e.value.substring(0, limit));
}
}

How to make onEdit() trigger function apply to multiple sheets

I have a Google Sheet I'm working on.
I have a script that fills in the column B with a timestamp when I update column A on the first tab. However I need it to do the same on the second tab, but I can't get it to work there. What do I need to change?
The current script I'm using is:
function onEdit(e) {
var sheetToWatch= 'Wrong Grading',
columnToWatch = 1,
columnToStamp = 2; //change all of these to your needs
if (e.range.columnStart !== columnToWatch
|| e.source.getActiveSheet().getName() !== sheetToWatch
|| !e.value)
return;
e.source.getActiveSheet()
.getRange(e.range.rowStart, columnToStamp)
.setValue(new Date());
}
For future readers, the code snippet in Paul's question is derived from code on the Google Docs help forum, which includes a detailed line-by-line explanation.
The function uses the variable sheetToWatch to identify one sheet (aka "tab") that the onEdit() function cares about. That is validated by this comparison:
|| e.source.getActiveSheet().getName() !== sheetToWatch
...and if the source of the current trigger event is not matched, the function exits without doing anything.
What do I need to change? If you want this function to work on all sheets in the Spreadsheet, then you can just eliminate this check altogether:
function onEdit(e) {
var columnToWatch = 1,
columnToStamp = 2; //change all of these to your needs
if (e.range.columnStart !== columnToWatch
|| !e.value)
return;
e.source.getActiveSheet()
.getRange(e.range.rowStart, columnToStamp)
.setValue(new Date());
}
If you want to have the onEdit() operate on a set of sheets, then you can change that above comparison to check if the current sheet's name is found in an array of sheet names. That will change the comparison to this:
|| sheetsToWatch.indexOf( e.source.getActiveSheet().getName() ) === -1
You can learn more about the indexOf() method here. What it's doing though, is getting the name of the event trigger source sheet, finding it in the sheetsToWatch array, and returning the found index. If the sheet does not appear in the array, indexOf() returns -1.
The resulting function is:
function onEdit(e) {
var sheetsToWatch= ['Wrong Grading',
'Something Else'],
columnToWatch = 1,
columnToStamp = 2; //change all of these to your needs
if (e.range.columnStart !== columnToWatch
|| sheetsToWatch.indexOf( e.source.getActiveSheet().getName() ) === -1
|| !e.value)
return;
e.source.getActiveSheet()
.getRange(e.range.rowStart, columnToStamp)
.setValue(new Date());
}

Categories