I am very new to google script trying to resolve key issues in business flow.
Through search have come up with the below script for multi-level data validation for sheet Template.
How can I edit this script to run for all Sheets except specific ones (ex. Sheet1, Sheet 2)
I have found the option of excluding sheets with the code below, but not sure how to use it and where to input it
var excludes = [];
// if (excludes.indexOf(s.getName()) != -1) return;
Thanks you in advance
var mainwsMaster = "Template";
var MenuWSname = "Master Menu"
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(mainwsMaster);
var wsMenu = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(MenuWSname);
var Menu = wsMenu.getRange(2,1,wsMenu.getLastRow()-1,3).getValues();
var firstColumn = 8;
var secondColumn = 9;
var thirdColumn = 10;
function onEdit(e){
var activeCell = e.range;
var val = activeCell.getValue();
var r = activeCell.getRow();
var c = activeCell.getColumn();
var wsName = activeCell.getSheet().getName();
if(wsName === mainwsMaster && c === firstColumn && r > 6){
applyFirstLevelValidation(val,r)
} else if(wsName === mainwsMaster && c === secondColumn && r > 6){
applySecondLevelValidation(val,r);
}
}//end onEdit
function applyFirstLevelValidation(val,r){
if(val === ""){
ws.getRange(r,secondColumn).clearContent();
ws.getRange(r,secondColumn).clearDataValidations();
ws.getRange(r,thirdColumn).clearContent();
ws.getRange(r,thirdColumn).clearDataValidations();
} else {
ws.getRange(r,secondColumn).clearContent();
ws.getRange(r,secondColumn).clearDataValidations();
ws.getRange(r,thirdColumn).clearContent();
ws.getRange(r,thirdColumn).clearDataValidations();
var filteredOptions = Menu.filter(function(o){return o[0] === val });
var filteredpiata = filteredOptions.map(function(o){return o[1] } );
var cell = ws.getRange(r,secondColumn);
applyValidationToCell(filteredpiata,cell);
}
}
function applySecondLevelValidation(val,r){
if(val === ""){
ws.getRange(r,thirdColumn).clearContent();
ws.getRange(r,thirdColumn).clearDataValidations();
} else {
ws.getRange(r,thirdColumn).clearContent();
var firstLevelColValue = ws.getRange(r, firstColumn).getValue();
var filteredOptions = Menu.filter(function(o){return o[0] === firstLevelColValue && o[1] === val });
var filteredpiata = filteredOptions.map(function(o){return o[2] } );
var cell = ws.getRange(r,thirdColumn);
applyValidationToCell(filteredpiata,cell);
}
}
function applyValidationToCell(list,cell){
var rule = SpreadsheetApp
.newDataValidation()
.requireValueInList(list)
.setAllowInvalid(false)
.build();
cell.setDataValidation(rule);
}
You mentioned this code:
var excludes = [];
// if (excludes.indexOf(s.getName()) != -1) return;
for your code it would look like this instead:
var excludes = ["Sheet1","Sheet2","OtherSheetToExclude","ETC"];
if (excludes.indexOf(wsName) != -1) {return};
You would place those two lines just after the wsName variable is declared in your onEdit(e) script.
It's basically saying. "Take the name of the sheet you've just edited and look for it in this list i just made called "Excludes". If you find it in there, STOP running this function."
Try
var excludes = ['Sheet1','Sheet2'];
and then, change as following
if( excludes.indexOf(wsName) == -1 && c === firstColumn && r > 6)
for instance, focused on the onEdit function
var firstColumn = 8;
var secondColumn = 9;
var excludes = ['Sheet1','Sheet2'];
function onEdit(e){
var activeCell = e.range;
var val = activeCell.getValue();
var r = activeCell.getRow();
var c = activeCell.getColumn();
var wsName = activeCell.getSheet().getName();
if(excludes.indexOf(wsName) == -1 && c === firstColumn && r > 6){
activeCell.getSheet().getRange('A1').setValue('cas1')
} else if(excludes.indexOf(wsName) == -1 && c === secondColumn && r > 6){
activeCell.getSheet().getRange('A1').setValue('cas2')
}
}//end onEdit
Related
In this sheet, I have multiple dependent dropdown lists. These dropdown lists evaluate if they have multiple or only one option available. If I only have one option, it will autocomplete with the single possible value.
This is an example of the sheet: https://docs.google.com/spreadsheets/d/13fIO3OgAALDVx5PmX6mx0RMdES4PUdsSBU9aBOQhwuk/edit?usp=sharing
The problem is that when I chose a client that only has one project, this project is completed automatically but the task isn't.
This is an example of what I want when I will select Client 3 in column A
Code I use:
var mainWsName = "Page 1";
var optionsWsName = "Data";
var firstLevelColumn = 1;
var secondLevelColumn = 2;
var thirdLevelColumn = 5;
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(mainWsName);
var wsOptions = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data");
var options = wsOptions.getRange(2,1,wsOptions.getLastRow()-1,7).getValues();
function onEdit(e){
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(mainWsName);
var row = e.range.getRow();
var col = e.range.getColumn();
var activeCell = e.range;
var val = activeCell.getValue();
var r = activeCell.getRow();
var c = activeCell.getColumn();
var wsName = activeCell.getSheet().getName()
if(wsName === mainWsName && c === firstLevelColumn && r > 3){
applyFirstLevelValidation(val,r)
}else if(wsName === mainWsName && c === secondLevelColumn && r > 3){
applySecondLevelValidation(val,r)
}
if(c === 1 && r > 3 && wsName === mainWsName && val === "intern"){
e.source.getActiveSheet().getRange(row,6).setValue("Not");
}else if(c === 1 && r > 3 && wsName === mainWsName && val !== ""){
e.source.getActiveSheet().getRange(row,6).setValue("Yes");
}else if(c === 1 && r > 3 && wsName === mainWsName && val === ""){
e.source.getActiveSheet().getRange(row,6).clearContent();
ws.getRange(r,secondLevelColumn).clearDataValidations();
}
}
function applyFirstLevelValidation(val,r){
if(val === ""){
ws.getRange(r,secondLevelColumn).clearContent();
ws.getRange(r,secondLevelColumn).clearDataValidations();
ws.getRange(r,thirdLevelColumn).clearContent();
ws.getRange(r,thirdLevelColumn).clearDataValidations();
} else{
ws.getRange(r,secondLevelColumn).clearContent();
ws.getRange(r,secondLevelColumn).clearDataValidations();
ws.getRange(r,thirdLevelColumn).clearContent();
ws.getRange(r,thirdLevelColumn).clearDataValidations();
var filteredOptions = options.filter(function(o){ return o[0] === val });
var listToApply = filteredOptions.map(function(o){ return o[1] });
var cell = ws.getRange(r,secondLevelColumn);
applyValidationToCell(listToApply,cell);
var rule = SpreadsheetApp.newDataValidation().requireValueInList(listToApply).build();//creo el dropdown
if(listToApply[1] || null){
applyValidationToCell(listToApply,cell);
}else{
cell.setDataValidation(rule).setValue(listToApply[0] || null);
}
}
}
function applySecondLevelValidation(val,r){
if(val === ""){
ws.getRange(r,thirdLevelColumn).clearContent();
ws.getRange(r,thirdLevelColumn).clearDataValidations();
} else{
ws.getRange(r,thirdLevelColumn).clearContent();
var firstLevelColValue = ws.getRange(r,firstLevelColumn).getValue();
var filteredOptions = options.filter(function(o){ return o[0] === firstLevelColValue && o[1] === val });
var listToApply = filteredOptions.map(function(o){ return o[2] });
var cell = ws.getRange(r,thirdLevelColumn);
applyValidationToCell(listToApply,cell);
var rule = SpreadsheetApp.newDataValidation().requireValueInList(listToApply).build();
cell.setDataValidation(rule).setValue(listToApply[0] || null);
}
}
function applyValidationToCell(list,cell) {
var rule = SpreadsheetApp.newDataValidation().requireValueInList(list).build();
cell.setDataValidation(rule);
}
Although I'm not sure whether I could correctly understand your question, for example, is the following modification the result you expect? In this modification, please modify the function of applyFirstLevelValidation as follows.
From:
if(listToApply[1] || null){
applyValidationToCell(listToApply,cell);
}else{
cell.setDataValidation(rule).setValue(listToApply[0] || null);
}
To:
if (listToApply[1] || null) {
applyValidationToCell(listToApply, cell);
} else {
cell.setDataValidation(rule).setValue(listToApply[0] || null);
applySecondLevelValidation(listToApply[0], r); // <--- Added
}
I have a script that filters from a database and creates dependant drop down lists based on initial inputs. I'm wondering is there anyway to set a default value to appear in these drop downs? Ideally so there are automatically set to the first value in the drop-downs?
I think I should be able to modify the applyValidationToCell function but I'm not sure how?
Any help would be appreciated
var mainWSname = "Sheet1"
var optonsWSname = "Sheet2"
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(mainWSname);
var wsOptions = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(optonsWSname);
var options = wsOptions.getRange(2, 15, wsOptions.getLastRow()-1, 3).getValues();
var firstLevel = 3
var secondLevel = 4
var thirdLevel = 5
function onEdit(e){
var activeCell = e.range;
var r = activeCell.getRow()
var c = activeCell.getColumn()
var val = activeCell.getValue();
var wsName = activeCell.getSheet().getName()
if(wsName === mainWSname && c === firstLevel && r > 76){
applyFirstLevelValidation(val, r)
} else if(wsName === mainWSname && c === secondLevel && r >76){
applySecondLevelValidation(val, r)
}
} /// end onEdit
function applyFirstLevelValidation(val, r){
if(val === ""){
ws.getRange(r,secondLevel).clearContent();
ws.getRange(r,secondLevel).clearDataValidations();
ws.getRange(r,thirdLevel).clearContent();
ws.getRange(r,thirdLevel).clearDataValidations();
} else {
ws.getRange(r,secondLevel).clearContent();
ws.getRange(r,secondLevel).clearDataValidations();
ws.getRange(r,thirdLevel).clearContent();
ws.getRange(r,thirdLevel).clearDataValidations()
var filteredOptions = options.filter(function(o){return o[0] === val})
var listToApply = filteredOptions.map(function(o) {return o[1] })
var cell = ws.getRange(r,secondLevel)
applyValidationToCell(listToApply, cell)
}
} //end applyFirstLevelValidation
function applySecondLevelValidation(val, r){
if(val === ""){
ws.getRange(r,thirdLevel).clearContent();
ws.getRange(r,thirdLevel).clearDataValidations();
} else {
ws.getRange(r,thirdLevel).clearContent()
var firstLevelColValue = ws.getRange(r, firstLevel).getValue();
var filteredOptions = options.filter(function(o){return o[0] === firstLevelColValue && o[1] === val })
var listToApply = filteredOptions.map(function(o) {return o[2] })
var cell = ws.getRange(r,thirdLevel)
applyValidationToCell(listToApply, cell)
}
} //end
function applyValidationToCell(list, cell){
var rule = SpreadsheetApp
.newDataValidation()
.requireValueInList(list)
.setAllowInvalid(false)
.build();
cell.setDataValidation(rule)
}
In your script, how about the following modification? In this modification, the function applyValidationToCell is modified.
From:
cell.setDataValidation(rule)
To:
cell.setDataValidation(rule).setValue(list[0]);
By the way, when the above modification is reflected in your script, 2nd data validation shows the initial value. But, in this case, the 3rd data validation is not shown. Because the 2nd data validation is not edited. So, when you want to put 2nd and 3rd data validations with the initial value when the 1st value is put to the column "C", how about the following modification? In this case, please modify your functions of applyValidationToCell and applyFirstLevelValidation as follows.
applyValidationToCell:
function applyValidationToCell(list, cell) {
var rule = SpreadsheetApp.newDataValidation().requireValueInList(list).setAllowInvalid(false).build();
cell.setDataValidation(rule).setValue(list[0]); // Modified
}
applyFirstLevelValidation:
function applyFirstLevelValidation(val, r) {
if (val === "") {
ws.getRange(r, secondLevel).clearContent();
ws.getRange(r, secondLevel).clearDataValidations();
ws.getRange(r, thirdLevel).clearContent();
ws.getRange(r, thirdLevel).clearDataValidations();
} else {
ws.getRange(r, secondLevel).clearContent();
ws.getRange(r, secondLevel).clearDataValidations();
ws.getRange(r, thirdLevel).clearContent();
ws.getRange(r, thirdLevel).clearDataValidations()
var filteredOptions = options.filter(function (o) { return o[0] === val })
var listToApply = filteredOptions.map(function (o) { return o[1] })
var cell = ws.getRange(r, secondLevel)
applyValidationToCell(listToApply, cell)
applySecondLevelValidation(listToApply[0], r); // Added
}
}
Note:
If the above modifications were not the result you expect, can you provide the sample Spreadsheet for replicating the issue? By this, I would like to confirm it.
You can create data validations as lists and then put them in any range you wish:
function myfunk() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
let r = SpreadsheetApp.newDataValidation().requireValueInList(['1','2','3','4','5']).build();
sh.getRange(1,1,5,1).setDataValidation(r);
}
DataValidation RequireValueInList
I'm trying to connect 2 spreadsheets, such that, I can perform a sumif function on one spreadsheet and get the result on the current one. I'm using onEdit installable trigger on function when since the simple trigger doesn't work. The dependant dropdown and also the sumif through a for loop works, but I can't seem to get the function when to call the function sum in order to set value on a cell. The sum function works separately and gives the result, but when executing onEdit it doesn't.
Also, is this the correct way to execute sumif? Is there any faster way(I require to execute it around 600-1000 times, here I kept it just 10 to test it out, which again is slow)?
My code follows:
'''
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var stck = SpreadsheetApp.openById("1WGbEo1Xr99HwHY_4ZaeTRIgCOuNcjVfqCzZx4dcQX4I");
var unisensor = stck.getSheetByName("Unisensor");
var ssOptions = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Product List");
var options1 = ssOptions.getRange(2,1,ssOptions.getLastRow() - 1,2).getValues();
function When(e){
var activeCell = e.range;
var val = activeCell.getValue();
var r = activeCell.getRow();
var c = activeCell.getColumn();
var ssName = activeCell.getSheet().getName();
if (ssName=="Stock" && r==2 && c==1){
ss.getRange(r,2).clearContent();
ss.getRange(r,2).clearDataValidations();
var filteredOptions = options1.filter(function(o){return o[0] === val});
var listToApply = filteredOptions.map(function(o){return o[1]});
console.log(listToApply);
var cell = ss.getRange(r,2);
applyValidationToCell(listToApply,cell);
}
if (ssName=="Stock" && r==2 && c==2){
var company = ss.getRange(r,1);
if(company ==="Unisensor"){
sum(val);
}
}
}
function applyValidationToCell(list,cell){
var rule = SpreadsheetApp
.newDataValidation()
.requireValueInList(list)
.setAllowInvalid(false)
.build();
cell.setDataValidation(rule);
}
function sum(val){
var res = 0;
var result = ss.getRange(2,3);
for (i =4;i<=10;i++){
var cell = unisensor.getRange(i,3).getValue();
var cellres = unisensor.getRange(i,9).getValue();
if( cell == val){
res+= cellres;
}
}
result.clearContent();
result.setValue(res);
Logger.log(res);
}
'''
Thanks in advance.
If when(e) is being executed without errors, but sum() is not called, this means that your if condition is not fulfilled
Troubleshoot by implementing the following logs:
function When(e){
var activeCell = e.range;
var val = activeCell.getValue();
var r = activeCell.getRow();
var c = activeCell.getColumn();
var ssName = activeCell.getSheet().getName();
if (ssName=="Stock" && r==2 && c==1){
ss.getRange(r,2).clearContent();
ss.getRange(r,2).clearDataValidations();
var filteredOptions = options1.filter(function(o){return o[0] === val});
var listToApply = filteredOptions.map(function(o){return o[1]});
console.log(listToApply);
var cell = ss.getRange(r,2);
applyValidationToCell(listToApply,cell);
}
if (ssName=="Stock" && r==2 && c==2){
console.log('if (ssName=="Stock" && r==2 && c==2)')
var company = ss.getRange(r,1);
if(company ==="Unisensor"){
console.log('company ==="Unisensor"')
sum(val);
}
else{
console.log('NOT company ==="Unisensor"')
}
}
else{
console.log('NOT if (ssName=="Stock" && r==2 && c==2)')
}
}
After the funciton executes on onEdit trigger - view the logs.
I have the following script in place to populate three different columns with differing date ranges (based on a filter formula) that are dependent on the date entered in column AM. Right now this is set up to adjust the data validation dropdown list ONLY if the cell in column AM is edited. I'd like it to also adjust the data validation dropdown list if the validation values themselves change (aka if I edit the filter formula at all).
Any help would be greatly appreciated!
var mainWsName = "PRT_Tracker";
var appointmentWsName = "Visit_Windows";
var firstLevelColumn = 39;
var secondLevelColumn = 41;
var thirdLevelColumn = 45;
var fourthLevelColumn = 50;
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(mainWsName);
var wsWindows = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(appointmentWsName);
var appointment = wsWindows.getRange(2,1,wsWindows.getLastRow()-1,4).getValues();
function onEdit(e) {
var activeCell = e.range;
var val = activeCell.getValue();
var r = activeCell.getRow(); //return row of active cell
var c =activeCell.getColumn(); // return col of active cell
var wsName = activeCell.getSheet().getName();
if (wsName === mainWsName && c === firstLevelColumn && r >1) {
applyFirstLevelValidation(val,r);
} if(wsName === mainWsName && c === firstLevelColumn && r >1) {
applySecondLevelValidation(val,r);
} if(wsName === mainWsName && c === firstLevelColumn && r >1) {
applyThirdLevelValidation(val,r);
}
}
function applyFirstLevelValidation(val,r){
var filteredAppointment = appointment.filter(function(a){return a[0] === val});
var listToApply = filteredAppointment.map(function(a){return a[1]});
var cell = ws.getRange(r,secondLevelColumn);
applyValidationToCell(listToApply,cell);
}
function applySecondLevelValidation(val,r){
var filteredAppointment = appointment.filter(function(a){return a[0] === val});
var listToApply = filteredAppointment.map(function(a){return a[2]});
var cell = ws.getRange(r,thirdLevelColumn);
applyValidationToCell(listToApply,cell);
}
function applyThirdLevelValidation(val,r){
var filteredAppointment = appointment.filter(function(a){return a[0] === val});
var listToApply = filteredAppointment.map(function(a){return a[3]});
var cell = ws.getRange(r,fourthLevelColumn);
applyValidationToCell(listToApply,cell);
}
function applyValidationToCell(list,cell) {
var rule = SpreadsheetApp
.newDataValidation()
.requireValueInList(list)
.build();
cell.setDataValidation(rule);
}
I have two scripts that run individually, but I can't seem to merge them together correctly. I am attempting to use the onEdit(e) function to capture the row of the cell that is edited, then used that row number to amend a different sheet.
function onEdit(e) {
if (
e.source.getSheetName() == "GPS" &&
e.range.columnStart == 10 &&
e.range.columnEnd == 10 &&
e.range.rowStart >= 4 &&
e.range.rowEnd <= 5000
) {
var range = e.range;
var row = range.getRow();
var change = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var url = change.getRange(row,1,1,1).getValue(); //How to use this variable????????????
function toMaster(change,row){
var dest = SpreadsheetApp.openById('destinationsheetidxxxx')
var s = dest.getSheetByName('GPS')
var data = s.getDataRange().getValues();
var url = change.getRange(row,1,1,1).getValue()
for(var i = 0; i<data.length;i++){
if(data[i][0] == url){
Logger.log((i+1))
var range = s.getRange(i+1,10,1,1);
range.setValue('Yes')
}
Try this:
function onEdit(e) {
var sh=e.range.getSheet();
if(sh.getName()=="GPS" && e.range.columnStart==10 && e.range.columnEnd == 10 && e.range.rowStart >= 4 && e.range.rowEnd<=5000) {
var row = e.range.rowStart;
var url = sh.getRange(row,1).getValue();
var dss=SpreadsheetApp.openById('destId')
var dsh=dss.getSheetByName('GPS')
var drg=dsh.getRange(row,1)
var data=drg.getValues()
for(var i = 0; i<data.length;i++){
if(data[i][0]==url){
Logger.log(i+1);
var range = dsh.getRange(i+1,10).setValue('Yes');
}
}
}
}