我的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列中的单元格为空,如果一行可以看作为空,那么我认为它会起作用。
答案 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#getValues
和Range#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