您如何在Google表格中进行动态/相关下拉?

tar*_*eel 39 validation google-sheets google-apps-script

如何根据google工作表中主类别下拉列表中选择的值来获取子类别列以填充下拉列表?

我google了,找不到任何好的解决方案,因此我想分享自己的解决方案.请参阅下面的答案.

tar*_*eel 27

您可以从设置了主页的Google工作表开始,然后下拉源页面,如下所示.

您可以通过常规数据>验证菜单提示设置第一列下拉菜单.

主页

已填充第一列的下拉列表的主页面.

下拉源页面

所需子类别的源页面

之后,您需要设置一个名称 的脚本onEdit.(如果不使用该名称,则getActiveRange()将不执行任何操作,只返回单元格A1)

并使用此处提供的代码:

function onEdit() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = SpreadsheetApp.getActiveSheet();
  var myRange = SpreadsheetApp.getActiveRange();
  var dvSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Categories");
  var option = new Array();
  var startCol = 0;

  if(sheet.getName() == "Front Page" && myRange.getColumn() == 1 && myRange.getRow() > 1){
    if(myRange.getValue() == "Category 1"){
      startCol = 1;
    } else if(myRange.getValue() == "Category 2"){
      startCol = 2;
    } else if(myRange.getValue() == "Category 3"){
      startCol = 3;
    } else if(myRange.getValue() == "Category 4"){
      startCol = 4;
    } else {
      startCol = 10
    }

  if(startCol > 0 && startCol < 10){
    option = dvSheet.getSheetValues(3,startCol,10,1);
    var dv = SpreadsheetApp.newDataValidation();
    dv.setAllowInvalid(false);  
    //dv.setHelpText("Some help text here");
    dv.requireValueInList(option, true);
    sheet.getRange(myRange.getRow(),myRange.getColumn() + 1).setDataValidation(dv.build());
   }

  if(startCol == 10){
    sheet.getRange(myRange.getRow(),myRange.getColumn() + 1).clearDataValidations();
  } 
  }
}
Run Code Online (Sandbox Code Playgroud)

之后,通过转到编辑>当前项目触发器在脚本编辑器屏幕中设置触发器.这将打开一个窗口,让您选择各种下拉菜单,最终以此结束:

触发设置

你应该好好去追求!

  • 这段代码可以短得多.查看此视频,其中显示了命名范围和setDataValidation的方法.我转录了代码检查视频下的评论.https://www.youtube.com/watch?v=ZgQPZMCBRuc (2认同)

Max*_*rov 9

注意

脚本有一个限制:它在一个下拉列表中处理多达500个值.

新脚本.201801

该脚本于2018年1月发布.请参阅:

  1. 带有说明和演示的主页,您可以在其中提出问题.
  2. GitHub页面包含说明和源代码.

改进:

  1. 加速
  2. 处理1张表中的多个规则
  3. 将其他工作表链接为源数据.
  4. 下拉列表的自定义列顺序

旧脚本.<201801

脚本的版本

  1. v.1.
  2. 第2节.2016-03.改进:适用于任何类别的重复项.例如,如果我们有list1与汽车模型和list2与颜色.任何型号都可以重复颜色.
  3. V3.2017-01.改进:输入唯一值时无错误.
  4. 最新版本:2018-02.请参阅此处的文章.

这个解决方案并不完美,但它带来了一些好处:

  1. 让你制作多个下拉列表
  2. 提供更多控制
  3. 源数据放在唯一的工作表上,因此编辑起来很简单

首先,这是一个工作示例,因此您可以在进一步测试之前进行测试.

当您选择一个选项时,脚本会生成新的验证规则

我的计划:

  1. 准备数据
  2. 像往常一样制作第一个列表: Data > Validation
  3. 添加脚本,设置一些变量
  4. 完成!

准备数据

数据看起来像一个表,其中包含所有可能的变体.它必须位于单独的工作表上,因此脚本可以使用它.看看这个例子:

Sourse数据

这里我们有四个级别,每个值重复.请注意,数据右侧的2列是保留的,因此请勿键入/粘贴任何数据.


第一个简单的数据验证(DV)

准备一个唯一值列表.在我们的示例中,它是行星列表.在包含数据的工作表上查找可用空间,并粘贴公式:=unique(A:A) 在主菜单上选择第一列,DV将从此处开始.转到数据>验证,然后选择具有唯一列表的范围.

从数据右侧4列


脚本

将此代码粘贴到脚本编辑器中:

