脚本在包含750行和16列的循环中超时

时间:2012-10-21 20:32:28

标签: google-apps-script

我有一个Google Apps脚本,我用它来批量同一个域中的电子邮件收件人。脚本基本上向他们发送包含月度报告的Google文档的链接。报告的值来自电子表格:

  • 访问包含16列和750行的电子表格
  • 阅读EMAIL专栏中的电子邮件地址
  • 访问Google Doc,它本质上是每月的模板 报告,为检索到的每个电子邮件地址制作模板的副本 从电子表格和使用列中的值基本上做 找到Doc的替代品。在我的应用程序中,我允许用户选择模板,然后将该templateId存储在ScriptDB中
  • 发送电子邮件给每位收件人,并附上每月的链接 报告 - 每个报告都是唯一的,因为列值代表a 用户。

此脚本的最大问题是它在执行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);                  

        }


  });


}

我非常感谢有关如何优化此脚本的一些指示,以便它不会超时。

1 个答案:

答案 0 :(得分:2)

我建议您修改脚本以一次处理75或100个项目,跟踪脚本属性(或其他位置)的位置并稍后继续处理750个项目。 这应该每5分钟左右在定时器触发器上启动。

发送所有内容后,关闭触发器并在需要时重新启动它。触发器可以通过编程方式轻松设置。