2012-10-21 52 views
0

我有一個Google Apps腳本用於批量電子郵件收件人在同一個域中。該腳本基本上向他們發送了一個鏈接,指向包含月度報告的Google文檔。腳本在包含750行和16列的循環中超時

  • 訪問包含16列和750列
  • 讀取電子表格從EMAIL列
  • 訪問谷歌的文檔的電子郵件地址基本上是的一個模板:爲報告來自一個電子表格中的值每月 報告,從電子表格中爲每個檢索到的電子郵件地址 製作一份模板副本,並使用列中的值基本上做 查找文檔中的替換。在我的應用程序中,我允許用戶選擇模板,然後在ScriptDB中存儲該模板ID
  • 發送電子郵件給每個收件人並鏈接到每月 報告 - 每個報告都是唯一的,因爲列值代表 用戶。

這個腳本最大的問題是5分鐘執行後超時。上次我嘗試運行它時,它發出了750封電子郵件目標中的145封電子郵件。

模板選擇代碼

function selectTemplate() { 
var app = UiApp.createApplication().setTitle("Select Template").setHeight(400).setWidth(500); 
var doclisthandler = app.createServerHandler('templateSelectionHandler'); 
var closeHandler = app.createServerHandler('closeSelectionHandler'); 
app.createDocsListDialog().showDocsPicker().addSelectionHandler(doclisthandler).addCloseHandler(closeHandler); 
SpreadsheetApp.getActiveSpreadsheet().show(app); 

} 

/** 
Function to retrieve the template ID from ScriptDb 
**/ 

function setTemplateId(){ 
    var db = ScriptDb.getMyDb(); 
    /**we dont query for a specific ID because by default we only store one template so we will 
    always have one record 
**/ 
    var results = db.query({}); 
    while (results.hasNext()) { 
     var result = results.next(); 
     var jsonResults = Utilities.jsonStringify(result); 

    } 
    Logger.log(jsonResults); 
    var jsonTemplate = Utilities.jsonParse(jsonResults); 
    var templateId = jsonTemplate.template_id; 
    return templateId; 
} 

這是發送電子郵件的代碼:

function sendEmail(){ 


    var mySheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 
    var range = mySheet.getDataRange(); 

    var myRange = range.offset(1, 0, range.getNumRows()-1); 

    var curFeatures = range.getValues(); 
    var curCols = new ColNumbers(curFeatures[0], COLS_KEYAPPCOLS); 

    var currentTime = new Date(); 
    var payrollYear = currentTime.getYear(); 
    var payMonth = mySheet.getSheetName(); 
    var hours = currentTime.getHours(); 
    var minutes = currentTime.getMinutes(); 

    try{ 
    //check if folder exists before you create one 
    var monthFolder = DocsList.getFolder("Report-" + mySheet.getSheetName() + "," + payrollYear); 
    }catch(e){ 
    //create a folder to hold the current pay slips 
    var monthFolder = DocsList.createFolder("Report-" + mySheet.getSheetName() + "," + payrollYear); 
    Logger.log(monthFolder.getName()); 

    } 


    myRange.getValues().forEach(function(recipient, index, data){ 

    var staffNumber = recipient[curCols.staffNumber]; 
    Logger.log("staff Number " + staffNumber); 
    var staffName = recipient[curCols.name]; 
    Logger.log("staffName " + staffName); 
    var subject = "Report - " + staffName + ", " + payMonth + "-" + payrollYear; 
    var emailAddress = recipient[curCols.email]; 
    var adminAllowance = recipient[curCols.admin]; 
    var respAllowance = recipient[curCols.resp]; 
    var topUpAllowance = recipient[curCols.topup]; 
    var arrears = recipient[curCols.arrears]; 
    var overtime = recipient[curCols.overtime]; 
    var grossPay = recipient[curCols.gross]; 
    var paye = recipient[curCols.paye]; 
    var mubasa = recipient[curCols.mubasa]; 
    var loan = recipient[curCols.loan]; 
    var rent = recipient[curCols.rent]; 
    var nssf = recipient[curCols.nssf]; 
    var net = recipient[curCols.net]; 
    var totalDed = recipient[curCols.totalded]; 

    var templateid = setTemplateId(); // get template file id 
    if(templateid == ""){ 
     Browser.msgBox("No template has been selected. Please select the correct template"); 
     return; 
    } 

    var docName = "Report details - " + staffNumber; 
    //if email address is not empty do all the cool stuff like sending the data 
    if(emailAddress != ""){ 
     var copyDoc = DocsList.getFileById(templateid).makeCopy(docName);  
     copyDoc.addToFolder(monthFolder); 


     var docid = copyDoc.getId(); 
     Logger.log("Document ID " + docid); 

     var doc = DocumentApp.openById(docid); 

     //set permissions for the doc 
     Logger.log("permission to view doc " + docid + " assigned to " + emailAddress); 
     doc.addViewer(emailAddress); 
     var docURL = doc.getUrl(); 
     var body = doc.getActiveSection(); 
     body.replaceText("%MONTH%", payMonth); 
     body.replaceText("%YEAR%", payrollYear); 
     body.replaceText("%STAFFNAME%", staffName); 
     body.replaceText("%PAYE%", paye); 
     body.replaceText("%OVERTIME%", overtime); 
     body.replaceText("%GROSS%", grossPay); 
     body.replaceText("%NSSF%", nssf); 
     body.replaceText("%MUBASA%", mubasa); 
     body.replaceText("%NET%", net); 
     body.replaceText("%ARREARS%", arrears); 
     body.replaceText("%TOTALDED%", totalDed); 
     body.replaceText("%LOAN%", loan); 
     body.replaceText("%RENT%", rent); 
     body.replaceText("%ADMIN%", adminAllowance); 
     body.replaceText("%RESP%", respAllowance); 
     body.replaceText('%TOPUP%', topUpAllowance); 

     //email message 

     doc.saveAndClose(); 


     Logger.log("Sending email to " + emailAddress + " at " + hours + ":" + minutes); 
     try{ 
     MailApp.sendEmail(emailAddress, 
         subject, "", 
         {htmlBody: message 
         }, 
         attachment: docName, 
         name: "Report" 
         }); 
     }catch(e){ 
     Logger.log(e); 
     } 

    }else{ 
     Logger.log("no email address found for staff member " + staffName);     

     } 


    }); 


} 

我會很感激我如何能優化這個腳本序它不超時一些指針。

回答

2

我建議你修改你的腳本一次處理75或100個項目,跟蹤你在腳本屬性(或其他地方)的位置,並稍後繼續處理,直到它處理了750個項目。 這應該每5分鐘左右在一個定時器觸發器上啓動。

當一切都發送,然後關閉觸發器,並在需要時重新啓動它。觸發器可以通過編程方式輕鬆設置。

+0

按照您的提示,也遇到了這個腳本http://www.labnol.org/internet/sort-gmail-by-size/21191/我跟蹤腳本屬性中腳本的結束位置,然後設置一個觸發器每分鐘運行一次。一旦計數器值==電子表格中的項目數量,我就知道腳本已經完成,並刪除了觸發器。到目前爲止,它似乎工作,我只會確認計數器何時歸零。 – jwesonga

+0

可能是1分鐘,在2次運行之間有點短...您應該避免使用腳本的併發實例,因爲這可能會導致計數器中的混亂。 –