【问题标题】:How to set a named range for a data validation programmatically (in Google apps script) in a Google spreadsheet?如何在 Google 电子表格中以编程方式(在 Google 应用程序脚本中)为数据验证设置命名范围?
【发布时间】:2022-08-05 05:18:32
【问题描述】:

用例

例子。我有一个命名范围Apples(地址\"Sheet10!B2:B\"),用于对大量工作表单元格进行数据验证。 Apples 的数据范围可以更改(在脚本中),例如到\"Sheet10!D2:D\"。

它适用于 UI

我可以手动设置一个命名范围作为数据验证的数据源。 在这种情况下,单元格的数据验证将始终引用命名范围Apples 并更新数据范围。

如何在 Google Apps 脚本中制作它?

气体限制

如果您有 namedRange 对象,则用于设置数据验证的代码应如下所示:

      mySheet.getRange(\'F5\')
        .setDataValidation(
          SpreadsheetApp.newDataValidation()
            .requireValueInRange(
              namedRange.getRange()
            )
            .setAllowInvalid(false)
            .build()
        );

DataValidationBuilder.requireValueInRange() 在这里不起作用,因为它只需要 class Range(它无法获得 NamedRange),并且不会使用对命名范围的引用。

有解决方法吗?

UPD1 - Spreadsheet.getRangeByName() 不起作用

通过名称获取范围没有帮助,数据验证将获得实际的范围地址。 SpreadsheetApp.getActive().getRangeByName(\"Apples\")

UPD2 到目前为止在 GAS 中没有办法做到这一点

正如@TheMaster 发布的那样,目前不可能。

请为帖子设置+1:

附言看起来唯一可行的解​​决方案是 Google Sheets API。

  • 你可以试试这个api。或逆向工程师:设置命名范围并查看脚本中实际包含的 dv。
  • @TheMaster,是的,考虑过 API 方法。抱歉,没有收到what dv it actually has in script。 dv 是什么意思?
  • 是的,找到了。我为此使用了一个宏。 @TheMaster,感谢逆向工程点,真的忘记了宏。 :D
  • 伟大的。 Dv 只是数据验证
  • 虽然我不确定我是否能正确理解您的目标,但我提出了一个使用 Sheets API 的示例脚本。你能确认一下吗?如果我误解了您的问题并且没有用,我深表歉意。

标签: google-apps-script google-sheets google-sheets-api


【解决方案1】:

我认为在您的情况下,我认为当使用 Sheets API 时,您的目标可能可以使用。

解决方法 1:

此解决方法使用 Sheets API。

用法:

1. 准备一份谷歌电子表格。

  1. 请创建一个新的 Google 电子表格。

  2. Example. I have a named range Apples (address "Sheet10!B2:B"), which in use for data validation for plenty of sheet cells. The data range for Apples can be changed (in a script), e.g. to "Sheet10!D2:D".,请插入一张“Sheet10”并将样本值放入单元格“B2:B”和“D2:D”。

  3. 请将命名范围Sheet10!B2:B 设置为Apple

    2. 示例脚本。

    请将以下脚本复制并粘贴到电子表格的脚本编辑器中并保存脚本。还有,please enable Sheets API at Advanced Google services

    function myFunction() {
      const namedRangeName = "Apple"; // Please set the name of the named range.
    
      const ss = SpreadsheetApp.getActiveSpreadsheet();
      const sheet = ss.getSheetByName("Sheet10");
      const requests = [{ updateCells: { range: { sheetId: sheet.getSheetId(), startRowIndex: 0, endRowIndex: 1, startColumnIndex: 0, endColumnIndex: 1 }, rows: [{ values: [{ dataValidation: { condition: { values: [{ userEnteredValue: "=" + namedRangeName }], type: "ONE_OF_RANGE" }, showCustomUi: true } }] }], fields: "dataValidation" } }];
      Sheets.Spreadsheets.batchUpdate({ requests }, ss.getId());
    }
    
    • 在此请求中,命名范围的名称直接放入userEnteredValue

    3. 测试。

    当此脚本运行到上述示例电子表格时,将获得以下结果。

    当看到这个演示时,首先,您可以看到“Apple”的命名范围,其中包含单元格“B1:B1000”。运行脚本时,将数据验证放入命名范围为“Apple”的单元格“A1”中。在这种情况下,数据有效性的值表示“B1:B1000”。当名为范围“Apple”的范围从“B1:B1000”更改为“D1:D1000”并确认“A1”的数据验证时,发现值从“B1:B1000”更改为“D1” :D1000"。

    解决方法 2:

    此解决方法使用 Google 电子表格服务 (SpreadsheetApp)。在现阶段,谷歌电子表格服务(SpreadsheetApp)似乎无法直接达到你的目的。这已经在评论和TheMaster's answer 的讨论中提到。当您想实现这一点时,如何使用 OnChange 检查命名范围的范围是否已更改,如下解决方法 2?

    用法:

    1. 准备一份谷歌电子表格。

    1. 请创建一个新的 Google 电子表格。

    2. Example. I have a named range Apples (address "Sheet10!B2:B"), which in use for data validation for plenty of sheet cells. The data range for Apples can be changed (in a script), e.g. to "Sheet10!D2:D".,请插入一张“Sheet10”并将样本值放入单元格“B2:B”和“D2:D”。

    3. 请将命名范围Sheet10!B2:B 设置为Apple

      2. 示例脚本。

      请将以下脚本复制并粘贴到电子表格的脚本编辑器中并保存脚本。还有,please install OnChange trigger to the function onChange

      首先,请运行createDataValidation。这样,数据验证被放入“Sheet10”的单元格“A1”。在这种情况下,设置范围是从命名范围“Apple”中检索到的范围。所以,在这种情况下,范围是Sheet10!B2:B1000

      下一步,请将命名范围的范围从Sheet10!B2:B1000 更改为Sheet10!D2:D1000. By this, onChange` 函数由安装的 OnChange 触发器自动运行。由此,“A2”的数据有效性被更新。这样,数据验证的值就会改变。

      const namedRangeName = "Apple"; // Please set the name of the named range.
      const datavalidationCell = "Sheet10!A2"; // As a sample. data validation is put to this cell.
      
      function onChange(e) {
        if (e.changeType != "OTHER") return;
        const range = e.source.getRangeByName(namedRangeName);
        const a1Notation = `'${range.getSheet().getSheetName()}'!${range.getA1Notation()}`;
        const prop = PropertiesService.getScriptProperties();
        const previousRange = prop.getProperty("previousRange");
        if (previousRange != a1Notation) {
          const rule = SpreadsheetApp.newDataValidation().requireValueInRange(e.source.getRangeByName(namedRangeName)).setAllowInvalid(false).build();
          e.source.getRange(datavalidationCell).setDataValidation(rule);
        }
        prop.setProperty("previousRange", a1Notation);
      }
      
      // First, please run this function.
      function createDataValidation() {
        const ss = SpreadsheetApp.getActiveSpreadsheet();
        const rule = SpreadsheetApp.newDataValidation().requireValueInRange(ss.getRangeByName(namedRangeName)).setAllowInvalid(false).build();
        ss.getRange(datavalidationCell).setDataValidation(rule);
        const prop = PropertiesService.getScriptProperties();
        const range = ss.getRangeByName(namedRangeName);
        const a1Notation = `'${range.getSheet().getSheetName()}'!${range.getA1Notation()}`;
        prop.setProperty("previousRange", a1Notation);
      }
      

      参考:

【讨论】:

  • 感谢您筋疲力尽的回答。已经使用选项#1。刚打开这个问题,确认一下。当然,这就是我所需要的,但 #2 值得考虑。
  • 解决方法 1 存在问题。它不适用于 onEdit() 函数。
  • @Kirby Search 已安装触发器
  • @TheMaster,是的,它适用于已安装的触发器。谢谢
【解决方案2】:

目前,这似乎是不可能的。然而,这是一个已知问题。 +1 此功能请求,如果您希望实现此功能。

https://issuetracker.google.com/issues/143913035

跟踪器问题创建者的解决方法:

如果验证规则是通过 Sheets GUI 使用 NamedRange 手动创建的,则可以使用 Range.getDataValidations() 以编程方式复制它,然后用于以编程方式创建新的 DataValidations。以这种方式创建的 DataValidation 保持与 NamedRange 的连接,并且其行为类似于手动创建的对应项。这表明“使用”NamedRanges 数据验证规则的功能已经可以通过 Apps 脚本实现,但不能选择“创建”它们。

【讨论】:

  • 设置+1。感谢您提供此链接。
【解决方案3】:

使用 getRangeByName()

function lfunko() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getSheetByName("Sheet0");
  var cell = sh.getRange(1, 10);//location where datavalidation is applied
  var rule = SpreadsheetApp.newDataValidation().requireValueInRange(ss.getRangeByName("MyList")).build();
  cell.setDataValidation(rule);
}

【讨论】:

  • 不,它不起作用。数据验证得到实际范围,如Sheet2!A2:A10
  • 因此,答案不适用于该问题(也不适用于我的问题),请删除它。
  • 这个对我有用。您可能需要修改一些范围,但 getRangeByName() 会起作用。我们都应该是这里的程序员,所以你应该有能力自己修改代码。我不会删除它。
  • 我知道它是如何工作的。您的解决方案无法帮助设置命名为范围,我的意思是参考它。您的代码将设置命名范围MyList 的实际地址。但我需要设置=MyList。是否有意义?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-22
  • 1970-01-01
相关资源
最近更新 更多