在 Google 脚本中反转复选框的最佳方法?

The most optimal way to invert checkboxes in Google Script?

因为 Google 脚本不支持单选按钮,我尝试创建一个解决方法。虽然我已经学习了 Python 的基础知识,但我是 Javascript/Google Sctipt 的新手。我终于让我的代码工作了,但我觉得对于这样一个简单的任务来说结果太笨拙了。如何优化?

这是工作示例:https://docs.google.com/spreadsheets/d/1bcMj3Yxewo4ZUgnhg0z46NyqJYBfxm-6ocvmEHLwtWE/edit?usp=sharing

这是我的代码:

const ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  
function onEdit(e) {
  var invertedRange = { // C4:D5 is the range to follow
    top : 4,
    bottom : 5,
    left : 3,
    right : 4
  }
  var thisRow = e.range.getRow();
  var thisCol = e.range.getColumn();
 
  // Invert the checkboxes in the range
  if (thisRow <= invertedRange.bottom && thisRow >= invertedRange.top) {
    if (thisCol <= invertedRange.right && thisCol >= invertedRange.left) {
      var changeArray = ss.getRange(invertedRange.top, invertedRange.left, 2, 2).getValues();
      var invertedArray = [];
      var rPos = 0; // first row of the 2x2 matrix
      var valueToAdd = true;
      for (var readRow = invertedRange.top; readRow <= invertedRange.bottom; readRow = readRow + 1) {
        var cPos = 0; // first column of the 2x2 matrix
        var invertedPart = [];
        for (var readCol = invertedRange.left; readCol <= invertedRange.right; readCol = readCol + 1) {
          if (thisRow == readRow && thisCol == readCol) {
            var valueToAdd = changeArray[rPos][cPos]; // do not invert the checkbox that was already manually changed by user edit
          } else {
            var valueToAdd = !changeArray[rPos][cPos]; // invert all other checkboxes in the range
          }
          var invertedPart = invertedPart.concat(valueToAdd); // create an array from a pair of checkbox values
          cPos = cPos + 1;
        }
        invertedArray[rPos]=invertedPart; // add the pairs into an array
        rPos = rPos + 1;
      }
      ss.getRange(invertedRange.top, invertedRange.left, 2, 2).setValues(invertedArray); // set the chackbox values
    } return;
  }
}

提供复选框单选组行为

此 onEdit 函数为任何范围提供单选按钮组行为。您需要通过设置 cbrg 的值和 selecting 您希望组在行或列中的方向来输入 A1 表示法中的范围。单击它会将您 select 所在行或列中的所有其他单元格设置为 true。它不支持 true 或 false 以外的验证值。

 function onEdit(e) {
  //e.source.toast('Entry');
  const sh = e.range.getSheet();
  const group = 'col';//change which direction that you wish to group in
  const cbrg = "C4:D5";//specifying the range the starting column and row must be greater than one. 
  const rg = sh.getRange(cbrg);
  const w = rg.getWidth();
  const h = rg.getHeight();
  const cs = rg.getColumn();
  const ce = cs + w - 1;
  const rs = rg.getRow();
  const re = rs + h - 1;
  //console.log('rs:%s,re:%s,cs:%s,ce:%s', rs, re, cs, ce);
  if (sh.getName() == 'Sheet1' && e.range.columnStart > cs - 1 && e.range.columnStart < ce + 1 && e.range.rowStart > rs - 1 && e.range.rowStart < re + 1 && e.value == 'TRUE') {
    if (group == 'row') {
      //e.source.toast('row');
      let cA = new Array(w).fill(false);
      cA[e.range.columnStart - cs] = true;
      sh.getRange(e.range.rowStart, cs, 1, cA.length).setValues([cA]);
    }
    if (group == 'col') {
      //e.source.toast('col');
      let idx = e.range.rowStart - rs;
      let cA = [];
      for (let i = 0; i < h; i++) {
        if (i == idx) cA.push([true]);
        else cA.push([false]);
      }
      sh.getRange(rs, e.range.columnStart, cA.length, 1).setValues(cA);
    }
  }
}

下面的执行速度稍快,只需设置顶行 (trow)、底行 (brow)、左列 (lcol)、右列 (rcol) 和单选组方向即可 'row' 或 'col'。它需要的函数调用少得多,但耗时。

function onEdit(e) {
  //e.source.toast('Entry');
  const sh = e.range.getSheet();
  const trow=4;//top row
  const brow=5;//bottom row
  const lcol=3;//left column
  const rcol=4;//right column
  const group = 'row';//change which direction that you wish to group in
  //console.log('trow:%s,brow:%s,lcol:%s,rcol:%s', trow, brow, lcol, rcol);
  if (sh.getName() == 'Sheet1' && e.range.columnStart >= lcol && e.range.columnStart <= rcol && e.range.rowStart >= trow && e.range.rowStart <= brow && e.value == 'TRUE') {
    if (group == 'row') {
      //e.source.toast('row');
      let cA = new Array(rcol-lcol+1).fill(false);
      cA[e.range.columnStart - lcol] = true;
      sh.getRange(e.range.rowStart, lcol, 1, cA.length).setValues([cA]);
    }
    if (group == 'col') {
      //e.source.toast('col');
      let idx = e.range.rowStart - trow;
      let cA = [];
      for (let i = 0; i < brow-trow+1; i++) {
        if (i == idx) cA.push([true]);
        else cA.push([false]);
      }
      sh.getRange(trow, e.range.columnStart, cA.length, 1).setValues(cA);
    }
  }
}

动画:

我更改了动画的范围,以便将其放入尽可能小的图像中。