0

I have 3 columns, all of which will have dropdowns (data validations).

Col 2 and 3 will show only if Col 1 is set to "Yes"

Col 1 | Col 2 | Col 3

Yes
No

Is there a way of using the if statement to load a dropdown or a google script

I have tried using this article/video

It works only if the Named ranges are linked, if not, it doesnt work. In this case Col 2 and Col 3 are unconnected only thing common is the "Yes" in Col 1.

2
  • In essence the video correctly outlines what you need to do. The script part really controls what depends on what, all you need is named ranges. I have a spreadsheet that provides conditional validation in col 2 based on col 1 and in col 3 based on the combination of col1 and col 2. Please show us your script (and a sample of your spreadsheet). Commented Apr 20, 2017 at 7:27
  • Heres a sample of my spreadsheet, detailing how it should work. docs.google.com/spreadsheets/d/… Commented Apr 20, 2017 at 7:51

1 Answer 1

3

From the sample I can see that it's just a copy paste of the code. The way it was designed was specifically to work that way, so you need to adjust the code for your purpose.

You might want to rewrite the code to be more accurate for your needs.

In the sample the onEdit() gets the column you are editing. Just as a side note, that can also be done easier. Instead of

function onEdit (){  
  var aCell = SpreadsheetApp.getActiveSheet().getActiveCell();

it could simply be (read up here)

function onEdit (event){  
  var aCell = event.range;

Then we look at the next important line that is the same for both options

var range = SpreadsheetApp.getActiveSheet().getRange(aCell.getRow(), aColumn + 1);

what this does is simply gets the next column range and that is where the rule will be applied. Now if you want the rule to apply to columns B C and D, all you need to do is adjust the getRange() like this:

var range = SpreadsheetApp.getActiveSheet().getRange(aCell.getRow(), aColumn + 1, 1, 3);

This will apply the rule to the all 3 columns. In .getRange(aCell.getRow(), aColumn + 1); the aCell.getRow() is for the current row, aColumn + 1 gets the next column after the one that was edited, 1 means get only 1 row and the next 3 says that get 3 columns. This however will only apply the exact same rule to everything. If you want to have different data sets for all 3 columns, you will have to adjust the other function:

function depDrop_(range, sourceRange){
  var rule = SpreadsheetApp.newDataValidation().requireValueInRange(sourceRange, true).build();
  range.setDataValidation(rule);
}

Currently it just sets 1 rule. What you will need is to create a rule for each range. You can either send it more variables or you can extract each column from that range and set a different rule on each.

Finally here is a sample of how I did it (basically the same as the example, just a bit more complex as it's something that actually is used in production)

function validateDynamic(event) {
  var spSheet = SpreadsheetApp.getActiveSpreadsheet();
  var shData = spSheet.getActiveSheet();
  var colTYPE = 2;          // column index for the Type entry
  var colMANUF = 6;         // column index for the Manufacturer entry
  var colMODEL = 7;         // column index for the Model entry

  var range;
  var newVal;
  if (event) {
    range = event.range;
    newVal = event.value;
  }
  else {
    range = SpreadsheetApp.getActiveRange();
    newVal = range.getValue();
  }

  var row = range.getRow();
  var col = range.getColumn();
  var validRange;
  var targetRange;
  var ruleName;

  switch(col) {
    case colTYPE:
//      shData.getRange(row, colMANUF, 1, 2).clearDataValidations().clearContent()
      targetRange = shData.getRange(row, colMANUF);
      ruleName = genRangeName('Type',newVal);
      if (newVal === 'N/A') {
        shData.getRange(row, colTYPE + 1, 1, shData.getMaxColumns() - 2).clearContent();
        shData.getRange(row, colMANUF, 1, 2).setValues([['N/A','N/A']]);
        setRule(genRangeName('Type',newVal),shData.getRange(row, colMODEL));
      }
      break;
    case colMANUF:
      var typeName = shData.getRange(row, colTYPE).getValue();
//      shData.getRange(row, colMODEL, 1, 1).clearDataValidations().clearContent();
      targetRange = shData.getRange(row, colMODEL);
      ruleName = genRangeName(typeName,newVal);
      break;
    default:
      throw('Dynamic Validation should not have run');
  }

  setRule(ruleName, targetRange);

  return 0;
}

And here is a screenshot of the data validation page (where I keep the lists for what should be in the dropdowns). This is way more conditional than what you need, but it's a different perspective :)

enter image description here

I build the named ranges with functions as well:

function genRangeName(str1, str2) {
  var name;
  if (str1 == '' || str1 == null || str1 == undefined) {
    name = str2;
  }
  else if (str2 == '' || str2 == null || str2 == undefined) {
    name = str1;
  }
  else
    name = str1 + '_' + str2;
  name = name.replace(/ /g,'');
  name = name.replace(/\//g,'');
  return name.toLowerCase();
}

and this is the function that actually sets the rule:

function setRule(ruleName, targetRange) {
  var validRange = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(ruleName);
  var rule = SpreadsheetApp.newDataValidation();
  rule.setAllowInvalid(false);
  rule.requireValueInRange(validRange);
  rule.build();
  targetRange.setDataValidation(rule);
  return 0;
}

NOTE:

The above is the general explanation. I have walked the asker through this via chat on his spreadsheet. Here is the code of how the task can be accomplished. To anyone else finding this, keep in mind that this is very static. It only works if you have the data validation applied to columns B, C and D with the exact same names.

function onEdit(event) {

  var row = event.range.getRow();     //we get the current row of the range so we do not have to worry about it later
  var col = event.range.getColumn();  //we get the current column of the range so we do not have to worry about it later

//  In this section we simply check if the edited column was column A. If not we do not care for the rest of the code and stop the script with a return
  if (col !== 1) {
    return 1;
  }
//  ------------------------------------------------------------------------------------------------------------------------------------------------------

  var rule
  var targetRange
  var sp = SpreadsheetApp.getActiveSheet()

  if (sp.getIndex() !== 1) {
    return 1
  }

  if (event.value == 'Bend') {
    targetRange = sp.getRange(row, 2)
    setRule(targetRange, 'bend_dyes')

    targetRange = sp.getRange(row, 3)
    setRule(targetRange, 'type_of_bend')

    targetRange = sp.getRange(row, 4)
    setRule(targetRange, 'bend_size')
  }
  else {
    targetRange = sp.getRange(row, 2, 1, 3) //we want to clear all data validation if it was set to something else
    targetRange.clearDataValidations()
  }

}

function setRule(targetRange, ruleName){
  var ruleRange = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(ruleName)
  var rule = SpreadsheetApp.newDataValidation().requireValueInRange(ruleRange, true)
  targetRange.setDataValidation(rule)

}
Sign up to request clarification or add additional context in comments.

2 Comments

How do I clear validation only if the event value is other than "Bend", but allowing all the targetranges to be captured. Right now it removes validation the moment any one of the targetranges are filled.
Its ok, I made a mistake in the scripting, thanks a lot Vytautas!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.