【问题标题】:Google Apps Script - Make onEdit() recognize setValue() changesGoogle Apps 脚本 - 使 onEdit() 识别 setValue() 更改
【发布时间】:2015-11-08 02:32:45
【问题描述】:

我有一个包含一些功能的电子表格。其中之一是 onEdit(event) 函数,它根据条件将一些值复制到其他工作表。这是代码(经过简化,但重要部分完好无损):

function onEdit(event) {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var s = event.source.getActiveSheet();
    var r = event.range;
    if(s.getName() === "Lista" && r.getColumn() === 9 && r.getValue() === "Posicionada") {
      var sheetname = s.getRange(r.getRow(),3).getValue();
      var columnRef = s.getRange(r.getRow(),4).getValue();
      var row = s.getRange(r.getRow(),5).getValue();
      var targetSheet = ss.getSheetByName("Mapa " + sheetname);
      var headers = targetSheet.getRange(1, 1, 1, targetSheet.getLastColumn());
      for (var i = 0; i < headers; i++) {
        if (headers[i] === columnRef) {
          break;
        }
      }
      var column;
      if (columnRef === "A1") {
        column = 2;
      }
      else if (columnRef === "A2") {
        column = 3;
      }
      else if (columnRef === "B1") {
        column = 4;
      }
      else if (columnRef === "B2") {
        column = 5;
      } 
      if (sheetname === "N2") {
        row = row - 30;
      }
      if (sheetname === "N3") {        
        column = column - 10;
        row = row - 42;
      }
      targetSheet.getRange(row,column).setValue(s.getRange(r.getRow(), 1, 1, 1).getValue()); 
    }
}

当我手动编辑单元格时,代码可以正常工作。但是,我有一个代码可以在用户按下侧边栏中的按钮时编辑单元格,代码如下:

function positionMU(){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var cell = ss.getActiveCell().activate();
  var cellLevel = cell.offset(0,2);
  var cellLetter = cell.offset(0,3);
  var cellNumber = cell.offset(0,4);
  var cellStatus = cell.offset(0,8);
  var dbq = "Posicionada";
  var fora = "Pendente de recebimento";  
  if (cellStatus.getValue() == "Aguardando posicionamento"){
      cellStatus.setValue(dbq);    //attention in this line  
  }
  else if (cellStatus.getValue() == "Aguardando saída"){
      cellStatus.setValue(fora);
      var cellExitDate = cell.offset(0,6);
      cellExitDate.setValue(getDate());
  }
}

如你所见,这个函数用setValue()改变单元格内容,但是,当我使用这个函数时,单元格的值改变了,但是onEdit()触发器不起作用。

如何让 onEdit() 触发器识别使用 setValue() 所做的更改?

【问题讨论】:

    标签: google-apps-script google-sheets


    【解决方案1】:

    你是对的。 onEdit() 仅在手动编辑范围时触发。正如here 所见,onEdit() 会在 user 更改值时触发。

    我通过使函数将值插入到我的 onEdit 响应的列中来测试该函数,但没有任何反应。包括我能想到的各种其他技术。最好的做法是建议将此作为对 App Script's Issue Tracker 的增强。

    但是,我通过编写另一个函数来使其工作,以便在脚本中的另一个函数对工作表进行更改时调用。这些是我写的测试函数:

    function addValues()
    {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getSheetByName("Sheet1");
      var range = sheet.getDataRange();
    
      var book = "Book";
      var cancel = "Cancel";
    
      var maxRow = range.getLastRow()+1;
    
      for(var i=0; i<4; i++)
      {
        if (i%2 == 0)
        {
          sheet.getRange(maxRow, 1).setValue(book);
          autoChanges(maxRow);
        }else{
          sheet.getRange(maxRow, 1).setValue(cancel);
          autoChanges(maxRow);
        }
    
        maxRow++;
      }
    }
    

    自动更改功能:

    function autoChanges(row)
    {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getSheetByName("Sheet1");
      var range = sheet.getDataRange();
      var data = range.getValues();
    
      var response = "";
    
      sheet.getRange(row, 2).protect();
    
      response = data[row-1][0];
    
      if (response == "Book")
      {
        sheet.getRange(row, 2).canEdit();
      }else{
        sheet.getRange(row, 2).setValue("--NA--");
      } 
    }
    

    不是最优雅的解决方案,但这似乎是您尝试做的唯一解决方法。

    【讨论】:

    • 我通过修改代码并在按钮的功能中实现来解决它。当按下按钮时,它会运行代码,所以它不需要被其他东西触发。
    【解决方案2】:

    调用 range.setValue() 没有触发 onEdit 事件有一些很好的原因,其中大多数与无限递归有关。事实上,你自己在 onEdit() 中调用了 setValue()。这将触发递归调用,据我所知,您无法处理基本情况,因此如果 setValue() 执行您想要的操作,您的代码将会爆炸。

    为什么不简单地将所有代码从事件处理程序中取出,并将其放入另一个函数中:

    function onEdit (e) {
      return handleEdits(e.range);
    }
    
    function handleEdits(r) {
      s = r.getSheet();
      ss = s.getParent();
      //the rest of your code should drop right in.
    }
    

    然后,在您的 autoChanges 函数中,继续调用 handleEdits,在您调用 setValue() 之后将其传递给适当的范围。

    【讨论】:

      【解决方案3】:

      如果你喜欢玩火,我个人也喜欢,你可以在修改后调用 onEdit(e) 函数。只需发送 e 对象调用和使用的任何对象即可。

      对我来说,我只需要添加:

          var e={};
          e.range=the range you are making a change to in the script;
          e.source = SpreadsheetApp.getActiveSpreadsheet();//or make sure you have the sheet for wherever you are setting the value
          e.value=whatever value you are setting
          e.oldValue=if you onEdit needs this, set it here
          //if you are using any of the other standard or special properties called by your onEdit...just add them before calling the function.
          onEdit(e);//call the function and give it what it needs.
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多