1

我仍然在这里学习绳索。根据其他贡献者建议的代码,我编写了一个脚本,用于向使用 Google 表单记录时间条目的顾问发送提醒电子邮件。电子表格首先导入日历条目,其中包含每个顾问的所有工作信息。导入日历条目后,如果顾问尚未记录他们的时间条目,以下脚本将向他们发送一封电子邮件,提醒他们这样做:

function sendReminder() {

  var rmndrFrom = "XYZ, Inc.";
  var myemail   = "support@xyz.com";

  var sheet     = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Pending");
  var numRows   = sheet.getLastRow();
  var lastCol   = sheet.getLastColumn();
  var dataRange = sheet.getRange(2, 1, numRows, lastCol); // row 1 is the header row
  var sheetData = dataRange.getValues();

  for (var i = 0; i < sheetData.length; ++i) {
    var row = sheetData[i];
    if (row[0]){
      var jobNumb = row[0]; // Job Number
      var conName = row[2]; // Consultant Name
      var conMail = row[3]; // Consultant Email
      var jobDate = row[4]; // Date

      // format email string
      var subject = "Time Entry Reminder: " + conName + " / Job " + jobNumb;

        try {
          var conMsgH = 'This is a reminder for you to record your time entry for Job #<strong>' + jobNum + '/' + jobDate + '</strong>';

          // strip HTML for plain text message
          var conMsgP = conMsgH.replace(/\<br\/\>/gi, '\n').replace(/(<([^>]+)>)/ig, "");

          // send reminder to consultants
          MailApp.sendEmail(conMail, subject, conMsgP, { htmlBody:conMsgH, name:rmndrFrom });

        } catch (e) { // error handler
          MailApp.sendEmail(myemail, "Error in sending reminder email.", e.message);
        }
      }
  }
}

所以基本上,这个脚本会解析待处理的工作表,如果 A 列有一个工作编号,它会向顾问发送一封提醒电子邮件,其中包含该工作编号。但是,单个顾问的名字可能有多个职位编号。我希望脚本向每位顾问发送一封电子邮件,其中包含他们必须记录其时间条目的工作编号列表。

提前感谢您的帮助。任何关于如何优化代码的建议也将不胜感激。

4

2 回答 2

2

有很多方法可以解决这个问题。一种方法是保留一张包含顾问电子邮件、姓名和工作编号列表的表格。将此数据加载到您的脚本中,列出所有作业 ID 和作业信息。然后根据顾问列表过滤职位 ID 并构建您的电子邮件,或者您可以发送该数字列表以获得非常短的脚本。

另一种方法是对代码中的每个顾问进行所有排序,然后以这种方式发送电子邮件。这是我采用的方法,我还在MDN 使用了迭代 JS 函数映射、过滤和减少更多细节

代码发布在下面,但如果您想查看它附加到电子表格并发表评论(以及构建仅包含顾问信息的额外工作表的功能),请查看此处

以下是我对您的功能的迭代。我希望它对您的情况有所帮助:

var rmndrFrom = "XYZ, Inc.";
var myemail   = "me@emailisawesome.com";
var subject   = "Time Entry Reminder";

function sendReminder() {
  var sheet       = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Pending");
  var numRows     = sheet.getLastRow();
  var lastCol     = sheet.getLastColumn();
  var sheetData   = sheet.getRange(2, 1, numRows-1, lastCol).getValues();
  var cons = sheet.getRange(2,3,numRows-1,1).getValues().reduce(flatten_).filter(getUniqueConsultants_);
  cons.forEach(sendEmail_, sheetData);
}

function sendEmail_(consultant) {
  var consultantsJobs = this.filter(getJobsForConsultant_, consultant);
  var jobList = consultantsJobs.map(buildJobLine_).join("<br>"); 
  try {
    var conMsgH = "Hi " + consultant + ",<br>";
    conMsgH    += "This is a reminder for you to record your time entry for the following jobs:<br><br>";
    conMsgH    += jobList;
    conMsgH    += "<br><br>Thank you for your cooperation.";
    var conMsgP = conMsgH.replace(/\<br\/\>/gi, '\n').replace(/(<([^>]+)>)/ig, "");
    MailApp.sendEmail(consultantsJobs[0][3], subject, conMsgP, {htmlBody:conMsgH, name:rmndrFrom});
  } catch (e) {
    MailApp.sendEmail(myemail, "Error in sending reminder email.", e.message);
  } 
}

