Sanli
Sanli

Reputation: 77

Three drop down lists depending on each other

I need to get three depending drop-down lists, which depend on each other. Here is an editable sheet with the example. Cells in the yellow column contain a drop-down list which is based on usual data validation (Options sheet). Cells in the green column give a corresponding drop-down list, which is based on the script. And in blue column I need to get a corresponding list from the sheet Options with names corresponding with the data in the middle green column.

I will appreciate any help.

var mainWsName = "master";
var optionsWsName = "options";
var firstLevelColumn = 12;
var secondLevelColumn = 13;
var thirdLevelColumn = 14;

var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(mainWsName);
var wsOptions = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(optionsWsName);


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 === mainWsName && c === firstLevelColumn && r > 4){
    applyFirstLevelValidation(val,r);
  } else if(wsName === mainWsName && c === secondLevelColumn && r > 4){
    applySecondLevelValidation(val,r);
  } 


} //end onEdit

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

}  



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

}  

function applyValidationToCell(list,cell){

  var rule = SpreadsheetApp
  .newDataValidation()
  .requireValueInlist(list)
  .setAllowInvalid(false)
  .build();

  cell.setDataValidation(rule)
}

0

Upvotes: 1

Views: 238

Answers (1)

Tanaike
Tanaike

Reputation: 201378

  • You want to show the dropdown list to the column "N" by the column "M".

If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.

Modification points:

  • options is not declared for the function of applyFirstLevelValidation and applySecondLevelValidation.
  • r.thirdLevelColumn of ws.getRange(r.thirdLevelColumn) occurs an error. Because r is the number.
  • .requireValueInlist(list) is .requireValueInList(list). It's a spelling mistake.

Modified script:

When your script is modified, please modify as follows.

From:

var filteredOptions = options.filter(function(o){ return o[0] === val });

To:

var filteredOptions = wsOptions.getDataRange().getValues().filter(function(o){ return o[0] === val });

and

From:

var filteredOptions =options.filter(function(o){ return o[0] === firstLevelColValue && o[1] === val });

To:

var filteredOptions = wsOptions.getDataRange().getValues().filter(function(o){ return o[0] === firstLevelColValue && o[1] === val });

and

From:

var listToApply = filteredOptions.map(function(o){ return o[2] });
var cell = ws.getRange(r.thirdLevelColumn);
applyValidationToCell(listToApply,cell);

To:

var listToApply = filteredOptions.map(function(o){ return o[2] });
var cell = ws.getRange(r, thirdLevelColumn);  // <--- Modified
applyValidationToCell(listToApply,cell);

and

From:

var rule = SpreadsheetApp
.newDataValidation()
.requireValueInlist(list)
.setAllowInvalid(false)
.build();

To:

var rule = SpreadsheetApp
.newDataValidation()
.requireValueInList(list)  // <--- Modified
.setAllowInvalid(false)
.build();

Whole modified script:

var mainWsName = "master";
var optionsWsName = "options";
var firstLevelColumn = 12;
var secondLevelColumn = 13;
var thirdLevelColumn = 14;

var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(mainWsName);
var wsOptions = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(optionsWsName);

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 === mainWsName && c === firstLevelColumn && r > 4){
    applyFirstLevelValidation(val,r);
  } else if(wsName === mainWsName && c === secondLevelColumn && r > 4){
    applySecondLevelValidation(val,r);
  } 
} //end onEdit

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 = wsOptions.getDataRange().getValues().filter(function(o){ return o[0] === val });  // <--- Modified
    var listToApply = filteredOptions.map(function(o){ return o[1] });
    var cell = ws.getRange(r, secondLevelColumn);
    applyValidationToCell(listToApply,cell);
   }
}  

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 = wsOptions.getDataRange().getValues().filter(function(o){ return o[0] === firstLevelColValue && o[1] === val });  // <--- Modified
    var listToApply = filteredOptions.map(function(o){ return o[2] });
    var cell = ws.getRange(r, thirdLevelColumn);  // <--- Modified
    applyValidationToCell(listToApply,cell);
   }
}  

function applyValidationToCell(list,cell){
  var rule = SpreadsheetApp
  .newDataValidation()
  .requireValueInList(list)  // <--- Modified
  .setAllowInvalid(false)
  .build();

  cell.setDataValidation(rule)
}

References:

If I misunderstood your question and this was not the direction you want, I apologize.

Upvotes: 1

Related Questions