0

This is the extended version of my previous question. I want to send email once in a week to the recipients based on the status column. Sheet Link: https://docs.google.com/spreadsheets/d/1GC59976VwB2qC-LEO2sH3o2xJaMeXfXLKdfOjRAQoiI/edit#gid=1546237372
The previous code is attached in the sheet.
From the sheet, When the Status column will be new and ongoing, a table will be generated with column Title, Link and due date and send a single email to the recipients even they are repeated. In the sheet, For resource Anushka, Status New appeared twice and Ongoing once. The table will be like-
Anushka || New || 10/25/2022
Anushka || New || 10/25/2022
Anushka || Ongoing || 10/25/2022
And after creating it, it will send single email to each recipients though they have appeared several times. I have done it for getting multiple emails whatever the status is with the help of another commenter from stackflow but I want to modify it and change it. The code for this one is a bit longer as I have two helper gs file, html table code and the main one. That's why I am not writing all the codes here. But in the sheet from the extension, one can see my code.

If anyone give me suggestions how to change or modify the logic, it will be appreciated.

Code

function macro(){
  // get range of cell with data from A1 to any cell near having value (call data region)
  var table = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet3").getRange("A1").getDataRegion();
  var header=table.getValues()
  var resource=header[0][1]
  var status_r=header[0][3]
  var due_date_r=header[0][5]
  var link_r=header[0][10]
  
  // create custom table filtered by the column having header "State" where the value match "New"
  var filterTable = new TableWithHeaderHelper(table) 
                .getTableWhereColumn("Status").matchValueRegex(/(New)/);
                
  // for each row matching the criteria
  
  for(var i=0; i< filterTable.length() ; i++){
    // Get cell range value at column Mail
    var mail = filterTable.getWithinColumn("Email").cellAtRow(i).getValue();
    // Any other value of column Target Value
    var resource_col = filterTable.getWithinColumn("Resource").cellAtRow(i).getValue();
    var status_col = filterTable.getWithinColumn("Status").cellAtRow(i).getValue();
    var due_date_col = filterTable.getWithinColumn("Due Date").cellAtRow(i).getValue();
    var link_col = filterTable.getWithinColumn("Link").cellAtRow(i).getValue();
    var new_data=[[resource_col,status_col,due_date_col,link_col]]
    var htmltemplate=HtmlService.createTemplateFromFile("email")
    htmltemplate.resource=resource
    htmltemplate.status_r=status_r
    htmltemplate.due_date_r=due_date_r
    htmltemplate.link_r=link_r
    htmltemplate.new_data=new_data
    var htmlformail=htmltemplate.evaluate().getContent()
    
    var subjectMail =  "Automation Support Services Actions Items";
    var dt1 = new Date() 
    var dt2 = due_date_col

   // get milliseconds
   var t1 = dt1.getTime()
   var t2 = dt2.getTime()

   var diffInDays = Math.floor((t1-t2)/(24*3600*1000));
   // 24*3600*1000 is milliseconds in a day
    console.log(diffInDays);
    
    // Send email 
    MailApp.sendEmail({
      to:mail ,
      subject: subjectMail,
      htmlBody:htmlformail,
    });
  } 
}```
  • Please provide [mcve] – Cooper Oct 16 '22 at 10:30
  • You can use templated html to send a table via email. Here's an [example](https://stackoverflow.com/a/73493778/7215091) – Cooper Oct 16 '22 at 10:57
  • Hi Cooper, I have created the table via HTML in my existing code. The main problem is my previous code is sending multiple email to the recipients in every new status. But I want to send single email to the recipients though he has several projects which status is new and ongoing. whenever the status is new and ongoing for that recipient, it will generate table with those rows of the status and send a single email to the recipient. – Anushka Nahid Oct 16 '22 at 18:27
  • Okay I see that's a problem. How are you going to fix it? – Cooper Oct 16 '22 at 19:01
  • I don't know yet. I am searching for some logic and similar problems that people faced so I also can try. As far I understand that If I find out the way how I send only one mail though the recipients are same it can fix my problem as I know how to make the tables. – Anushka Nahid Oct 16 '22 at 19:45

1 Answers1

1

2 loops can make the job.

// get range of cell with data from A1 to any cell near having value (call data region)
var table = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet3").getRange("A1").getDataRegion();
// init html header data
var header=table.getValues()
var resource=header[0][1]
var status_r=header[0][3]
var due_date_r=header[0][5]
var link_r=header[0][10]

var listOfEmails = [];
var tableWithHeader = new TableWithHeaderHelper(table) 

// get all email
for(var i=0; i< tableWithHeader.length() ; i++){
  var mail = tableWithHeader.getWithinColumn("Email").cellAtRow(i).getValue();
  listOfEmails.push(mail)
}
// filter all email to get unique liste of email
var uniqueMailList = listOfEmails.filter((c, index) => {
    return listOfEmails.indexOf(c) === index;
});

for(var i=0; i< uniqueMailList.length; i++){
  // get mail of target i
  var mail = uniqueMailList[i]
  // filter table using mail of target i and status
  var mailTable = new TableWithHeaderHelper(table) 
                .getTableWhereColumn("Status").matchValueRegex(/(New)/)
                .getTableWhereColumn("Email").matchValue(mail);
  // initialise html template
  var htmltemplate=HtmlService.createTemplateFromFile("email")
  htmltemplate.resource=resource
  htmltemplate.status_r=status_r
  htmltemplate.due_date_r=due_date_r
  htmltemplate.link_r=link_r
  var new_data = []
  var htmlformail
  // loop into the filtered table of target i only
  for(var j=0; j< mailTable.length() ; j++){
    // Any other value of column Target Value
    var resource_col = mailTable.getWithinColumn("Resource").cellAtRow(j).getValue();
    var status_col = mailTable.getWithinColumn("Status").cellAtRow(j).getValue();
    var due_date_col = mailTable.getWithinColumn("Due Date").cellAtRow(j).getValue();
    var link_col = mailTable.getWithinColumn("Link").cellAtRow(j).getValue();
    new_data.push([resource_col,status_col,due_date_col,link_col])
  }
  htmltemplate.new_data=new_data
  htmlformail=htmltemplate.evaluate().getContent()

  var subjectMail =  "Automation Support Services Actions Items";
  var dt1 = new Date() 
  var dt2 = due_date_col

  // get milliseconds
  var t1 = dt1.getTime()
  var t2 = dt2.getTime()

  var diffInDays = Math.floor((t1-t2)/(24*3600*1000));
  // 24*3600*1000 is milliseconds in a day
  console.log(diffInDays);
    
  // Send email 
  MailApp.sendEmail({
    to:mail ,
    subject: subjectMail,
    htmlBody:htmlformail,
  });
}
            

I'm not confident on the new_data.push([resource_col,status_col,due_date_col,link_col]), it's seems to be corect but I have no no way to verify that

Anyway thanks for using the utils script at https://github.com/SolannP/UtilsAppSsript, glad to see it help

  • 1
    Hi Puygrenier, Thanks for saving me again. I tried it and this time I added Ongoing with it also and it is working perfectly. The .push method is also working. I just concat with the 'New status' data with the 'Ongoing' data and it seems fine. Thanks a lot for the help and sorry for the late reply because of Timezone. – Anushka Nahid Oct 17 '22 at 07:28
  • My plessure @AnushkaNahid, I'mm glad that you successfully mmnage to customized it ! Don't hesitate if you have any other question ! – Puygrenier Solann Oct 17 '22 at 10:21
  • Thanks a lot and of course I will ping if I face any other problems! – Anushka Nahid Oct 17 '22 at 11:36
  • Hi Puygrenier, have you ever attached links to the rows in HTML table in a way that the first link from the array will be added to the first row of the table, the second link to the next row and so on? Actually I have tried with href and it only takes the first element so I used foreach inside of anchor tag but it's not working. Do you ever encountered this kind of problems? – Anushka Nahid Oct 17 '22 at 18:34
  • hi @AnushkaNahid, I'm not use to handle HtmlService, you should look for a similar question or create a new question to get the best answer possible ! – Puygrenier Solann Oct 18 '22 at 06:42
  • Thanks for letting me know. I have posted a new question regarding this and also looking for similar problems. Thanks! – Anushka Nahid Oct 18 '22 at 07:07
  • hi @Puygrenier. Sorry to bother you again for this. I am facing a problem while sending the email based on the status. It seems like when there is no 'New' status for an individual email but that person has status for other condition then it can't be able to read the email address. It gives the error that 'this email address is not among possible cell values'. Thats why it can't be able to go to the next cell's email address though it has 'New' status. It gives the error on TableHelper macthValue function. Do u know what can be the reason and how to solve it. – Anushka Nahid Nov 14 '22 at 10:22
  • Hi @AnushkaNahid , that's a way to avoid to continue the code and have unknow behavior. You can add try{ var mailTable = new TableWithHeaderHelper(table) .getTableWhereColumn("Status").matchValueRegex(/(New)/) .getTableWhereColumn("Email").matchValue(mail); } catch (e) { continue; } In that way if there is in error while looking for a value it will just pass to the next iteration – Puygrenier Solann Nov 14 '22 at 16:27
  • Hi Puygrenier! I am sorry for the late reply. I tried with try statement but didn’t use continuous. Let me try with this hope it will work. Thanks a lot I will let u know how it goes – Anushka Nahid Nov 15 '22 at 17:26