如何在 Google 电子表格中以编程方式(在 Google Apps 脚本中)设置数据验证的命名范围?

Kir*_*rby 5 google-sheets google-apps-script google-sheets-api

使用案例

例子。我有一个命名范围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()
        );
Run Code Online (Sandbox Code Playgroud)

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

有解决方法吗?

UPD1 -Spreadsheet.getRangeByName()不起作用

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

UPD2 到目前为止,GAS 还没有办法做到这一点

正如@TheMaster 所言,目前这是不可能的。

请为帖子设置+1:

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

Tan*_*ike 3

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

解决方法1:

此解决方法使用 Sheets API。

用法:

1. 准备一个 Google 电子表格。

  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:BApple

2. 示例脚本。

请将以下脚本复制并粘贴到电子表格的脚本编辑器中并保存脚本。并且,请在高级 Google 服务中启用 Sheets API

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());
}
Run Code Online (Sandbox Code Playgroud)
  • 在此请求中,命名范围的名称直接放入userEnteredValue

3. 测试。

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

在此输入图像描述

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

解决方法2:

此解决方法使用 Google 电子表格服务 (SpreadsheetApp)。现阶段,Google Spreadsheet服务(SpreadsheetApp)似乎无法直接实现你的目标。这一点在评论的讨论和TheMaster的回答中已经提到过。当您想实现此目的时,如何使用 OnChange 检查指定范围的范围是否已更改,如以下解决方法 2 所示?

用法:

1. 准备一个 Google 电子表格。

  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:BApple

2. 示例脚本。

请将以下脚本复制并粘贴到电子表格的脚本编辑器中并保存脚本。并且,请为该函数安装 OnChange 触发器onChange

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

下一步,请将命名范围从Sheet10!B2:B1000Sheet10!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);
}
Run Code Online (Sandbox Code Playgroud)

参考: