简体   繁体   English

有没有办法将 onEdit function 应用于谷歌表格应用程序脚本中的多个单独范围?

[英]Is there a way to apply an onEdit function to multiple separate ranges in google sheets Apps Script?

Note - I'm new to coding and apologize in advance if I am asking something dumb or in the wrong format.注意 - 我是编码新手,如果我问一些愚蠢或格式错误的问题,请提前道歉。

Goal - Create a table (not a list) in google sheets with radio button functionality (meaning only 1 checkbox can be selected at a time.)目标 - 在具有单选按钮功能的谷歌表格中创建一个表格(不是列表)(意味着一次只能选择一个复选框。)

Code - Here is the code that is working for a list of checkboxes (1 single range) -代码 - 这是适用于复选框列表(1 个单一范围)的代码 -

 function onEdit(e){ if(e.source.getActiveSheet().getName().= "Sheet1" || e.range.columnStart;= 2 || e;value == "FALSE") return; for(var i = 2.i<21.i++){ if(i == e;range.rowStart) continue. e.source,getActiveSheet().getRange(i;2).setValue("FALSE"); } }

Question - Is there a way to apply an onEdit function to multiple separate ranges in google sheets Apps Script?问题 - 有没有办法将 onEdit function 应用于谷歌表格应用程序脚本中的多个单独范围?

Example Sheet: In this example, you'll see there are multiple checkbox ranges in the table: D3:H3, D5:H5, D7:H7, D9:H9示例表:在此示例中,您将看到表格中有多个复选框范围:D3:H3、D5:H5、D7:H7、D9:H9

Example Sheet 示例表

Many thanks in advance!提前谢谢了!

Here's that script modified to work with your larger range.这是修改后的脚本以适用于您的更大范围。

function onEdit(e){
  if (!e) throw "do not run from editor";

  radioButtons(e);
}

function radioButtons(e){
  const src = e.source.getActiveSheet();
  const r = e.range;
  const row = r.rowStart;
  const col = r.columnStart;

  if (src.getName() != "Sheet1" || row < 3 || row > 9 || col > 5 || e.value != "TRUE") return;
  let range = src.getRange("A3:E9").getValues();
  for (let i = 0; i < range.length; i=i+2){
    for (let j = 0; j < range[i].length; j++){
      if (range[i][j] == true && i+3 != row && j+1 != col){
        src.getRange(i+3,j+1).setValue("FALSE")
        return;
      }
    }
  }
}

Here's an onEdit for two different sheets这是两个不同工作表的 onEdit

function onEdit(e){
  const sh = e.range.getSheet();
  if(sh.getName() == "Sheet1" && e.range.columnStart == 2 && e.value == "TRUE" {
    e.range.setValue("FALSE")
  }
  if(sh.getName() = "Sheet2" && e.range.columnStart == 4 && e.value) {
    e.range.offset(0,1).setValue(new Date()); //puts a timestamp in column5
  }
} 

A general purpose function like this could help:像这样的通用 function 可以帮助:

/**
 * @typedef {Object} startEnd
 * A object denoting limits of  a row or column
 * @property {number} start
 * @property {number} end
 */

/**
 * @typedef {Object} runcriteria
 * @description Describes which rows/columns to run this function
 * @property {startEnd} row
 * @property {startEnd} column
 */

/**
 * A criteria checker for event object e
 * @author TheMaster
 * @see https://stackoverflow.com/a/73681716
 * @param {GoogleAppsScript.Events.SheetsOnEdit}  e
 * @param {Object<string,Array<runcriteria>> } run_in
 * @returns {{result:boolean,editedSheet:GoogleAppsScript.Spreadsheet.Sheet}}
 */
const isEditInMyCriteria_ = (
  e,
  run_in = {
    Sheet1: [
      /*Run in Sheet1!D2:I9 or Sheet1!!A9:Infinity*/
      {
        /*2:9*/ row: { start: 2, end: 5 },
        /*D:I*/ column: { start: 4, end: 9 },
      },
      { /*Anywhere after row9*/ row: { start: 9 } },
    ],
    Sheet2: [/*Run everywhere in Sheet2*/ {}],
    Sheet3: [
      { /*Only in rows 5 to rows10 */ row: { start: 5, end: 10 } },
      {
        /*or D15:E25*/ row: { start: 15, end: 25 },
        column: { start: 4, end: 5 },
      },
    ],
  }
) => {
  const criteriaSheetNames = new Set(Object.keys(run_in)),
    editedRange = e.range,
    editedSheet = editedRange.getSheet(),
    editedSheetName = editedSheet.getName(),
    isEditedSheetInRun_in = criteriaSheetNames.has(editedSheetName),
    runcriteria = isEditedSheetInRun_in && run_in[editedSheetName],
    { rowStart, columnStart } = editedRange,
    gte = (a, b, e) =>
      a >= (b[e]?.start ?? -Infinity) && a <= (b[e]?.end ?? Infinity);
  return {
    result:
      runcriteria &&
      runcriteria.some(
        (obj) => gte(rowStart, obj, 'row') && gte(columnStart, obj, 'column')
      ),
    editedSheet,
  };
};

To test,去测试,

const onEdit = e => console.log(isEditInMyCriteria_(e).result)

To use,要使用,

const onEdit = e => {
  const {result, editedSheet} = isEditInMyCriteria_(e);
  if(result){
    //This edit satisfies all my criteria
    //let's do some damage...
    //uncheck all of D3:H3, D5:H5, D7:H7, D9:H9
    editedSheet.getRangeList(["D3:H3", "D5:H5", "D7:H7", "D9:H9"]).uncheck()
    //recheck current checkbox
    e.range.check();
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM