我正在尝试优化Google Apps脚本,该脚本以反向(从下到上)迭代电子表格中的行。脚本检查行中的第一个单元格(如果过去15天)并检查第12列中的字符串"是"如果两个条件都为真,则行从一个工作表移动到另一个工作表。
我遇到的麻烦是我超过规定的时间(6分钟),迭代2500行的所有数据,并期望增长得更大。
我确信这里已经多次回答了类似的问题,但鉴于我目前的编程技能水平,我无法应用我在这里找到的解决方案。非常感谢任何帮助。
这是工作表的格式:
1st column 12th column
+-----------+-----/ /-----+-------------+
| Date | | Refunded? |
+-----------+-----/ /-----+-------------+
| 8/29/2017 | | YES |
+-----------+-----/ /-----+-------------+
| 9/26/2017 | | NO |
+-----------+-----/ /-----+-------------+
这是剧本:
function myFunction() {
// get compare date (15 days from current date
var compareDate = new Date().getTime() - (15 * (1000 * 60 * 60 * 24));
// get sheets in spreadsheet
var target = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
var arr = [];
// get 1st sheet data
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var values = sheet.getDataRange().getValues();
var r = values.length;
// logic
while (r >= 1) {
if (values[r] && values[r][0].getTime() < compareDate && values[r][12].toLowerCase() == "yes" ) {
arr.push(values[r])
sheet.deleteRow(r + 1)
}
r--;
}
target.getRange(target.getLastRow() + 1, 1, arr.length, arr[0].length).setValues(arr.reverse())
}
如果我注释掉以下代码行&#34; sheet.deleteRow(r + 1)&#34;该脚本几乎立即完成,所以这似乎是减慢脚本执行速度的罪魁祸首。这个问题会有更有效的解决方案吗?
答案 0 :(得分:2)
不是通过迭代删除一行,而是使用deleteRows(rowPosition, howMany)在脚本末尾一次删除所有行。代码行可能类似于以下代码:
sheet.deleteRows(2, values.length - 1);
答案 1 :(得分:0)
深入了解Ruben关于一次删除多行的想法。在实际开始比较之前对数据进行排序是个好主意,这样所有最旧的“是”值都在底部。
要检查它,我设置了一张包含25000条记录的工作表:
function fillSheet() {
var yesNo = ['yes', 'no'];
var array = [];
for (var i = 0; i < 25000; i++) {
array[i] = [];
var rand = yesNo[Math.floor(Math.random() * yesNo.length)];
array[i].push(new Date(2016, 1, i), i, i + 1, i + 2, i + 3, i + 4, i + 5, i + 6, i + 7, i + 8, i + 9, i + 10, rand);
}
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
sheet.getRange(2, 1, array.length, array[0].length).setValues(array);
}
然后我修改了你的函数,以便它首先按照是/否和按日期对数据范围进行排序,然后进行检查(从这次的顶部开始)。
function myFunction() {
// get compare date (15 days from current date
var compareDate = new Date().getTime() - (15 * (1000 * 60 * 60 * 24));
// get sheets in spreadsheet
var target = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
var arr = [];
// get 1st sheet data
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var lastRow = sheet.getLastRow();
var lastCol = sheet.getLastColumn();
//sorting the range without the header row firstly by yes/no values and then by dates to make sure the oldest yes value are at the bottom and only then getting the values
sheet.getRange(2, 1, lastRow - 1, lastCol).sort([{column: 13, ascending: true}, {column: 1, ascending: false}]);
var values = sheet.getRange(2, 1, lastRow - 1, lastCol).getValues();
var r = 0;
var firstMatch = 0;
// logic
while (r < values.length) {
if (values[r] && values[r][0].getTime() < compareDate && values[r][12].toLowerCase() == "yes" ) {
//looking for the first match which will be used in deleting the rows
if (firstMatch === 0) {
firstMatch = r + 1;
}
else if (firstMatch > 0 && firstMatch > r) {
firstMatch = r + 1;
}
arr.push(values[r])
}
r++;
}
if (firstMatch > 0) {
target.getRange(target.getLastRow() + 1, 1, arr.length, arr[0].length).setValues(arr); //this will insert the array twice in my case anв i'm not sure why
sheet.deleteRows(firstMatch, values.length - firstMatch + 2); //+2 is empirical to make sure all rows are removed; not really sure where it comes from
sheet.getRange(2, 1, lastRow, lastCol).sort({column: 1, ascending: true});
}
}
这样,运行大约需要4秒钟。
但是有一些小问题:
它尝试将生成的数组两次插入到目标工作表中,但显然不应该。也许与我现在使用的Vivaldi浏览器有关,不知道。
经验的firstMatch,values.length - firstMatch + 2 - 再次不确定为什么它应该+2但是没有它它不会删除最后2行。
希望它无论如何都有帮助。