2016-08-30 17 views
0

私は現在、残念ながら遅すぎる実行するGoogleスクリプトを書いています。 (6分以上の制限)。スクリプトはドキュメントを開き、2つの文字列(Googleシートに設定されている)を置き換えて、PDFとして保存します。何もない。Googleスクリプトが遅すぎる

私はこのスクリプトを実行するためにこれらのドキュメントを約200個持っていますが、6分以内に6個までしか管理できません。ちょうどこれが遅いGoogleスクリプトですか、または私は間違いなく最も非効率的なGoogleスクリプトを作ったことがありますか?

function createAllPDF() { 
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 
    var range = SpreadsheetApp.getActiveSheet().getActiveRange() 
    var numRows = SpreadsheetApp.getActiveSpreadsheet().getLastRow() - 1; 
    for(var i = 9; i <= numRows; i++) { 
    var thisRange = sheet.getRange("A" + n + ":C" + n); 
    var fond = thisRange.getCell(1, 1).getValue(); 
    var adresse = thisRange.getCell(1, 3).getValue(); 
    thisRange.setBackground('#cfe2f3'); 
    genDoc(fond, adresse); 
    } 
} 
//// CREATE PDF ////////////////// FUNCTION FOR GENERATING THE PDF ///////////////////////////////// 
function genDoc(fond, adresse) { 
    // Finds the template and duplicate it into a new file. 
    var template = ("xxxxxxxxxxxx"); 
    var docId = DriveApp.getFileById(template).makeCopy().getId(); 
    // Opens the newly created Document for editing 
    var doc = DocumentApp.openById(docId); 
    var body = doc.getActiveSection(); 
    // Renames the newly generated document 
    var newName = doc.setName(fond); 
    // Replaces each with the parsed variables. 
    body.replaceText("%FOND%", fond); 
    body.replaceText("%ADRESSE%", adresse); 
    doc.saveAndClose(); 
    //Adds the PDF ID to the invoice_input sheet 
    var conv = DriveApp.getFileById(docId); 
    var pdf = conv.getAs("application/pdf"); 
    var fileId = DriveApp.createFile(pdf).getId(); 
    // Gets the PDF file by ID 
    var thisPDF = DriveApp.getFileById(fileId); 
    // The ID of the folder I'd like to put the PDF into. 
    var folderId = "xxxxxxxxxxx"; 
    // Gets the folder by ID 
    var targetFolder = DriveApp.getFolderById(folderId); 
    // Adds the PDF to the Folder 
    targetFolder.addFile(thisPDF); 
    // Removes the PDF from the root. 
    var root = DriveApp.getRootFolder().removeFile(thisPDF); 
    // Deletes the duplicated document 
    DriveApp.getFileById(docId).setTrashed(true) 
    return fileId; 
} 

どのように最適化するかの指針は非常に高く評価されます。私は非常に新しいスクリプトとプログラミングのプログラミングに一般的なので、大きな言葉は、heheです。 このボードを誤って使用している場合は、お詫び申し上げます。私に知らせて訂正します。

+2

