通过getLastRow

时间:2018-06-15 11:21:52

标签: google-apps-script google-sheets

我的Google表格中有一个脚本可以复制我的工作历史记录中的一行数据"表"工作时间表"表格中的单元格AV在"作业历史记录"被清除了。如果" Job Schedule"中有完全空的行,这可以正常工作。 sheet,但目标工作表上的某些列包含公式和其他字符,这导致getLastRow()将它们视为包含数据的行。

如何定义最后一行是什么?有没有办法getLastRow()只检查行中的一个单元格,以确定它是否是最后一行?这是我的剧本:

function onEdit(event) {
  var editedCell;
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var s = event.source.getActiveSheet();
  var r = event.source.getActiveRange();

  if(s.getName() == "Job History" && r.getColumn() == 47 && r.getValue() == "") {
    var row = r.getRow();
    var numColumns = s.getLastColumn();
    var targetSheet = ss.getSheetByName("Job Schedule");
    var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1, 1, numColumns);
    var source = s.getRange(row, 1, 1, numColumns);
    var notes = source.getNotes();
    source.copyTo((target), {contentsOnly:true});
    target.setNotes(notes);
    s.deleteRow(row);
  }
}

请参阅this example。它创建的脚本是为了从" Job Schedule"中移动行。表单"工作历史"在第47列单元格中收到"X"时的工作表,以及"工作持有"收到"H"时的工作表。这一直没有问题,但是当我试图“反转”时当它们的第47列值被清除时,从历史记录和保持表单移回到计划表单,这不会发生,因为“空白”中的某些单元格会被清空。行使用公式和一些字符进行格式化,因此如果B列中的单元格为空,如果一行可以看作为空,那么我认为它会起作用。

1 个答案:

答案 0 :(得分:0)

虽然您无法更改Sheet#getLastRow的运行方式,但可以使用它来限制搜索空间-即,无需检查最后一行的可能行({{1 }}),直到找到一个非空单元格为止,您可以从getMaxRow()行开始。

您可以采用两种方法-一种模拟按下getLastRow() + Ctrl,另一种测试单元格。

模拟按键/连续范围检测

这使用getNextDataCell方法,然后在相反的方向偏移一次(因为它选择了带有数据的下一个边缘单元(或图纸的边缘))。它永远不会返回工作表中的第一行。

Up

edit:由于简单的触发器调用不会显示错误,因此您不会看到任何问题的可视通知-您必须在Stackdriver上检查脚本的日志。我为越界访问// Will throw if called on an expanding arrayformula column. Adds a new row if needed. function getTargetRowInColumn_(sheet, columnIndex) { const maxRow = sheet.getMaxRows(); // If the last row is the max row (e.g. an expanding arrayformula is present in a column), // then accessing getLastRow() + 1 will silently fail. var r = sheet.getRange(maxRow, columnIndex + 1);; if (sheet.getLastRow() === maxRow && (r.getValue() !== "" || r.getFormula())) { // We want either the next row (which we will create), or there is a formula // that will add values to this column - user error for accessing this column. sheet.insertRowsAfter(maxRow, 1); SpreadsheetApp.flush(); r = r.offset(1, 0); if (r.getValue() !== "" || r.getFormula()) throw new RangeError("target column index '" + columnIndex + "' has expanding formula"); return ++maxRow; // Same output as r.getRow(), but faster. } r = r.getNextDataCell(SpreadsheetApp.Direction.UP); do { r = r.offset(1, 0); } while (r.getValue()); return r.getRow(); } 添加了一些健全性检查,即使在允许显示错误消息的上下文中运行,通常也会导致无提示失败。

价值测试

这使用对Range#getValuesRange#getFormulas的批量调用,然后不再使用该工作表。在这里,我们测试数组索引是否为空字符串(Range),如果是,则要求索引中也没有公式。 ""getValues都返回一个空字符串,表示“无值/公式”,并且由于公式可能有意返回值getFormulas,因此都需要检查。

""

价值测试方法将为您提供最大的灵活性,因为您可以准确定义控制// Does not throw if called on an expanding arrayformula column. Does not add a new row. function getTargetRowInColumn_(sheet, columnIndex) { var lastRow = sheet.getLastRow(); const r = sheet.getRange(1, columnIndex + 1, lastRow, 1); const values = r.getValues(); const formulas = r.getFormulas(); do { --lastRow; // isEmptyString = values[lastRow][0] === ""; // isNotAFormula = !formulas[lastRow][0]; // isEmptyStringValue && isNotAFormula } while (values[lastRow][0] === "" && !formulas[lastRow][0]); // lastRow now points to an array index that is occupied by either a formula or value. // += 1 converts from array index to Range row, and then += 1 again // (since we want the next row, which is empty). lastRow += 2; return lastRow; } 变量更改的因素。但是,由于您确切地定义了控制lastRow变量更改的因素,因此必须考虑与比较和短路运算符相关的可能的陷阱,并将数据存储在工作表中。连续范围检测会将所有这些都从您的控件中删除,无论这是好是坏(取决于您的特定任务)。请注意,以上两个示例都使用列索引,而不是列。 “ A”为0,“ B”为1,依此类推。如果要通过任何方式更改它,请执行此操作。


一个用法示例,每当编辑任何工作表上的任何单元格时,都会在电子表格的第一个工作表的前3列中弹出一个包含下一个空白单元格的行号的吐司。

lastRow