0

同じドメインのメール受信者を一括送信するために使用している Google Apps Script があります。スクリプトは基本的に、月次レポートを含む Google ドキュメントへのリンクを送信します。レポートの値は、スプレッドシートから取得されます。

  • 16 列 750 行のスプレッドシートにアクセスする
  • EMAIL 列からメールアドレスを読み取ります
  • 基本的に月次レポートのテンプレートである Google Doc にアクセスし、スプレッドシートから取得した各メール アドレスのテンプレートのコピーを作成し、列の値を使用して基本的に Doc の置換を検索します。私のアプリでは、ユーザーがテンプレートを選択できるようにしてから、その templateId を ScriptDB に保存します。
  • 月次レポートへのリンクを含む各受信者に電子メールを送信します。列の値はユーザーを表すため、各レポートは一意です。

このスクリプトの最大の問題は、実行から 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);                  

        }


  });


}

このスクリプトがタイムアウトしないように最適化する方法について、いくつかの指針をいただければ幸いです。

4

1 に答える 1

2

一度に 75 または 100 個のアイテムを処理するようにスクリプトを変更し、スクリプト プロパティ (または別の場所) のどこにいるかを追跡し、750 個のアイテムが処理されるまでしばらくしてから続行することをお勧めします。これは、約 5 分ごとのタイマー トリガーで開始する必要があります。

すべてが送信されたら、トリガーをシャットダウンし、必要に応じて再起動します。トリガーはプログラムで簡単に設定できます。

于 2012-10-21T21:14:24.633 に答える