2016-08-30 4 views
0

Ich schreibe gerade ein Google-Skript, das leider zu langsam läuft. (Mehr als die 6 Minuten Grenze). Das Skript öffnet ein Dokument, ersetzt zwei Zeichenketten (die in einem Google-Blatt gesetzt werden), speichert es als PDF. Nichts Außergewöhnliches.Google-Skript läuft zu langsam

Ich habe etwa 200 dieser Dokumente, um durch dieses Skript zu laufen, aber innerhalb der 6-Minuten-Grenze schafft es es nur durch sechs zu gehen. Ist Google Script nur so langsam, oder habe ich versehentlich das ineffizienteste Google-Skript überhaupt erstellt?

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; 
} 

Alle Hinweise zur Optimierung werden sehr geschätzt. Ich bin sehr neu in Google Script und Programmierung im Allgemeinen, also keine großen Worte, hehe. Entschuldigen Sie sich, wenn ich diese Platine falsch verwende. Bitte lass es mich wissen und ich werde korrigieren.

+2

Sie könnten besser bei [Code Review] (http://codereview.stackexchange.com/help/on-topic) – pnuts

Antwort

0

(Anmerkung: habe nicht getestet, sollte aber loszulegen)

einige Ideen:

  1. Bewegen Sie den "getRange" Befehl aus der for-Schleife.
  2. Lesen Sie die Vorlage, targetFolder und rootFolder außerhalb der for-Schleife und übergeben Sie sie als Argumente an genDoc.
  3. Wiederverwendung von "Blatt" und "Conv", wenn möglich.
  4. Schreiben Sie alle bgColors gleichzeitig, anstatt einzeln.
  5. Gib nichts zurück.

So etwas wie folgt aus:


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

Hey, Vielen Dank für die Antwort! Es läuft jetzt doppelt so schnell, was großartig ist. Leider ist es nicht annähernd schnell genug, um meine Dokumente innerhalb von 6 Minuten fertig zu stellen. Es ist nicht einmal schnell genug, um es innerhalb der 50-Minuten-Frist des Tages zu beenden. Vielleicht ist dies nicht genau das, was Google-Skript verwendet werden soll. Nochmals vielen Dank für die Hilfe. – Jake

+0

Weitere Informationen finden Sie unter Installierbare Trigger https://developers.google.com/apps-script/guides/triggers/installable und allgemeine Optimierungstechniken http://stackoverflow.com/questions/14450819/google-app-script- Timeout-5 Minuten – opowell

0

Ich merke sofort, dass Sie eine undefinierte Variable n haben. Es ist in der Zeile:

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

Dies ist der Code völlig unbrauchbar gemacht haben sollte. Wenn diese Variablen in i geändert wurden, konnte ich den Code für die vollständigen 6 Minuten erfolgreich ausführen. Während dieser Zeit war es in der Lage, etwa 41,5-mal zu wiederholen. Es erstellte Dateien für die Zeilen 9-53, wurde jedoch gestoppt, bevor die letzte Datei dem richtigen Ordner hinzugefügt werden konnte.

Wenn Sie das Ausführungstranskript betrachten, sind Ihre längsten Operationen die verschiedenen Aufrufe zum Erstellen, Verschieben und Löschen von Dateien.

Sie definieren auch range und dann nie diese Variable verwenden, was es unnötig macht.

Ich habe den Code in der Struktur und Methode, die ich für mich selbst oft verwendet habe, umgeschrieben. Ich konnte Zeilen 9-59 vollständig verarbeiten. Diese Methode konnte es um 6 Zeilen erweitern. Ich würde vorschlagen, einen Timeout-Trigger hinzuzufügen, um die Funktion alle 5 Min. 55 Sekunden zu stoppen und dann 5 Sekunden später erneut zu starten. Anleitungen zu Javascript-Zeit finden Sie unter here. Ich benutze auch eine andere Match-Methode; RegEx verwenden. Es gibt umfangreiche Anleitungen zu RegEx und wie diese Verarbeitungszeit minimiert werden kann. Ich bin in dieser Gegend nicht annähernd so gut.

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); 
    } 
    } 
} 

Sie werden bemerken, dass ich die for() und if() in der Hauptfunktion verschachtelt.Auf diese Weise geben Sie keine Informationen zwischen den Funktionen hin und her. Im Allgemeinen, je mehr Sie außerhalb die Schleifen definieren können, desto weniger Anrufe müssen Sie vornehmen. Es gibt mehr Variablen, die ich außerhalb der for-Schleife hätte setzen können, um den Lauf weiter zu verlängern.

Grundsätzlich ist es ein langer Prozess und es wird nicht in der Lage sein, es 200 mal in 6min zu laufen. Sie können dies auf vielleicht 55/60 Gesamtzeilen mit perfekter Effizienz erweitern, aber an diesem Punkt müssen Sie es nur noch einmal ausführen lassen.