Google表格onEdit(e)无法捕获多个编辑

时间:2019-10-28 14:13:56

标签: google-apps-script google-sheets

Google表格脚本编辑器中的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 个答案:

答案 0 :(得分:0)

您需要使用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()
    }
  }
}

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

下面是在简单的电子表格上运行的图片: Forgot to add any foos or bars

答案 1 :(得分:0)

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

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

只有一个单元格。

使用getRange时,如果希望范围分别包含多个行或一列,则应包括参数numRowsnumColumns(请参阅更多信息{{3} }。

您的函数recordChange可能像这样:

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())
}

请注意,您不需要获取新的范围即可更改已编辑单元格的背景颜色(如上面的代码所示,您可以将此精确范围作为here的属性)

在第8列中设置版本日期时,您确实需要使用getRange。如您所见,您需要提供范围将具有的行数(与已编辑范围的行数相对应),然后使用event object获得此行数。

关于功能recordAction,如果我对您的理解正确,那么您希望它在编辑各行后删除第一列中的背景色。如果是这样,您的功能可能如下所示:

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)。

希望对您有帮助。