function SmartDataValidation(event) 
{
  //--------------------------------------------------------------------------------------
  // The event handler, adds data validation for the input parameters
  //--------------------------------------------------------------------------------------
  
  
  // Declare some variables:
  //--------------------------------------------------------------------------------------
  var TargetSheet = 'Main' // name of the sheet where you want to verify the data
  var LogSheet = 'Data' // name of the sheet with information
  var NumOfLevels = 4 // number of associated drop-down list levels
  var lcol = 2; // number of the leftmost column, in which the changes are checked; A = 1, B = 2, etc.
  var lrow = 2; // line number from which the rule will be valid
  //--------------------------------------------------------------------------------------
  
  //	===================================   key variables	 =================================
  //
  //		ss			sheet we change (TargetSheet)
  //			br				range to change
  //			scol			number of column to edit
  //			srow			number of row to edit	
  //			CurrentLevel	level of drop-down, which we change
  //			HeadLevel		main level
  //			r				current cell, which was changed by user
  //			X         		number of levels could be checked on the right
  //
  //		ls			Data sheet (LogSheet)
  //
  //    ======================================================================================
  
  
  // [ 01 ].Track sheet on which an event occurs
  var ts = event.source.getActiveSheet();
  var sname = ts.getName();
  
  if (sname == TargetSheet) 
  {
    
    // ss -- is the current book
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    
    // [ 02 ]. If the sheet name is the same, you do business...
    var ls = ss.getSheetByName(LogSheet); // data sheet
    
    // [ 03 ]. Determine the level
    
    //-------------- The changing sheet --------------------------------
    var br = event.source.getActiveRange();
    var scol = br.getColumn(); // the column number in which the change is made
    var srow = br.getRow() // line number in which the change is made
    // Test if column fits
    if (scol >= lcol) 
    {
      // Test if row fits
      if (srow >= lrow) 
      {  
        var CurrentLevel = scol-lcol+2;
        // adjust the level to size of
        // range that was changed
        var ColNum = br.getLastColumn() - scol + 1;
        CurrentLevel = CurrentLevel + ColNum - 1; 
        
        // also need to adjust the range 'br'
        if (ColNum > 1) 
        {
          br = br.offset(0,ColNum-1);
        } // wide range
        
        var HeadLevel = CurrentLevel - 1; // main level
        
        // split rows
        var RowNum = br.getLastRow() - srow + 1;
        
        var X = NumOfLevels - CurrentLevel + 1;

        
        // the current level should not exceed the number of levels, or 
        // we go beyond the desired range
        if (CurrentLevel <= NumOfLevels )	
        {
          // determine columns on the sheet "Data"
          var KudaCol = NumOfLevels + 2
          var KudaNado = ls.getRange(1, KudaCol);
          var lastRow = ls.getLastRow(); // get the address of the last cell
          var ChtoNado = ls.getRange(1, KudaCol, lastRow, KudaCol);

          // ============================================================================= > loop >				
          for (var j = 1; j <= RowNum; j++)
          {		
            for (var k = 1; k <= X; k++) 
            {
               
              HeadLevel = HeadLevel + k - 1; // adjust parent level
              CurrentLevel = CurrentLevel + k - 1; // adjust current level
              
              var r = br.getCell(j,1).offset(0,k-1,1);
              var SearchText = r.getValue(); // searched text

              // if anything is choosen!
              if (SearchText != '') 
              {
                
                //-------------------------------------------------------------------
                
                // [ 04 ]. define variables to costumize data
                // for future data validation
                //--------------- Sheet with data --------------------------           
                // combine formula 
                // repetitive parts
                var IndCodePart = 'INDIRECT("R1C' + HeadLevel + ':R' + lastRow + 'C';
                IndCodePart = IndCodePart + HeadLevel + '",0)';
                // the formula
                var code = '=UNIQUE(INDIRECT("R" & MATCH("';
                code = code + SearchText + '",';
                code = code + IndCodePart;
                code = code + ',0) & "C" & "' + CurrentLevel
                code = code + '" & ":" & "R" & COUNTIF(';
                code = code + IndCodePart;   
                code = code + ',"' + SearchText + '") + MATCH("';
                code = code + SearchText + '";';
                code = code + IndCodePart;
                code = code + ',0) - 1'; 
                code = code + '& "C" & "' ;   
                code = code + CurrentLevel + '",0))';
                // Got it! Now we have to paste formula
                
                KudaNado.setFormulaR1C1(code);   
                // get required array
                var values = [];
                for (var i = 1; i <= lastRow; i++) 
                {
                  var currentValue = ChtoNado.getCell(i,1).getValue();
                  if (currentValue != '') 
                  { 
                    values.push(currentValue);
                  } 
                  else 
                  {
                    var Variants = i-1; // number of possible values
                    i = lastRow; // exit loop
                  }       
                }
                //-------------------------------------------------------------------
                
                // [ 05 ]. Build daya validation rule
                var cell = r.offset(0,1);
                var rule = SpreadsheetApp
                .newDataValidation()
                .requireValueInList(values, true)
                .setAllowInvalid(false)
                .build();
                cell.setDataValidation(rule); 
                if (Variants == 1) 
                {
                  cell.setValue(KudaNado.getValue());		
                } // the only value
                else
                {
                  k = X+1;
                } // stop the loop through columns
                
                
              } // not blanc cell
              else
              {
                // kill extra data validation if there were 
                // columns on the right
                if (CurrentLevel <= NumOfLevels ) 
                {
                  for (var i = 1; i <= NumOfLevels; i++) 
                  {
                    var cell = r.offset(0,i);
                    // clean
                    cell.clear({contentsOnly: true});
                    // get rid of validation
                    cell.clear({validationsOnly: true});
                  }
                } // correct level
              } // empty row
            } // loop by cols
          } // loop by rows
          // ============================================================================= < loop <	
          
        } // wrong level
        
      } // rows
    } // columns... 
  } // main sheet
}

function onEdit(event) 
{
  
  SmartDataValidation(event);
  
}
Run Code Online (Sandbox Code Playgroud)

这是要更改的变量集,您可以在脚本中找到它们:

  var TargetSheet = 'Main' // name of the sheet where you want to verify the data
  var LogSheet = 'Data' // name of the sheet with information
  var NumOfLevels = 4 // number of associated drop-down list levels
  var lcol = 2; // leftmost column, in which the changes are checked; A = 1, B = 2, etc.
  var lrow = 2; // line number from which the rule will be valid
Run Code Online (Sandbox Code Playgroud)

我建议每个熟悉脚本的人都会将您的编辑内容发送给此代码.我想,有更简单的方法来查找验证列表并使脚本运行得更快.