function buildJobLine_(job) {
  return "Job #" + job[0] + " on " + Utilities.formatDate(job[4], Session.getTimeZone(), "MMM dd yyyy");
}

function getJobsForConsultant_(row) {
  return row[2] == this;
}

function getUniqueConsultants_(v,i,a) {
  return a.indexOf(v) == i;
}

function flatten_(a,b) {
  return a.concat(b);
}
于 2012-12-24T23:34:01.450 回答
1

我必须说fooby的答案远远超出了我的 JS 技能,我相信它会很好地工作,但我仍然想提出一些不同的东西(而且从我的 pov 更简单),只是为了好玩 ;-)

与原始脚本的主要区别是数组的排序允许我检测重复名称并相应地对其进行威胁。html 组合肯定会好得多,但这不是您的主要要求。

这是代码

function sendReminder() {

  var rmndrFrom = "XYZ, Inc.";
  var myemail   = "support@xyz.com";
  var sheet     = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Pending");
  var initial = "Hi conName,<BR>This is a reminder for you to record your time entry for the following jobs : <BR><BR><table border = 1 cellpadding = 3 bgcolor='#FFFFBB'><TR><TD>";

  var sheetData = sheet.getDataRange().getValues();// simplified code to get the data array
  sheetData.shift();//skips the headers
  sheetData.sort(function(x,y){
  var xp = x[2];// sort on column 3 but you can change  here...
  var yp = y[2];// sort on column 3 but you can change  here...
  return xp == yp ? 0 : xp < yp ? -1 : 1;// sort ascending, eventually change here...
  });
//  Logger.log(sheetData);// sorted
  var last = sheetData.length
  var i = 1;//index 0 is handled outside the loop
  var row = sheetData[0];
  var subject = "Time Entry Reminder: " + row[2] + " / Job "
  var conMsgH = initial
  var msgComponent = makeline_(row)
  subject += msgComponent[0]
  conMsgH += msgComponent[1]

  while (i<last){
    if(sheetData[i][2]!=sheetData[i-1][2]||i==last-1){
      sendData_(sheetData[i-1][3],sheetData[i-1][2],subject,conMsgH)
      var subject = "Time Entry Reminder: " + sheetData[i][2] + " / Job "
  var conMsgH = initial;
      }
  msgComponent = makeline_(sheetData[i])
  subject += msgComponent[0]
  conMsgH += msgComponent[1]
  ++i
  }
}

function sendData_(conMail,conName,subject,conMsgH){
  conMsgH = conMsgH.substr(0,conMsgH.length-8)+'</TABLE>'
  conMsgH = conMsgH.replace('conName',conName)
  var conMsgP = conMsgH.replace(/<\/tr>/ig, '\n').replace(/<br>/ig, '\n').replace(/(<([^>]+)>)/ig, "")
  subject = subject.substr(0,subject.length-2);// remove the last '+ '
//  Logger.log(subject)
//  Logger.log(conMsgH)
  Logger.log(conMsgP)
//  Logger.log(conMail)
  try{
          // send reminder to consultants          
          MailApp.sendEmail(conMail, subject, conMsgP, { htmlBody:conMsgH, name:rmndrFrom });
        } catch (e) { // error handler
//          MailApp.sendEmail(myemail, "Error in sending reminder email.", e.message);
    }
}

function makeline_(row){
      var jobNumb = row[0]; // Job Number
      var conName = row[2]; // Consultant Name
      var conMail = row[3]; // Consultant Email
      var descr = row[1]; // description
      var FUS1=new Date(row[4]).toString().substr(25,6)+':00';// get timezone of this event, taking care of daylight savings
      var jobDate = Utilities.formatDate(row[4], FUS1, "MMM dd yyyy @ hh:mm aaa"); // Date
      var subject =  jobNumb+' + ';
      var conMsgH =  'Job #'+jobNumb + '</TD><TD>' + jobDate + '</TD><TD>' + descr + '</TD></TR><TR><TD>';
return [subject,conMsgH];
}

编辑:对邮件格式进行了一些改进,使用表格显示工作和日期+删除了一些错误;-)(老实说,我这样做也是为了我个人使用,因为我有几乎相同的用例)

于 2012-12-25T01:07:47.997 回答