【问题标题】:Iterate a function through several rows in a Google Spreadsheet遍历 Google 电子表格中的多行函数
【发布时间】:2013-05-15 13:50:05
【问题描述】:

这是我写的脚本。每当编辑该行时,它都会在该行的末尾放置一个时间戳。

function setDate() {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getActiveSheet();
  //Get Active cell
      var mycell = ss.getActiveSelection();
      var cellcol = mycell.getColumn();
      var cellrow = mycell.getRow();
  //Check to see if column is A or B to trigger
      if (cellcol == EDITMECOLUMN)
      {
  //check for row to trigger
        if (cellrow == EDITMEROW)
        {
  //Find cell and set date in a defined cell
      var celldate = sheet.getRange(EDITMEROW, EDITMECOLUMN);
      celldate.setValue(new Date());
  //end set date
        }
      }
 }

它工作得很好,但是我怎样才能改变它以便它对每一行进行迭代,而不是我必须手动复制每一行的脚本?我有一个填充电子表格的表格,表格中每个主题的“最新”结果都放在报告电子表格中。我需要每一行的列时间戳,因为每一行代表表单中的一个主题,并且表单用户可以选择一次跳过几个星期的部分。

EDITMExx 片段只是我放置列或行# 的位置。

从 onEdit() 触发器调用该函数

【问题讨论】:

  • 需要更多信息才能提供合理的答案。什么是 EDITMEx?你怎么称呼这个setDate()?它是 onEdit 触发函数、自定义电子表格函数还是其他什么?您需要解决什么用例将时间戳放在多行上以进行一次编辑?请为这个问题添加更多信息。
  • 已添加更多信息,谢谢。
  • 我认为我们被“迭代”这个词吓跑了。您的意思是想要在编辑该行时在每一行上添加时间戳,还是想要在编辑任何行时在每一行上重复添加时间戳
  • 第一个,我想要每行在编辑时的时间戳:)

标签: javascript google-apps-script google-sheets google-apps


【解决方案1】:

创建一个循环遍历所有行的 for 循环(或任何类型的循环)。比如:

var numRows = sheet.getDataRange().getNumRows();
var data = sheet.getDataRange().getValues();
for(var i=0; i<numRows; i++){
    data[i][someColumnWhereYouWantDateSet].setValue(new Date());
}

【讨论】:

  • 我应该在我的函数中的什么地方放置for循环?我在 if 语句中尝试过,但没有奏效。
【解决方案2】:

由于您是从 onEdit 触发器调用此函数,因此您可以(应该!)利用生成的事件来知道将时间戳放在哪里。 (见Understanding Events。)

您声明“每当编辑该行时”都会放置一个时间戳。我假设时间戳列是固定的,如下所示:var TIMESTAMP = xx,其中 xx 是列号。

/**
 * onEdit function to place timestamp in a specified column
 * when an edit is made in a row.
 * 
 * @param {Event Object} event  Information about the event
 *                              that caused this function to
 *                              be triggered.
 */
function setDate(event) {
  var TIMESTAMP = 5;   // Column number for timestamp
  var HEADER_ROWS = 1; // # of header rows to skip monitoring

  var ss = event.source.getActiveSheet();
  var changedRange = event.source.getActiveRange();
  var changedRow = changedRange.getRow();

  //Logger.log("Edited range:" + changedRange.getA1Notation());
  if (changedRow > HEADER_ROWS) {
    ss.getRange(changedRow,TIMESTAMP).setValue(new Date());
  }
  // else do nothing
}

这是一个非常基本的 onEdit 函数,只有一个条件检查 - 它避免了为您的标题添加时间戳。您可以添加其他测试来监控列子集、特定工作表等。了解 Event 参数中传递了哪些对象将有助于您想象其他可能性。

警告:您可能会通过多种方式错过对电子表格的更改。请参阅this answer 了解更多信息。

如果您不熟悉 Apps 脚本触发器,请参阅 How can I test a trigger function in GAS? 了解调试提示。

【讨论】:

  • 对不起,我意识到我仍然有一个问题。当我直接编辑一个单元格时它工作得很好,但是假设单元格 B1 设置为 =D1。当我编辑单元格 D1 时,单元格 B1 已更改,但 B 行的日期未更新。有什么建议吗?
  • 啊,但是在那种情况下,您没有编辑 B 行,内容因公式而发生了变化 - one of the things that don't get picked up by onEdit triggers。如果这是您想要的行为,您可以做的一件事是维护每一行内容的两个副本 - 电子表格中的一个,以及第二个“旧”副本 - 然后在任何更改时,遍历所有行以查找内容更改并标记它们。
  • ...对于一个小表格,这会是好的,但即使是适度大小的数据也会使编辑非常缓慢。另一个想法是,您可以构建和维护公式关系图,并在每次更改时遍历该图以记录更新了哪些单元格。更少的数据密集型,但更复杂的计算。我想我的意思是您将无法依赖 onEdit 触发器来标记公式更改。
  • “您可以构建和维护公式关系图,并在每次更改时遍历它以记录哪些单元格已更新。”这个选项会是什么样子?是否类似于带有 if 语句的公式,以查看“历史”单元格是否等于“公式编辑单元格”,如果不是,它将设置当前日期的值?
  • 有点...我想象你会在整个电子表格上getFormulas(),并解析这些以确定单元格关系。由此,创建一个表格,告诉您“如果 D 改变,B 将改变”。然后,当 onEdit 告诉您 D 更改时,您也会知道时间戳 B。听起来很简单 - 但对于一般解决方案,这将非常非常棘手。
猜你喜欢
  • 2015-09-21
  • 2020-03-14
  • 2017-06-27
  • 1970-01-01
  • 2012-02-26
  • 2017-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多