Google apps script 控制电子表格的确定';getLastRow的最后一行
我的Google工作表中有一个脚本,当“工作历史”中的单元格AV被清除时,它会将一行数据从我的“工作历史”工作表复制到“工作日程”工作表。如果在“作业计划表”上有完全空行,这很好,但是目标页上的一些列包含公式和其他字符,这导致Google apps script 控制电子表格的确定';getLastRow的最后一行,google-apps-script,google-sheets,Google Apps Script,Google Sheets,我的Google工作表中有一个脚本,当“工作历史”中的单元格AV被清除时,它会将一行数据从我的“工作历史”工作表复制到“工作日程”工作表。如果在“作业计划表”上有完全空行,这很好,但是目标页上的一些列包含公式和其他字符,这导致 GETLASTROW()/将它们视为包含数据的行。 如何定义最后一行是什么?有没有办法让我只检查行中的一个单元格来确定它是否是最后一行?这是我的剧本: function onEdit(event) { var editedCell; var ss = Spread
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);
}
}
请看。它创建的脚本用于在第47列单元格中接收到
“X”
时将行从“作业计划”表移动到“作业历史记录”表,并在接收到“H”
时将行移动到“作业保留”表。这样做没有任何问题,但当我尝试从历史记录中“反转”此移动,并在清除第47列值时将工作表保留回明细表时,不会发生这种情况,因为“空”行中的某些单元格使用公式和一些字符格式化,因此,如果一行可以被视为空的,例如,如果列B中的单元格是空的,那么我认为它会工作。虽然您不能改变工作表#getLastRow
的操作方式,但您可以使用它来限制您的搜索空间-也就是说,不需要检查最后一行中的每一行(由getMaxRow()
给出的行)在找到一个非空单元格之前,可以从getLastRow()
行向上移动
您可以采取两种方法-一种是模拟按下Ctrl
+Up
,另一种是测试单元格
模拟按键/连续距离检测
这将使用该方法,然后沿相反方向偏移一次(因为它会选择下一个包含数据的边单元(或图纸的边))。它永远不会返回工作表中的第一行
// 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();
}
编辑:因为简单的触发器调用不会显示错误,所以您不会看到任何问题的可视通知-您必须检查Stackdriver上的脚本日志。我添加了一些越界Range
访问的健全性检查,即使在允许显示错误消息的上下文中运行,通常也会导致无声故障
价值测试
这将使用对和的批处理调用,然后再也不会使用该工作表。这里我们测试数组索引是否为空字符串(“”
),如果为空,则要求索引中也没有公式。getValues
和getFormulas
都会为“no value/formula”返回一个空字符串,并且由于公式可能会故意返回值”
,因此都需要进行检查
// 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
变量的更改。但是,由于您精确地定义了对<代码> LASSTROW 变量的控制,您必须考虑与比较和短路操作符相关的可能陷阱,并且数据存储在您的表中。连续范围检测从您的控件中删除所有这些内容,这是好是坏(取决于您的特定任务)。请注意,上面的两个示例都使用列索引,而不是列。“A”是0,“B”是1,以此类推。如果你想改变它,一定要这样做
示例用法,每当编辑任何工作表上的任何单元格时,将弹出一个toast,其中包含电子表格中第一个工作表的前3列中下一个空白单元格的行号
function onEdit(e) {
const all = e.source.getSheets();
var message;
try {
message = ["eh?", "bee", "see"].map(function (colName, i) {
return [
"Column '" + colName + "'",
"(index " + i + "):",
getTargetRowInColumn_(all[0], i)
].join(" ");
}).join("; ");
} catch (err) {
message = err.message;
}
e.source.toast(message, "Row of the next blank cell in first sheet", 60);
// Datestamp the next empty cell in column A of the first sheet.
var targetColumn = 1; // Column A
all[0].getRange(getTargetRowInColumn_(all[0], targetColumn - 1), targetColumn).setValue(new Date());
}
您希望检索每列最后一行的行号。我的理解正确吗?@Tanaike谢谢你的回复-我想检索某个特定列最后一行的行号。谢谢你的回复。如果特定列是常量,我可以问你吗?@Tanaike谢谢你问你是否可以问常量列-可以。@Tanaike你想知道什么?我仍在努力使这项工作,任何帮助是感激的!谢谢你的回复;我试过使用这两种方法,但一定是做错了什么。将其添加到当前脚本并使其运行而不是getLastRow的正确方法是什么?@J.Kubassek我添加了一个使用它的示例,并修复了第一个脚本的一些问题method@tehhowh好极了!第1(B)列实际上是正确的。那么在我的例子中,我将如何选择整个行范围?这不起作用:var target=targetSheet.getRange(targetSheet.getTargetRowinColumn_389;()+1,1,1,numColumns)@J.Kubassek
getTargetRowInColumn_(…)
不是属于Sheet
类的方法,因此不能像targetsheet.getTargetRowInColumn(…)
那样调用它。当有疑问时,请保持简单:var targetRow=getTargetRowInColumn_(targetSheet,targetColumn-1);targetSheet.getRange(targetRow,targetColumn,.
(其中targetColumn
基于1,函数假设基于0的输入)@tehhowh好的,我现在越来越近了,但我不明白targetColumn变量应该如何替换我以前的numColumns变量。