我根据大量谷歌搜索和来自 this 的灵感创建了下面的代码邮政。我是编码新手,所以您必须原谅我的无知,因为我确信我的一些方法有点简陋。我希望你们能就如何改进我现有的代码和/或实现我在下面列出的修改提供一些提示。
我的代码的目的是在某些工作表中的某些单元格被修改时生成时间戳。
工作表 1:视频
触发时间戳的单元格:第 1、2、3、4、5、22、23、24 列,其中行 > 10
接收时间戳的单元格:如果为空则为 Y 列,否则为 Z 列
工作表 2:类别
触发时间戳的单元格:第 13、16、17 列,其中行 > 3
接收时间戳的单元格:T 列为空,否则为 U 列
我的代码
/*----------------------------Timestamps for Videos----------------------------*/
function onEditVideoTimestamps() {
//check to make sure on the right sheet
var s = SpreadsheetApp.getActiveSheet()
if (s.getName() == "Videos") {
//check to make sure edited row and column is within range
var cell = s.getActiveCell();
var rownbr = cell.getRow();
var colnbr = cell.getColumn();
var nbrcolumns = s.getMaxColumns();
var r = s.getRange(rownbr, 1, 1, nbrcolumns);
var rowArray = r.getValues();//now all your data for that row is in a two Dimensional array [[1,2,3,4,'My Data','etc']]
if (rownbr > 10 && (colnbr == 1 || colnbr == 2 || colnbr == 3 || colnbr == 4 || colnbr == 5 || colnbr == 22 || colnbr == 23 || colnbr == 24)) {
//is Y empty?
var checkY = s.getRange('Y' + rownbr.toString()).getValue()
if(checkY == '') {
//Yes
var time;
time = new Date();
time = Utilities.formatDate(time, "GMT-05:00", "MM/dd/yyyy HH:mm:ss");
//the column letter is where the timestamp will appear
SpreadsheetApp.getActiveSheet().getRange('Y' + rownbr.toString()).setValue(time);
} else {
//No
var time;
time = new Date();
time = Utilities.formatDate(time, "GMT-05:00", "MM/dd/yyyy HH:mm:ss");
//the column letter is where the timestamp will appear
SpreadsheetApp.getActiveSheet().getRange('Z' + rownbr.toString()).setValue(time);
}
}
/*----------------------------Timestamps for Categories/Albums----------------------------*/
} else {
//check to make sure on the right sheet
var s = SpreadsheetApp.getActiveSheet()
if (s.getName() == "Categories") {
//check to make sure edited row and column is within range
var cell = s.getActiveCell();
var rownbr = cell.getRow();
var colnbr = cell.getColumn();
var nbrcolumns = s.getMaxColumns();
var r = s.getRange(rownbr, 1, 1, nbrcolumns);
var rowArray = r.getValues();//now all your data for that row is in a two Dimensional array [[1,2,3,4,'My Data','etc']]
if (rownbr > 3 && (colnbr == 13 || colnbr == 16 || colnbr == 17)) {
//is T empty?
var checkT = s.getRange('T' + rownbr.toString()).getValue()
if(checkT == '') {
//Yes
var time;
time = new Date();
time = Utilities.formatDate(time, "GMT-05:00", "MM/dd/yyyy HH:mm:ss");
//the column letter is where the timestamp will appear
SpreadsheetApp.getActiveSheet().getRange('T' + rownbr.toString()).setValue(time);
} else {
//No
var time;
time = new Date();
time = Utilities.formatDate(time, "GMT-05:00", "MM/dd/yyyy HH:mm:ss");
//the column letter is where the timestamp will appear
SpreadsheetApp.getActiveSheet().getRange('U' + rownbr.toString()).setValue(time);
}
}
}
}
}
问题
此代码可能需要 40 秒以上才能运行。理想情况下,它不会超过 10 个,如果可能的话甚至更少,因为它是在 onEdit 上触发的。就目前而言,我很快就超过了每日 GAS 限额。
我想在我的脚本中添加以下逻辑:
视频
- 如果第 1 列更改为“已批准”,则会在初始时间戳列 (Y) 中生成一个新的时间戳,即使 Y 已经填充。第 1 列是一个状态字段,可以随时更改为“已批准”、“待定”、“已删除”或“已拒绝”。如果它更改为“已批准”,我希望 Y 获得时间戳,而不管其内容如何。否则,我当前的逻辑适用:如果填充 Y,则时间戳进入 Z(最后修改的时间戳)。
类别
我真的只想对这张表进行相同的更改,只是不同的单元格引用。
- 如果第 13 列更改为“已批准”,则无论是否已填充,都会在 T 列中生成新的时间戳。如果在该范围内进行了任何其他更改,并且 T 已经填充,则时间戳将放置在 U 中。
就像我说的,我是一个初学者,所以非常感谢任何帮助。让我知道是否需要澄清任何事情。谢谢
最佳答案
您的代码中有很多冗余。例如,在每个 bool 测试中,您初始化一个 time
变量。您应该执行此操作一次,然后在适当的情况下使用时间戳。
您可以实现的另一个即时更改是使用 onEdit
事件对象。这包含一个 Range
参数,您可以使用该参数查找事件的行和列,而无需多次调用电子表格,这应该会加快脚本的速度。
这是针对您当前需求的优化脚本。在测试中,它每次运行不到一秒。我没有添加额外的功能。您只需要再进行几个 bool 测试,因此您应该能够做到这一点。
function onEdit(e) {
var time = Utilities.formatDate(new Date(), "GMT-05:00", "MM/dd/yyyy HH:mm:ss");
var vidColNbr = [1,2,3,4,5,22,23,24];
var catColNbr = [13,16,17]
var sheet = e.range.getSheet();
//check to make sure on the right sheet
if (sheet.getName() == "Videos") {
//check to make sure edited row and column is within range
if((e.range.getRow() >= 10) && (vidColNbr.indexOf(e.range.getColumn()) > -1)) {
//is Y empty?
var checkY = sheet.getRange('Y' + e.range.getRow()).getValue();
if(checkY == '') {
//Yes
SpreadsheetApp.getActiveSheet().getRange('Y' + e.range.getRow()).setValue(time);
} else {
//No
SpreadsheetApp.getActiveSheet().getRange('Z' + e.range.getRow()).setValue(time);
}
}
/*----------------------------Timestamps for Categories/Albums----------------------------*/
} else {
//check to make sure on the right sheet
if (sheet.getName() == "Categories") {
//check to make sure edited row and column is within range
if ((e.range.getRow() >= 3) && (catColNbr.indexOf(e.range.getColumn()) > -1)) {
//is T empty?
var checkT = sheet.getRange('T' + e.range.getRow()).getValue()
if(checkT == '') {
SpreadsheetApp.getActiveSheet().getRange('T' + e.range.getRow()).setValue(time);
} else {
SpreadsheetApp.getActiveSheet().getRange('U' + e.range.getRow()).setValue(time);
}
}
}
}
}
The event Object reference很有帮助。您可以通过 onEdit
事件访问大多数方法和类,这确实可以加快执行速度。
关于javascript - 时间戳 onEdit 运行缓慢 - 如何优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48965893/