当前位置: 首页 > 知识库问答 >
问题:

Google Sheets OneEdit(e)未捕获多个编辑

令狐献
2023-03-14

Google Sheets脚本编辑器中的onEdit(e)函数仅捕获单个单元格上的编辑。有没有办法让它捕获多个单元格上的编辑,例如,如果我将信息复制到20个单元格中,onEdit(e)是否可以识别20个单元格已被编辑,而不仅仅是第一个单元格?

我到处寻找解决这个问题的方法,但我找不到有人问这个问题的例子。

function recordChange(c){
  var range = c.range;
  var column = 8; //Column for change log
  var row = range.getRow();
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheets()[0];

  var oldRow = range.getRow();
  var oldColumn = range.getColumn();

  sheet.getRange(oldRow, oldColumn).setBackground("orange");

  var changeCell = sheet.getRange(row, column)
  changeCell.setValue(new Date())

  var testCell = sheet.getRange(2, 2)
  var test = range.getValues();
  var newT = test.map(function(x){ return x});
  testCell.setValue(newT)

}

function recordAction(c){

  var range = c.range;
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheets()[0];
  var row = range.getRow();

  for (var i = 1; i<9; i++){
    sheet.getRange(row, i).setBackground(null);
  }

}

//Main Function
function onEdit(e){

  var range = e.range;
  if (range.getRow() != 1){
    if (range.getColumn() != 9 && range.getColumn() != 8) {recordChange(e);} else {recordAction(e);}
  }
}

编辑单元格时,应在单独的列中添加日期,并以橙色突出显示单元格。但是,当我尝试编辑多个单元格时,它只会注册第一个单元格,因此作为在工作表上记录编辑的手段,它是非常无用的。

我假设有一种方法可以在数组中捕获多个编辑,但是我找不到任何明显的方法来实现这一点。

共有2个答案

吴飞语
2023-03-14

您需要在e.range对象中使用一些方法。

我在这里编写了一个小示例代码:

function onEdit(e) {

  var sheet = SpreadsheetApp.getActive().getActiveSheet();
  var changes = e.range.getValues();
  // +1 because of header row
  var lastRow = e.range.getLastRow() + 1;
  var date = new Date();
  var dateOfChange = date.toLocaleDateString() + " at " + date.toLocaleTimeString();
  var timeColumn = 4

  //sheet.getDataRange().getLastColumn()
  for (var i = 0; i < changes.length; i++) {
    var row = (lastRow - changes.length) + i;
    var timeCell = sheet.getRange(row, timeColumn);

    //this is quick and dirty but you will probably want to add more advanced data validation
    var validator = 0
    changes[i].forEach(function(x) {x.toString().length > 0 ? validator++ : null;})

    if (validator > 0 && e.range.getLastColumn() < timeColumn) {
      timeCell.setValue(dateOfChange);
    } else {
      timeCell.clear()
    }
  }
}

只需将时间列值更改为自己的timestamp列整数,并确保该列位于要将数据粘贴到的最后一列之后,否则需要编写更复杂的代码。

秦滨海
2023-03-14

基本上,您的代码没有达到预期的效果,因为您在以下行中得到的范围如下:

sheet.getRange(oldRow, oldColumn).setBackground("orange");

只有一个细胞。

使用getRange时,如果希望范围分别包含多个行或列,则应包含参数numRowsnumColumns(请参阅此处的更多信息)。

你的html" target="_blank">函数recdChange可以是这样的:

function recordChange(c) {
  var range = c.range;
  var ss = c.source; // This returns the spreadsheet from which the event was triggered
  var sheet = ss.getSheets()[0];
  var column = 8; //Column for change log
  var firstRow = range.getRow();
  var numRows = range.getNumRows();
  range.setBackground("orange");
  var dateCells = sheet.getRange(firstRow, column, numRows);
  dateCells.setValue(new Date())
}

请注意,您不需要获得一个新的范围来更改编辑单元格的背景颜色(您有这个确切的范围作为事件对象的属性,正如您在上面的代码中看到的)。

在第8列中设置版本日期时,确实需要使用getRange。如您所见,您需要提供该范围将具有的行数(对应于编辑范围的行数),并且您可以通过使用getNumRow获得该行数。

关于函数recdAction,如果我理解正确,您希望它在编辑相应行时删除第一列中的背景颜色。如果是这样的话,你的函数可以是这样的:

function recordAction(c) {
  var range = c.range;
  var ss = c.source;
  var sheet = ss.getSheets()[0];
  var row = range.getRow();
  var firstRow = range.getRow();
  var firstColumn = 1;
  var numRows = range.getNumRows();
  var numCols = 8;
  var editedRange = sheet.getRange(firstRow, firstColumn, numRows, numCols);
  editedRange.setBackground(null);
}

这里还需要使用getRange,因为要修改的范围与来自事件对象的范围不同。为此,您需要提供适当的参数。同样,您可以使用getNumRows获取行数。如果要删除前8列的背景,您已经知道这两个列参数(1和8)。

我希望这对你有所帮助。

 类似资料:
  • 问题内容: 在以下Java表达式中做什么? 问题答案: 它基本上意味着: 将“ SomeExceptionType”捕获到变量“ e”中,并保证在处理异常期间不会为“ e”分配其他异常。 通常,这太过分了,好像我将一个异常捕获到一个临时变量名称中(e仅对异常处理块有效),我不必太严厉地监管自己以至于不信任自己来分配其他变量(可能会创建)相同变量名的异常。 就是说,这个障碍可能是由一群不同想法的团队

  • 我想知道为什么在下面的代码中没有捕捉到异常: 函数的调用方式如下: 但我还是遇到了一个导致应用程序崩溃的异常: 我想说try/catch块会捕获异常,但唉。。。 什么原因导致异常没有被捕获?我想说线程并不重要,因为我使用try/get块来处理线程中的异常。 在Laalto的回答之后,我更新了代码,如下所示(对于那些感兴趣的人):

  • 问题内容: 谁能告诉我为什么这个类的输出是’xa’? 为什么不会捕获其他异常(RuntimeException和Exception)? 问题答案: 抛出的唯一异常是throw语句旁边的那个异常。另一个已创建但未抛出。无法同时引发两个异常。 通常,当在另一个异常的构造函数中传递异常时,将指示该异常是导致此异常的原因。但是,实际抛出的唯一异常是throw语句旁边的异常。 在这种情况下,NullPoin

  • 我想捕获多个事件,以防运行带有多个参数的方法。有没有可能在不编写自己的调度程序将我的事件粘合在一起的情况下实现这一点?

  • 问题内容: 为什么Java中的某些异常未被捕获?这是代码由于没有处理的异常而完全失败。(Java版本1.4)。 我得到一个 但这有效 我懂了 我以为捕获异常会捕获所有异常?如何捕获Java中的所有异常? 问题答案: 因为某些异常不是源自-例如和。 基本上,类型层次结构是: 只能抛出派生类,因此,如果您抓住,那实际上就可以抓住一切。 ,以及任何异常,从获得 其他 比那些源自数作为 检查的异常 -他们

  • 我对Java线程、Runnable等相当陌生。因此,我想知道为什么下面的代码没有捕获异常? 阅读有没有一种方法可以使Runnable的run()引发异常,我收集到: "...如果您的run()方法确实是Thread的目标,则抛出异常是没有意义的,因为它是不可观察的;抛出异常与不抛出异常(无)具有相同的效果。"(@erickson) 我应该检查Runnable.run()方法中的异常。 为什么会这样