0

我是 Google App 脚本的新手,除了基本的 HTML 之外,我对任何类型的脚本一无所知。然而,多亏了这个论坛,Google App 脚本并没有带来太大的挑战。

我是一名数据分析师,一直在研究低成本/开源方法,以模拟网站发布者的一些基本大数据优势。我的任务把我带到了谷歌脚本。自从我一周前了解它以来,我已经能够写一些了。

客观的挑战是:

  1. 我有一个使用 IMPORTHTML 函数动态提取大约 1000 行的电子表格。范围会随着源每天刷新而自动刷新,因此前一天的数据会丢失。这需要在存档表中备份数据,以便我可以分析所选时间范围内的历史数据。

  2. 我想自动复制行并将它们粘贴到存档表的顶部,就在范围标题的下方,这样我就不必按日期对存档进行排序,这可能是数据分析所必需的。我还需要检查重复的行并删除它们——以防万一。

首先,我编写了一个脚本,将复制的行附加到存档范围的最后一行下方。但是,按日期排序变得必要,因为我必须按特定日期范围(例如 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);
   
   */

}

4

1 回答 1

0

您可以在 Google 应用程序脚本本身中完成的任何操作都比进行需要从 Google 的服务器或外部服务器获取数据的调用(例如对电子表格、文档、站点等的请求)要快得多。如果您能找到最小化脚本对这些服务的调用的方法,您的脚本将运行得更快。

为了加快脚本速度,使用一个命令将所有数据读入一个数组,对数组中的数据执行任何操作,然后用一个命令写出数据。

这是一个例子:

var cell = sheet.getRange('a1');
var colors = new Array(100);
for (var y = 0; y < 100; y++) {
xcoord = xmin;
colors[y] = new Array(100);
for (var x = 0; x < 100; x++) {
colors[y][x] = getColor_(xcoord, ycoord);
xcoord += xincrement;
}
ycoord -= yincrement;
}
sheet.getRange(1, 1, 100, 100).setBackgroundColors(colors);

您必须使用 Google 的最佳实践,Google 列表中的亮点是:

  • 减少 API 调用次数
  • 进行 API 调用时,批处理请求
  • 使用内置缓存服务的 Apps 脚本
  • 不要使用 UIApp;使用 HTMLService

以下是帮助您提高脚本性能的文档列表最佳实践:https ://developers.google.com/apps-script/best_practices#minimize-calls-to-other-services

于 2016-05-22T15:26:24.667 回答