[コードレビュー](http://codereview.stackexchange.com/help/on-topic) – pnuts

答えて

0

(注:これをテストしていませんが、あなたは始めるべきです)

いくつかのアイデアを:

  1. は、forループの外に "getRange" コマンドを移動します。
  2. forループの外側にあるテンプレートtargetFolderおよびrootFolderを読み込んで、引数としてgenDocに渡します。
  3. 可能であれば、「シート」と「conv」を再利用してください。
  4. すべてのbgColorsを個別にではなく一度に記述します。
  5. 何も返さないでください。

だから、このような何か:


function createAllPDF() { 
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 
    var numRows = sheet.getLastRow() - 1; 
    var range = sheet.getActiveRange(); 
    var values = range.getValues(); 
    var templateId = ("xxxxxxxxxxxx"); 
    var template = DriveApp.getFileById(templateId); 
    // The ID of the folder I'd like to put the PDF into. 
    var folderId = "xxxxxxxxxxx"; 
    // Gets the folder by ID 
    var targetFolder = DriveApp.getFolderById(folderId); 
    var rootFolder = DriveApp.getRootFolder(); 
    for(var i = 9; i <= numRows; i++) { 
    var fond = values[i][1]; // TODO: check syntax. 
    var adresse = values[i][3]; 
    genDoc(fond, adresse, template, targetFolder, rootFolder); 
    } 
    range.setBackground('#cfe2f3'); // TODO: only first 3 columns 
} 
//// CREATE PDF ////////////////// FUNCTION FOR GENERATING THE PDF ///////////////////////////////// 
function genDoc(fond, adresse, template, targetFolder, rootFolder) { 
    // Finds the template and duplicate it into a new file. 
    var conv = template.makeCopy(); 
    var docId = conv.getId(); 
    // Opens the newly created Document for editing 
    var doc = DocumentApp.openById(docId); 
    var body = doc.getActiveSection(); 
    // Renames the newly generated document 
    var newName = doc.setName(fond); 
    // Replaces each with the parsed variables. 
    body.replaceText("%FOND%", fond); 
    body.replaceText("%ADRESSE%", adresse); 
    doc.saveAndClose(); 
    //Adds the PDF ID to the invoice_input sheet 
    var pdf = conv.getAs("application/pdf"); 
    var fileId = DriveApp.createFile(pdf).getId(); 
    // Gets the PDF file by ID 
    var thisPDF = DriveApp.getFileById(fileId); 
    // Adds the PDF to the Folder 
    targetFolder.addFile(thisPDF); 
    // Removes the PDF from the root. 
    rootFolder.removeFile(thisPDF); 
    // Deletes the duplicated document 
    conv.setTrashed(true); 
} 
+0

でお勧めします。ありがとうございました!今は2倍速く走っています。これは素晴らしいことです。残念ながら、それは6分以内に私の文書を完成させるのに十分な速さではありません。それは一日の50分の時間制限内でそれを完了するのに十分な速さではない。 これはまさにGoogleスクリプトが使用されているとは限りません。 ご協力いただきありがとうございます。 – Jake

+0

インストール可能なトリガーhttps://developers.google.com/apps-script/guides/triggers/installableおよび一般的な最適化テクニックをご覧ください。http://stackoverflow.com/questions/14450819/google-app-script-タイムアウト - 5分 – opowell

0

私はすぐにあなたが未定義の変数nを持っていることに気づきます。それはラインである:

var thisRange = sheet.getRange("A" + n + ":C" + n);

これはコードが完全に使用不能作られている必要があります。これらの変数をiに変更すると、完全に6分間コードを正常に実行することができました。その間、約41.5回ループすることができました。 9〜53行目のファイルが作成されましたが、最後のファイルを正しいフォルダに追加する前に停止しました。

実行記録を見ると、最も長い操作はファイルの作成、移動、削除の呼び出しです。

また、rangeを定義し、この変数を使用しないでください。この変数は不要です。

私は自分自身のために何度も使った構造と方法でコードを書きました。私は行9~59を完全に処理することができました。このメソッドは6行分拡張できました。 5分55秒ごとに機能を停止させてから5秒後にもう一度起動するように、タイムアウトトリガーを追加することをお勧めします。 javascriptの時間に関するガイドはhereです。私は別のマッチメソッドも使用します。 RegExを使用します。 RegExには広範なガイドがあり、その処理時間を最小限に抑える方法があります。私はこの分野に堪能ではありません。

function PDFCreator() { 
    var ss = SpreadsheetApp.getActiveSpreadsheet(); 
    var sheet = ss.getSheetByName("Test Sheet"); 
    var lastRow = sheet.getLastRow(); 
    var checkRange = sheet.getRange(9, 1, (lastRow - 8), 3); 
    var check = checkRange.getBackgrounds(); 
    var lightBlue = "#cfe2f3"; 
    var template = DriveApp.getFileById("1RslWGntAwfLTSytOv_IoOv2_iBhSmsK0ZtEVWaq3ezM"); 
    var folder = DriveApp.getFolderById("0BwZ6LWJudkOHaTFiQjd5cFA5OG8"); 
    for (i = 0; i < check.length; i++) { 
    if (check[i] == lightBlue) { 
     continue; 
    } else { 
     var dataRow = sheet.getRange((i + 9), 1, 1, 3); 
     var fond = sheet.getRange((i + 9), 1, 1, 1).getValue(); 
     var adresse = sheet.getRange((i + 9), 3, 1, 1).getValue(); 
     var docName = fond + ".pdf"; 
     var docCopy = template.makeCopy(docName, folder); 
     var docId = docCopy.getId(); 
     var docToEdit = DocumentApp.openById(docId); 
     var docBody = docToEdit.getBody(); 
     docBody.replaceText(/\%{1}[F][O][N][D]\%{1}/g, fond); 
     docBody.replaceText(/\%{1}[A][D][R][E][S][S][E]\%{1}/g, adresse); 
     docToEdit.saveAndClose(); 
     var fileToPDF = DriveApp.getFileById(docId); 
     var pdfBlob = fileToPDF.getAs(MimeType.PDF); 
     var pdfRoot = DriveApp.createFile(pdfBlob).setName(docName); 
     var pdf = pdfRoot.makeCopy(folder); 
     pdfRoot.setTrashed(true); 
     fileToPDF.setTrashed(true); 
     dataRow.setBackground(lightBlue); 
    } 
    } 
} 

あなたは、私がメイン関数の内部for()if()を入れ子になったことに気づくでしょう。そうすれば、関数間で情報を何度も渡すことはありません。一般的には、をループの外側に定義すると、より多くの呼び出しを行う必要があります。 forループの外側に設定して、実行をさらに拡張できる変数がたくさんあります。

基本的には長いプロセスで、6分で200回実行することはできません。これを完全な効率で合計55/60行に拡張することができますが、その時点で再度実行する必要があります。