独立于单元格使用 getLastRow

Use getLastRow independently of a cell

您好,我目前正在研究时间跟踪系统。使用以下代码,我可以跟踪值在单元格中的时间。这个时间记录在另一个工作表中,这是由 appendRow () 连续完成的。现在我遇到了问题,如果多个单元格具有一个值,我只会在最后一个单元格中获得日期 + 时间。无论单元格如何,它都插入最后一个值是否有效?

function onEdit(e) {
  addTimestamp(e);
}

function addTimestamp(e) {
  var ui = SpreadsheetApp.getUi();
  var ws = "Tabellenblatt2";
  var ss = e.source;
  var targetSheet = ss.getSheetByName("Tabellenblatt1");
  var range = targetSheet.getRange(3, 2, 1000, 1);
  var currentDate = new Date();
  if (e.source.getActiveSheet().getName() === ws && range != "") {
    var cell = ss.getActiveCell();
    var val = cell.getValue();
    if (val != "") {
      let rowToAdd = [val, "", currentDate, ""]
      ss.getSheetByName("Tabellenblatt1").appendRow(rowToAdd);
      ui.alert("Test2");
    } else {
      var sheet = ss.getSheetByName("Tabellenblatt1");
      sheet.getRange(sheet.getLastRow(), 4).setValue(currentDate);
      ui.alert("Test3");
    }
  }
}

为了更清楚地解释我的问题,两张脚本当前的图片运行。

如果姓名 1 (C11) 现在取消订阅,则不会在第一个工作表中为姓名 1 输入最后日期,而是为姓名 2 输入最后日期。

解释:

您可以使用 TextFinder class 搜索被删除的名称并找到特定名称的行。

  • 要查找旧值,您可以使用 e.oldValue,但这有一个限制。

解决方案:

function onEdit(e) {
  addTimestamp(e);
}

function addTimestamp(e) {
  var ui = SpreadsheetApp.getUi();
  var ws = "Tabellenblatt2";
  var ss = e.source;
  var targetSheet = ss.getSheetByName("Tabellenblatt1");
  var range = targetSheet.getRange(3, 2, 1000, 1);
  var currentDate = new Date();
  if (e.source.getActiveSheet().getName() === ws && range != "") {
    var val = e.range.getValue();
    if (val != "") {
      let rowToAdd = [val, "", currentDate, ""]
      ss.getSheetByName("Tabellenblatt1").appendRow(rowToAdd);
      ui.alert("Test2");
    } else {
      var sheet = ss.getSheetByName("Tabellenblatt1");
      var dataFinder = sheet.createTextFinder(e.oldValue);
      var nameRow = dataFinder.findAll()[0].getRow();
      sheet.getRange(nameRow, 4).setValue(currentDate);
      ui.alert("Test3");
    }
  }
}

限制:

如果您删除单元格的内容,则e.oldValue值未定义,因此上述解决方案将不起作用。

  • 要获得旧值,您需要用空字符串替换它。为此,左键单击要删除的单元格(名称),select 公式区域中的文本:

    然后按删除键删除文本。

最后但同样重要的是,该解决方案假定名称是唯一的。

问题:

由于,当直接删除单元格内容(而不是先选择它然后删除内容)时,e.oldValue不会填充,跟踪删除了哪个值变得麻烦了。

您需要找到一种方法来跟踪源 sheet (Tabellenblatt2) 中的哪些行对应于目标 sheet (Tabellenblatt1) 中的哪些行).

解决方案:

您可以为此使用 PropertiesService

  • 每次向源sheet写入新项目时,使用setProperty()存储一个属性,其key是当前编辑行的索引, value 是附加到目标 sheet.
  • 的行的索引
  • 每次从源 sheet 中删除一个项目时,使用 getProperty(key)(使用当前行索引)在目标 sheet 中检索相应的行索引(其中应写入第二个时间戳。
  • 将时间戳写入刚刚检索到的行。

代码示例:

function addTimestamp(e) {
  var ui = SpreadsheetApp.getUi();
  var ws = "Tabellenblatt2";
  var ss = e.source;
  var targetSheet = ss.getSheetByName("Tabellenblatt1");
  var range = targetSheet.getRange(3, 2, 1000, 1);
  var currentDate = new Date();
  var scriptProperties = PropertiesService.getScriptProperties();
  if (e.source.getActiveSheet().getName() === ws) {
    var cell = ss.getActiveCell();
    var val = cell.getValue();
    var sourceRowIndex = cell.getRow();
    if (val != "") {
      let rowToAdd = [val, "", currentDate, ""]
      targetSheet.appendRow(rowToAdd);
      scriptProperties.setProperty(sourceRowIndex, targetSheet.getLastRow());
    } else {
      var rowIndex = Number(scriptProperties.getProperty(sourceRowIndex));
      if (rowIndex) targetSheet.getRange(rowIndex, 4).setValue(currentDate);
    }
  }
}

注:

  • 重要提示:不会为以前存在的值存储属性。手动创建这些属性,或删除所有现有值并从头开始。
  • 在上面的示例中,script properties is used, but document properties and user properties 也可能是合适的,具体取决于您的当前情况。