How do you do dynamic / dependent drop downs in Google Sheets?

前端 未结 5 1188
清歌不尽
清歌不尽 2020-11-27 12:06

How do you get a sub-category column to populate a drop down based on the value selected in the main category drop down in google sheets?

I googled around and couldn

5条回答
  •  遥遥无期
    2020-11-27 12:19

    Continuing the evolution of this solution I've upped the ante by adding support for multiple root selections and deeper nested selections. This is a further development of JavierCane's solution (which in turn built on tarheel's).

    /**
     * "on edit" event handler
     *
     * Based on JavierCane's answer in 
     * 
     *   http://stackoverflow.com/questions/21744547/how-do-you-do-dynamic-dependent-drop-downs-in-google-sheets
     *
     * Each set of options has it own sheet named after the option. The 
     * values in this sheet are used to populate the drop-down.
     *
     * The top row is assumed to be a header.
     *
     * The sub-category column is assumed to be the next column to the right.
     *
     * If there are no sub-categories the next column along is cleared in 
     * case the previous selection did have options.
     */
    
    function onEdit() {
    
      var NESTED_SELECTS_SHEET_NAME = "Sitemap"
      var NESTED_SELECTS_ROOT_COLUMN = 1
      var SUB_CATEGORY_COLUMN = NESTED_SELECTS_ROOT_COLUMN + 1
      var NUMBER_OF_ROOT_OPTION_CELLS = 3
      var OPTION_POSSIBLE_VALUES_SHEET_SUFFIX = ""
      
      var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet()
      var activeSheet = SpreadsheetApp.getActiveSheet()
      
      if (activeSheet.getName() !== NESTED_SELECTS_SHEET_NAME) {
      
        // Not in the sheet with nested selects, exit!
        return
      }
      
      var activeCell = SpreadsheetApp.getActiveRange()
      
      // Top row is the header
      if (activeCell.getColumn() > SUB_CATEGORY_COLUMN || 
          activeCell.getRow() === 1 ||
          activeCell.getRow() > NUMBER_OF_ROOT_OPTION_CELLS + 1) {
    
        // Out of selection range, exit!
        return
      }
      
      var sheetWithActiveOptionPossibleValues = activeSpreadsheet
        .getSheetByName(activeCell.getValue() + OPTION_POSSIBLE_VALUES_SHEET_SUFFIX)
      
      if (sheetWithActiveOptionPossibleValues === null) {
      
        // There are no further options for this value, so clear out any old
        // values
        activeSheet
          .getRange(activeCell.getRow(), activeCell.getColumn() + 1)
          .clearDataValidations()
          .clearContent()
          
        return
      }
      
      // Get all possible values
      var activeOptionPossibleValues = sheetWithActiveOptionPossibleValues
        .getSheetValues(1, 1, -1, 1)
      
      var possibleValuesValidation = SpreadsheetApp.newDataValidation()
      possibleValuesValidation.setAllowInvalid(false)
      possibleValuesValidation.requireValueInList(activeOptionPossibleValues, true)
      
      activeSheet
        .getRange(activeCell.getRow(), activeCell.getColumn() + 1)
        .setDataValidation(possibleValuesValidation.build())
        
    } // onEdit()

    As Javier says:

    • Create the sheet where you'll have the nested selectors
    • Go to the "Tools" > "Script Editor…" and select the "Blank project" option
    • Paste the code attached to this answer
    • Modify the constants at the top of the script setting up your values and save it
    • Create one sheet within this same document for each possible value of the "root selector". They must be named as the value + the specified suffix.

    And if you wanted to see it in action I've created a demo sheet and you can see the code if you take a copy.

提交回复
热议问题