在Google表格中查找所有复选框

时间:2019-02-28 22:26:26

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

自从2018年将复选框添加到本机Google Sheets UI以来,开发人员一直希望以编程方式阅读它们或以某些方式对其进行处理,例如将其视为“单选按钮”,将其重置为“未选中”或设置他们“检查”。

如何最好地在给定的Google表格中找到复选框,以免在操纵其他单元格时避免意外修改其他单元格?

一种方法是检查工作表上的值并将任何true / false值视为复选框:

function getAllCheckboxes() {
  const wb = SpreadsheetApp.getActive();
  const checkboxes = [];

  wb.getSheets().forEach(function (sheet) {
    var rg = sheet.getDataRange();
    var values = rg.getValues();
    var sheetCheckBoxes = [];

    values.forEach(function (row, r) {
      row.forEach(function (val, c) {
        // Checkbox values are stored as `false` (unchecked) and `true` (checked)
        if (val === false || val === true) {
          sheetCheckBoxes.push({
            rowIndex: r,
            colIndex: c,
            value: val,
            r1c1: "R" + (r+1) + "C" + (c+1)
          });
        }
      });
    });
    if (sheetCheckBoxes.length) {
      checkboxes.push({
        name: sheet.getName(),
        sheetId: sheet.getSheetId(),
        boxes: sheetCheckBoxes
      });
    }
  });

  return checkboxes; // An array of objects describing a sheet and its checkboxes.
}

但是,这并非在所有用例中都有效:该单元格可能显示为文字TRUEFALSE,而不是复选框。上面的代码将其视为一个,因为它具有相同的值。

2 个答案:

答案 0 :(得分:3)

复选框在Google表格应用程序中作为数据验证的a specific type实施,并且可以具有用户指定的“选中”和“未选中”值-不仅仅是{{1 }}和true。因此,要正确地找到单元格,我们必须check the data validation type应用于每个单元格。可以通过两种方式在Google Apps脚本中完成此操作:使用电子表格服务或使用Google Sheets API(v4)。

电子表格服务

电子表格服务方法不需要您启用任何其他符号标识符或启用Google Cloud Platform中的任何API。但是,在某些情况下,它可能不如Sheets API快。

该脚本与问题中的脚本非常相似,不同之处在于我们必须迭代2D数据验证规则数组,而不是值数组。 (如果不需要复选框的当前值,则可以跳过获取false数组。)

values

Sheets API

要使用Sheets API,必须首先在应用程序的Google Cloud Platform项目中启用它。对于Apps Script项目,将自动创建其中之一,并可以通过Apps Script编辑器中的“资源”菜单进行访问。如果不确定如何激活the Advanced Services guide符号和Sheets REST API,请查阅Sheets

function getAllCheckboxesViaService() { const wb = SpreadsheetApp.getActive(); const checkboxes = []; // The specific type of Data Validation that demarcates a UI checkbox. const CB = SpreadsheetApp.DataValidationCriteria.CHECKBOX; wb.getSheets().forEach(function (sheet) { var rg = sheet.getDataRange(); var values = rg.getValues(); var sheetCheckBoxes = []; var dvRules = rg.getDataValidations(); dvRules.forEach(function (row, r) { // iterate data validations instead of values row.forEach(function (rule, c) { if (rule && rule.getCriteriaType() === CB) { sheetCheckBoxes.push({ rowIndex: r, colIndex: c, r1c1: "R" + (r+1) + "C" + (c+1), choices: (rule.getCriteriaValues().length ? rule.getCriteriaValues() : [true, false]), value: values[r][c], }); } }); }); if (sheetCheckBoxes.length) { checkboxes.push({ name: sheet.getName(), sheetId: sheet.getSheetId(), boxes: sheetCheckBoxes }); } }); return checkboxes; } 部分响应掩码包括fields时,通过端点spreadsheets.get检索

数据验证。通常,仅此特定字段是无用的-了解关联的工作表的标题,ID以及复选框的值也很有用,因此sheets/data/rowData/values/dataValidation的规范更有用。 (您可以在Google APIs Explorer中尝试使用有效的域掩码)

Sheets API中的相关数据验证类型为BOOLEAN。我们可以通过API查询一次所需的电子表格,然后在本地检查结果响应数据,以确定哪些单元格具有复选框,哪些没有复选框:

fields

有效地使用复选框位置

一旦知道电子表格中的哪些单元格对应于复选框-哪些值显示为“已选中”还是“未选中”,就很自然地希望读取或修改它们。盲目地写sheets(data(rowData(values(dataValidation,effectiveValue/boolValue))),properties(sheetId,title))或{{1} }到复选框单元格仅对默认(布尔)复选框有效。要处理所有可能的用户创建的复选框,必须编写表示“ checked”或“ unchecked”的适当值。(以上脚本将这些值存储在{ {1}}属性。)

最容易在Apps脚本中使用RangeList类完成值的重置,尽管Sheets API端点spreadsheets.values.batchUpdate可以实现类似的结果(是的,Sheets API {{3}可以接受R1C1表示法) }规范),尽管使用了一些样板来构建请求。 API方法能够发出单个请求,而Spreadsheet Service只能为每个工作表实例化一个function getAllCheckboxesViaAPI() { const wbId = SpreadsheetApp.getActive().getId(); const fields = "sheets(data/rowData/values(" + "dataValidation(condition(type,values/userEnteredValue))," + "effectiveValue(boolValue,numberValue,stringValue))," + "properties(sheetId,title))"; const resp = Sheets.Spreadsheets.get(wbId, {fields: fields}); // Enable before use... if (!resp.sheets || !resp.sheets.length) return []; const checkboxes = []; resp.sheets.forEach(function (sheetObj) { if (!sheetObj.data || !sheetObj.data.length) return; var sheetCheckBoxes = []; sheetObj.data.forEach(function (gridRange) { gridRange.rowData.forEach(function (row, r) { row.values.forEach(function (cell, c) { if (cell.dataValidation && cell.dataValidation.condition // Require the cell to be displayed as a Checkbox. && cell.dataValidation.condition.type === "BOOLEAN") { sheetCheckBoxes.push({ rowIndex: r, colIndex: c, r1c1: "R" + (r+1) + "C" + (c+1), choices: (cell.dataValidation.condition.values ? cell.dataValidation.condition.values : [true, false]), value: cell.effectiveValue // object, e.g. {booleanValue: false} or {stringValue: "Yes"} }); } }); }); }); checkboxes.push({ name: sheetObj.properties.title, sheetId: sheetObj.properties.sheetId, boxes: sheetCheckBoxes }); }); return checkboxes; } (并且您需要为每种类型的复选框创建1个true,以避免编写错误值(例如,当“未经检查的”值应为false时为choices)。

RangeList

要从RangeList构建API请求,可以满足以下条件:

false

答案 1 :(得分:0)

这似乎可行:

function testForCheckBoxes() {
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getActiveSheet();
  var rg=sh.getDataRange();
  var vA=rg.getDataValidations();
  var cbA=[];
  for(var i=0;i<vA.length;i++) {
    for(var j=0;j<vA[i].length;j++) {
      var rule=vA[i][j];
      if(rule!=null) {
        var criteria = rule.getCriteriaType();
        if(criteria == SpreadsheetApp.DataValidationCriteria.CHECKBOX) {
          cbA.push(Utilities.formatString('%s', sh.getRange(i+1,j+1).getA1Notation()));
        }
      }
    }
  }
  var ui=HtmlService.createHtmlOutput(cbA.join(', '));
  SpreadsheetApp.getUi().showModelessDialog(ui, 'Check Boxes in A1Notation')
}