2017-01-11 6 views
0

私は自分のプロジェクトに必要な背景を提供することができますが、ここには結論があります。900行以上のループを実行するGoogle Appsスクリプトの最適化

処理が必要な900以上の広告申込情報があるスプレッドシートがあります。各ラインアイテムは、処理する2〜6人の異なるチームメンバーを通過する必要があります(アイテムの種類によっては、2人でも、6人でもよい)。各広告申込情報が各チームメンバーに所属する期間に関する指標を作成しようとしています。

スプレッドシートの2番目のタブで、私は900個の広告申込情報をもう一度表示しました。これは、ステータスと次のステータスに移行したときのタイムスタンプを記録します。そこから、各広告申込情報があるステータスから次のステータスに移行するまでにどれくらいの時間がかかるかを分析することができます。

私は両方のタブを見て、プライマリキーの行項目(最初のタイムスタンプ)と一致するスクリプトを書いて、各行がメインのスプレッドシートにあるかどうかを調べて、メトリック]タブをクリックします。別のステータスの場合、スクリプトは新しいステータスを記録し、新しいステータスをタイムスタンプします。

私のスクリプトは動作しますが、それは非常に遅く、最大実行時間に達する前に約50行しか取得できません。 スクリプトをより効率的にするだけで、1回の実行で900行すべてを処理することができます。

function myFunction() { 
var app = UiApp.createApplication() 

var doc = SpreadsheetApp.openById('1ijBVLZcGlvxvB9R_r2wXZUylIem70yihZpqDLufNm9Q'); 
var newS = doc.getSheetByName('NEW') 
var metricsS = doc.getSheetByName('Metrics Data') 
var numRows = metricsS.getDataRange().getNumRows() 

for (var j = 2; j < numRows ; j++) { 
for (var i = 2; i < numRows ; i++) {     
    if(((metricsS.getRange(j, 1, 1, metricsS.getLastColumn()).getCell(1, 1).getValue()) == (newS.getDataRange().getCell(i, 1).getValue())) && ((metricsS.getRange(j, 1, 1, ((metricsS.getRange(j, 1, 1, 100).getValues())[0].filter(String).length)).getCell(1, ((metricsS.getRange(j, 1, 1, 100).getValues())[0].filter(String).length)-1).getValue()) != (newS.getDataRange().getCell(i, 2).getValue()))) {  
metricsS.getRange(j, 1, 1, 250).getCell(1, ((metricsS.getRange(j, 1, 1, 100).getValues())[0].filter(String).length)+1).setValue(newS.getDataRange().getCell(i, 2).getValue());  
metricsS.getRange(j, 1, 1, 100).getCell(1, ((metricsS.getRange(j, 1, 1, 100).getValues())[0].filter(String).length)+1).setValue(new Date()); break;}} 
} 

return app;} 
+0

すべてのgetRange()呼び出しには多くの時間がかかります。各タブ(シート)のオブジェクトにすべてのデータを取得してから、オブジェクトの1つをループするのが最適です。記事のチュートリアル:Simple Mail Merge(https://developers.google.com/apps-script/articles/mail_merge)記事の一番下のサンプルコード、getRowsData()機能を最後まで。 –

答えて

2

標準のアドバイスはループ内でのgetValueを使用しないことです:use batch operation getValues instead。あなたのケースでは、これは単なる行/列番号は1で始まりながら、JavaScriptのインデックスは、インデックス1でループを開始する第二の手段で始まるすべての行を超えるループ、従って、0で始まることに注意してください

var allData = metricsS.getDataRange().getValues(); 

// now we have all data, so loop through this JavaScript array 

for (var j = 1; j < allData.length ; j++) { 
    for (var i = 1; i < allData.length ; i++) { 
    if (allData[i][2] > allData[j][0]) { // some condition 
     // do something 
    }   
    } 
} 

だろう、 上記のように。

同様にsetValue:出力をダブルJavaScript配列に配置し、ループが終了した後にsetValuesを1回適用します。

関連する問題