Just
Just

Reputation: 437

Google App Script to Group Row data in sheet based on email column

I have google sheet with several projects. The sheet also has names of project leaders that manage these projects. One project leaders can manage up to 5 projects at a go. The sheet looks like this.

enter image description here

I would like to group each row data by column F (email) and send one email to each project lead on the projects they are managing, say for instance Tim Curry will receive a table listing only the projects he leads. My code below is not adequate to accomplish this task and I will appreciate help in modifying it to group the data and send it as HTML.

function sendEmails() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var startRow = 3;  // First row of data to process
  var numRows =  12;   // Number of rows to process                     
 
  
  var dataRange = sheet.getRange(startRow, 1, numRows, 12)  
  // Fetch values for each row in the Range.
  var data = dataRange.getValues();
  var emails = data.map(function (e) { 
    return e[5]; 
  })
  var uniqueEmails = [...new Set(emails)];
  
  for (var j = 0; j < uniqueEmails.length; j++) {
    var subject = "";
    var body = "Please see if your project is on course, if not foward this email to PMS admin"
    for (var i = 0; i < data.length; i++) {
      if (data[i][5] == uniqueEmails[j]){
        var row = data[i];
        var projectnumber = row[0];
        var startdate = row[1];
        var enddate = row[2];
        var projectname = row[3];
        var projectlead= row[4];
        var email= row[5];
        
        
        var lr = sheet.getLastRow();
        var tableRangeValues=sheet.getRange(2,1, lr-1,6).getDisplayValues();
        
        var htmlTemplate = HtmlService.createTemplateFromFile("Notify") 
        htmlTemplate.projectnumber = projectnumber;
        htmlTemplate.startdate= startdate;
        htmlTemplate.enddate= enddate;
        htmlTemplate.projectname= projectname;
        htmlTemplate.projectlead=projectlead;
        htmlTemplate.email=email;
        var htmlForEmail = htmlTemplate.evaluate().getContent();
        
        if (enddate instanceof Date && enddate.getTime()>= new Date(07/14/20).getTime()) {   
         var emailSent = row[6];           
          if (emailSent != "Y") {
            subject += "Action Required - Project End"; 
          }
        }
        
      }
    }
    if(subject.length > 0){
      
                MailApp.sendEmail({
                to: uniqueEmails[j], 
                cc: "[email protected]",
                subject: subject, 
                body: body
              }); 
    }
  }
}

Notify HTML table Code:

 <thead>
<tr>
<th><?=projectnumber?></th>
<th><?=startdate?></th>
<th><?=enddate?></th>
<th><?=projectname?></th>
<th><?=projectlead?></th>
<th><?=email?></th>
</tr>
</thead>
<tbody>
<?tableRangeValues.forEach(r=>{?>
<tr>
<td><?=r[0]?></td>
<td><?=r[1]?></td>
<td><?=r[2]?></td>
<td><?=r[3]?></td>
<td><?=r[4]?></td>
<td><?=r[5]?></td>
</tr>
<?})?>
</tbody>
</table>

Upvotes: 1

Views: 853

Answers (1)

ziganotschka
ziganotschka

Reputation: 26836

Use ... new Set() to retrieve unique emails from the sheet and concatenate the email contents for the rows that correspond to each unique email

Sample:

function sendEmails() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var startRow = 3;  // First row of data to process
  var numRows =  12;   // Number of rows to process                     
  //  var numItems = SpreadsheetApp.getActiveSheet().getRange(startRow,1 numRows, sheet.getLastColumn()).getValues();
  // var numRows = numItems[0]
  
  var dataRange = sheet.getRange(startRow, 1, numRows, 11)  
  // Fetch values for each row in the Range.
  var data = dataRange.getValues();
  var emails = data.map(function (e) { 
    return e[5]; 
  })
  var uniqueEmails = [...new Set(emails)];
  
  for (var j = 0; j < uniqueEmails.length; j++) {
    var subject = "";
    var body = "Please see if your project is on course, if not foward this email to PMS admin"
    for (var i = 0; i < data.length; i++) {
      if (data[i][5] == uniqueEmails[j]){
        var row = data[i];
        var projectnumber = row[0];
        var startdate = row[1];
        var enddate = row[2];
        var projectname = row[3];
        var projectlead= row[4];
        var email= row[5];
        if (enddate instanceof Date && enddate.getTime()>= new Date(07/14/20).getTime()) {   
         var emailSent = row[6];           
          if (emailSent != "Y") {
            subject += "Action Required - Project: " + projectname + " " + projectnumber + " " ; 
          }
        }
        
      }
    }
    if(subject.length > 0){
      
                 MailApp.sendEmail({
                to: uniqueEmails[j], 
                cc: "[email protected]",
                subject: subject, 
                body: body
              }); 
    }
  }
}

UPDATE

If you want to group the rows e.g. to pass them together to a loop in the html template, you can use the Javascript function filter().

Sample

Code.gs

var tableRangeValues;

function sendEmails() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var startRow = 3;  // First row of data to process
  var numRows =  12;   // Number of rows to process                       
  var dataRange = sheet.getRange(startRow, 1, numRows, 12)  
  // Fetch values for each row in the Range.
  var data = dataRange.getValues();
  var emails = data.map(function (e) { 
    return e[5]; 
  })
  var uniqueEmails = [...new Set(emails)];  
  for (var j = 0; j < uniqueEmails.length; j++) {
    var subject = "Action Required - Project End";
    var body = "Please see if your project is on course, if not foward this email to PMS admin";
    
    tableRangeValues = data.filter(function(row){return (row[5] == uniqueEmails[j]);});
    var htmlTemplate = HtmlService.createTemplateFromFile("Notify") ;
    var htmlForEmail = htmlTemplate.evaluate().getContent();
    body += htmlForEmail;
    
    if(filteredData.length > 0){
      Logger.log("body: " + body);  
      MailApp.sendEmail({
        to: uniqueEmails[j], 
        cc: "[email protected]",
        subject: subject, 
        htmlBody: body
      }); 
    }
  }
}

Notify.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
     <thead>

</thead>
<tbody>
<?tableRangeValues.forEach(r=>{?>
<tr>
<td><?=r[0]?></td>
<td><?=r[1]?></td>
<td><?=r[2]?></td>
<td><?=r[3]?></td>
<td><?=r[4]?></td>
<td><?=r[5]?></td>
</tr>
<?})?>
</tbody>
</table>
  </body>
</html>
  • Note that you need to declare tableRangeValues as a global variable if you want to use in the html template with scriptlets
  • Note that if you want to send an email with an htmlBody you have to specify it as such within MailApp.sendEmail()

Upvotes: 2

Related Questions