我是 Google App 脚本的新手,除了基本的 HTML 之外,我对任何类型的脚本一无所知。然而,多亏了这个论坛,Google App 脚本并没有带来太大的挑战。
我是一名数据分析师,一直在研究低成本/开源方法,以模拟网站发布者的一些基本大数据优势。我的任务把我带到了谷歌脚本。自从我一周前了解它以来,我已经能够写一些了。
客观的挑战是:
我有一个使用 IMPORTHTML 函数动态提取大约 1000 行的电子表格。范围会随着源每天刷新而自动刷新,因此前一天的数据会丢失。这需要在存档表中备份数据,以便我可以分析所选时间范围内的历史数据。
我想自动复制行并将它们粘贴到存档表的顶部,就在范围标题的下方,这样我就不必按日期对存档进行排序,这可能是数据分析所必需的。我还需要检查重复的行并删除它们——以防万一。
首先,我编写了一个脚本,将复制的行附加到存档范围的最后一行下方。但是,按日期排序变得必要,因为我必须按特定日期范围(例如 14 天或 7 天)过滤数据以进行高级分析。所以我添加了一个用于排序的片段和另一个用于删除重复的片段。它工作得很好,但是,排序需要很长时间。考虑到每天都会添加数千个新行,这将继续花费更长的时间。我需要一个更智能的解决方案。
所以我开始编写一个脚本,它将 (1) 检测源范围中的行数 (2) 在存档表的标题下方插入尽可能多的行,以及 (3) 将复制的范围粘贴到新插入的行中。
我写完了,它运行得非常快;显然不需要排序。但是,我想知道,是否有一种方法可以让它更快、更智能且面向未来。请在下面找到代码。任何建议将不胜感激。
function myFunction() {
//1. Get data from source sheet of a spreadsheet whose id is known, we will also need the data range's last row number
var firstStep = SpreadsheetApp.openById("ID of Source Spreadsheet");
var ss = firstStep.getSheetByName("Sheet1");
ss.activate();
var myRange = ss.getRange(4, 2, ss.getLastRow() - 3, ss.getLastColumn());
var myData = myRange.getValues();
//'3' subtracted from last row data collector above as first three rows contain static data or blank row in my source sheet. Applied same technique at line 17 below as well. This totally depends on how you position the source range in the source sheet. For exaple, for a range starting at 1,1 on any sheet, no such subtraction woud be required.
var lastRow = myRange.getLastRow() - 3;
//2. Open archive spreadsheet, select the destination sheet, insert exact number of rows of source range and then paste copied range.
var secondStep = SpreadsheetApp.openById("ID of archive spreadsheet");
var newSS = secondStep.getSheetByName("dump1");
newSS.activate();
//2.a Insert Rows as in #lastrow in the new sheet, just below the header at Row 1
newSS.insertRowsBefore(2, lastRow)
//2.b Paste values
newSS.getRange(2, 1, myData.length, myData[0].length).setValues(myData);
//2.c Paste last row number of the copied range in another cell of the same sheet, optional step, just to be sure that last row determination process is right. You may remove this step if you like.
newSS.getRange(1, 15).setValue(lastRow);
/*
//3.a Optional: Script to remove duplicate rows in archive sheet. Will increase the script-run duration considerably.
var data = newSS.getDataRange().getValues();
var newData = new Array();
for(i in data){
var row = data[i];
var duplicate = false;
for(j in newData){
if(row.join() == newData[j].join()){
duplicate = true;
}
}
if(!duplicate){
newData.push(row);
}
}
newSS.clearContents();
newSS.getRange(1, 1, newData.length, newData[0].length).setValues(newData);
*/
}