2016-02-04 107 views
0

我正在编写一个脚本,该脚本将查看每月报表,并为我们工作的公司创建每个商店的工作表,并将每个工作表的数据复制到新工作表。目前我遇到的问题是,我们有两天的数据,171条线路正在运行我的脚本369.261秒,并且未能完成。Google表单的脚​​本 - 最大执行时间超过

function menuItem1() { 
    var ss = SpreadsheetApp.getActiveSpreadsheet(); 
    var sheet1 = ss.getSheetByName("All Stores"); 
    var data = sheet1.getDataRange().getValues(); 
    var CurStore; 
    var stores = []; 
    var target_sheet; 
    var last_row; 
    var source_range 
    var target_range; 
    var first_row = sheet1.getRange("A" + 1 +":I" + 1); 

    //assign first store number into initial index of array 
    CurStore = data[1][6].toString(); 
    //add 0 to the string so that all store numbers are four digits. 
    while (CurStore.length < 4) {CurStore = "0" + CurStore;} 
    stores[0] = CurStore; 

    // traverse through every row and add all unique store numbers to the array 
    for (var row = 2; row <= data.length; row++) { 
    CurStore = data[row-1][6].toString(); 

    while (CurStore.length < 4) { 
     CurStore = "0" + CurStore; 
    } 

    if (stores.indexOf(CurStore) == -1) { 
     stores.push(CurStore.toString()); 
    } 
    } 

    // sort the store numbers into numerical order 
    stores.sort(); 

    // traverse through the stores array, creating a sheet for each store, set the master sheet as the active so we can copy values, insert first row (this is for column labels), traverse though every row and when the unique store is found, 
    // we take the whole row and paste it onto it's newly created sheet 
    // at the end push a notification to the user letting them know the report is finished. 
    for (var i = stores.length -1; i >= 0; i--) { 
    ss.insertSheet(stores[i].toString()); 
    ss.setActiveSheet(sheet1); 
    target_sheet = ss.getSheetByName(stores[i].toString()); 
    last_row = target_sheet.getLastRow(); 
    target_range = target_sheet.getRange("A"+(last_row+1)+":G"+(last_row+1)); 
    first_row.copyTo(target_range); 

    for (var row = 2; row <= data.length; row++) { 
     CurStore = data[row-1][6].toString(); 

     while (CurStore.length < 4) { 
     CurStore = "0" + CurStore; 
     } 

     if (stores[i] == CurStore) { 
     source_range = sheet1.getRange("A" + row +":I" + row); 
     last_row = target_sheet.getLastRow(); 
     target_range = target_sheet.getRange("A"+(last_row+1)+":G"+(last_row+1)); 
     source_range.copyTo(target_range); 
     } 
    } 

    for (var j = 1; j <= 9; j++) { 
     target_sheet.autoResizeColumn(j); 
    } 
    } 

    Browser.msgBox("The report has been finished."); 
} 

任何帮助将不胜感激,因为我仍然在使用这种相对较新,而且我敢肯定有很多方法可以加快这,如果没有,我最终会找到一种方法打破功能来分割执行。如果需要,我还可以根据需要提供一些示例数据。

在此先感谢。

+1

数据范围有多大?如果您将每行商店的数据拼接出来,那么您可能可以大大加快流程速度,以便下一家商店不必再搜索这些数据。在运行它自己而不是手动触发器时,您可能也可以更快地执行它。 –

+0

一旦所有数据都在月底进入,我会认为数据范围将至少为3000行,最多为9行。关于拼接行的唯一的事情是我想拥有一个包含所有数据的主表。 您是否介意在计划的触发器上进一步阐述为什么可以实现更快的执行? – AustynM

+0

您不会将实际工作表中的数据拼接在一起,只需从数据变量(您可以从主服务器获得或可以先写入数据变量)中进行拼接。根据我的经验,您必须扫描才能找到条目的范围会不断缩小,这抵消了删除元素的成本。根据我的经验,在表单关闭时运行该进程会使其执行得更快,可能是因为用户不会同时查询它,也不必持续更新视图。 –

回答

0

问题是在每次迭代中调用SpreadsheepApp与lib相关的方法,如getRange()。如此处所述:

在脚本中使用JavaScript操作比调用其他服务要快得多 。 Google 应用程序脚本本身的任何功能要比拨打 从Google服务器或外部服务器获取数据的请求要快得多,例如 对电子表格,文档,网站,翻译,UrlFetch等的请求。 如果您能找到方法来尽量减少脚本对这些服务的调用,您的脚本运行得更快。

我遇到同样的情况,而不是做这样的事情for(i=0;i<data.length;i++),我结束了划分data.length成3个独立的功能,并将它们每次他们中的一个结束手动运行。 和你一样,我有一个复杂的报告来自动化,这是唯一的解决方案。

+0

关于这个不幸的部分是我最需要的功能(insertSheet)是始终在2-5秒内执行的任何地方。 – AustynM

+0

我建议使用x张空白工作表创建一个模板电子表格,而不是在'for'循环中插入工作表,只需制作该电子表格的副本并将其用于每月报告。 – Adelin