Automated duplicate check & bcc using Google Script - javascript

I wrote this JS to send email automatically using Google Script into a spreadsheet.
Unfortunately, the duplicate check is not working, and the bcc line trigger an error.
Actually I want to send an email only for the LAST answer into the spreadsheet everytime.
Could you help me?
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = active;
var dataRange = sheet.getRange(startRow, 1, numRows, 14)
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var name = row[2];
var surname = row[3];
var salesRepEmail = row[4];
var qualityAnalystEmail = "john#doe.com"
var customerEmail = row[5];
var websiteURL = row[6];
var solution1 = row[7];
var solution2 = row[8];
var solution3 = row[9];
var toResolve1 = row[10];
var toResolve2 = row[11];
var toResolve3 = row[12];
var checkDate = row[13];
var message = 'Bonjour '+ name + ' ' + surname + ', ' + 'blablabla';
var emailSent = row[14]; // Third column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "Votre Optimisation De Site Mobile pour " +websiteURL;
MailApp.sendEmail(customerEmail, subject, message, {
cc: "",
bcc: qualityAnalystEmail,+ " " + salesRepEmail,
});
sheet.getRange(startRow + i, 15).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}

Your code is triggering on bcc line cause you put a extra comma. As seen on the documentation, the bcc parameters should be a string with
a comma-separated list of email addresses to BCC
In your cas, you should'nt have:
bcc: qualityAnalystEmail,+ " " + salesRepEmail
but:
bcc: qualityAnalystEmail + ", " + salesRepEmail
which gives:
MailApp.sendEmail(customerEmail, subject, message, {
cc: "",
bcc: qualityAnalystEmail+ ", " + salesRepEmail
});
(You also put a extra comma after your bcc parameters which is not good)

Thank you so much , Please find below the datas and the script.
I will try to call the variables into the HTML afterwards using Google Scriptlet. For the moment, the simple text is sufficient. It seems to be working like that, but the code is not clean.
Image Du Tableau
// This constant is written in column O for rows for which an email
// has been sent successfully.
var EMAIL_SENT = "EMAIL_SENT";
function testSchemas() { {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = sheet.getLastRow();
var numRows = 1; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 15)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var name = row[2];
var surname = row[3];
var salesRepEmail = row[4];
var qualityAnalystEmail = "xxx#yyy.com"
var customerEmail = row[5];
var websiteURL = row[6];
var solution1 = row[7];
var solution2 = row[8];
var solution3 = row[9];
var toResolve1 = row[10];
var toResolve2 = row[11];
var toResolve3 = row[12];
var checkDate = row[13];
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
Logger.log(doGet);
var htmlBody = HtmlService.createHtmlOutputFromFile('Index').getContent();
var message = 'Bonjour '+ name + ' ' + surname + ', ' + 'c\'est avec grand plaisir que je vous écris pour résumer ... - '+solution1+' \n\n- '+solution2+' \n\n- '+solution3+' \n\nMalgré...';
var emailSent = row[14]; // Third column
if (emailSent != "EMAIL_SENT") { // Prevents sending duplicates
/*MailApp.sendEmail(customerEmail, subject, message, {
cc: "",
bcc: qualityAnalystEmail + ", " + salesRepEmail
}); */
MailApp.sendEmail({
to: customerEmail,
bcc: qualityAnalystEmail + ", " + salesRepEmail,
subject: 'Résumé De Notre Consultation Du Site Mobile ' + websiteURL,
htmlBody: htmlBody,
});
}
Logger.log(name);
sheet.getRange(startRow + i, 15).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}

Related

How can I add a hyperlink to a javascript message?

Im trying to send an email from google sheets and I've setup the columns to represent the subject, text and email addresses. The problem is that I need to add a hyperlink in the middle of the message and im stuck here. I can't get the paragraph to format correctly AND have the hyperlink replace a word in the middle of the sentence.
This is the code:
function AISEMAIL() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet1=ss.getSheetByName('Email Addresses');
var sheet2=ss.getSheetByName('Email Fields');
var subject = sheet2.getRange(2,1).getValue();
var message = sheet2.getRange(2,2).getValue();
var calendardisplayname = sheet2.getRange(2,3).getValue();
var calendarlink = sheet2.getRange(2,4).getValue();
var formdisplayname = sheet2.getRange(2,5).getValue();
var formlink = sheet2.getRange(2,6).getValue();
message=message.replace("<calendar>",calendardisplayname).replace("<form>",formdisplayname);
var n=2;
for (var i = 2; i < n+1 ; i++ ) {
var emailAddress = sheet1.getRange(i,1).getValue();
let options = {
htmlBody: message
+ '' + calendardisplayname + ''
+ '' + formdisplayname + ''
}
GmailApp.sendEmail(emailAddress, subject, message,options);
}
}
Problem:
You are always trying to append the links at the end on your options. Also, it becomes redundant. What you need to do is include the links when you replace the values of <calendar> and <form>.
Code:
// Add the links on the replace
message = message
.replace("<calendar>", '' + calendardisplayname + '')
.replace("<form>", '' + formdisplayname + '');
var n = 2;
for (var i = 2; i < n + 1; i++) {
var emailAddress = sheet1.getRange(i, 1).getValue();
let options = {
htmlBody: message
}
GmailApp.sendEmail(emailAddress, subject, message, options);
}
Old Output:
New Output:
This is just a guess, but could you use HtmlService to create your html message?
function AISEMAIL() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet1=ss.getSheetByName('Email Addresses');
var sheet2=ss.getSheetByName('Email Fields');
var subject = sheet2.getRange(2,1).getValue();
var message = sheet2.getRange(2,2).getValue();
var calendardisplayname = sheet2.getRange(2,3).getValue();
var calendarlink = sheet2.getRange(2,4).getValue();
var formdisplayname = sheet2.getRange(2,5).getValue();
var formlink = sheet2.getRange(2,6).getValue();
message=message.replace("<calendar>",calendardisplayname).replace("<form>",formdisplayname);
var n=2;
for (var i = 2; i < n+1 ; i++ ) {
var emailAddress = sheet1.getRange(i,1).getValue();
//ADDED htmlText VARIABLE
var htmlText;
let options = {
// ADDED HtmlService.createHtmlOutput()
htmlBody: htmlText = HtmlService.createHtmlOutput(message
+ '' + calendardisplayname + ''
+ '' + formdisplayname + '');
}
// CHANGED message TO htmlText
GmailApp.sendEmail(emailAddress, subject, htmlText,options);
}
}
REFERENCES
HtmlService
Also, if you need to create dynamic html for each email, check out these links...
createTemplateFromFile()
.evaluate()
Templated HTML

Google Sheet Auto Email Script

I have a form that contains 84 questions, not all of them are mandatory.
This is the script I manage to write so far:
function SendEmail() {
var ActiveSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var StartRow = 2;
var RowRange = ActiveSheet.getLastRow() - StartRow + 1;
var WholeRange = ActiveSheet.getRange(StartRow,1,RowRange,84);
var AllValues = WholeRange.getValues();
var message = "";
for (i in AllValues) {
var CurrentRow = AllValues[i];
var EmailSent = CurrentRow[85];
if (EmailSent == "Sent")
continue;
# I know this part takes only the first 5 column, I wrote them only as an example. In bold the headers of each column.
message =
"<p><b>Kind of content: </b>" + CurrentRow[2] + "</p>" +
"<p><b>Project Name: </b>" + CurrentRow[3] + "</p>" +
"<p><b>Project Description: </b>" + CurrentRow[4] + "</p>" +
"<p><b>Name of your team: </b>" + CurrentRow[5] + "</p>" +
"<p><b>Scope of work: </b>" + CurrentRow[6] + "</p>";
var setRow = parseInt(i) + StartRow;
ActiveSheet.getRange(setRow, 85).setValue("sent");
}
var SendTo = "email#gmail.com";
var Subject = "New"+" " + CurrentRow[2] +" "+"project request";
MailApp.sendEmail({
to: SendTo,
cc: "",
subject: Subject,
htmlBody: message,
});
}
What I want is to send an email every time somebody fills the form and the content of the email should include only the last row and only the columns with data with their header.
The way this script is written will generate an email with 84 rows, most of them empty and not relevant. Can somebody give me a hand with it?
Thank you so much for your help!!
You can use sheet.getLastRow() to get the index of the last row in the sheet that has data.
For finding columns that have data, you can iterate through the row data and look for cell values that are not blank.
var header = sheet
.getRange(1,1,1,sheet.getLastColumn())
.getDisplayValues()[0];
var data = sheet
.getRange(sheet.getLastRow(),1,1,sheet.getLastColumn())
.getDisplayValues()[0];
var output = [];
for (var d=0; d<data.length; d++) {
if (data[d] !== "") {
output.push(header[d] + " = " + data[d]);
}
}
return data.join("\n");
I know you are too naive to coding and Amit is a busy person, so just to help you, I am plugging in the code he has provided to your code with a small correction, so you can just copy the entire code :)
function SendEmail() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lRow = sheet.getLastRow();
var emailSent = sheet.getRange(lRow, 86).getValue();
var header = sheet
.getRange(1,1,1,sheet.getLastColumn())
.getDisplayValues()[0];
if (emailSent != "Sent"){
var data = sheet
.getRange(lRow,1,1,sheet.getLastColumn())
.getDisplayValues()[0];
var output = [];
for (var d=0; d<data.length; d++) {
if (data[d] !== "") {
output.push(header[d] + " = " + data[d]);
}
}
var message = output.join("\n");
var SendTo = "email#gmail.com";
var Subject = "New"+" " + sheet.getRange(lRow, 3).getValue() +" "+"project request";
MailApp.sendEmail({
to: SendTo,
cc: "",
subject: Subject,
htmlBody: message,
});
sheet.getRange(lRow, 86).setValue("sent");
}
}
You can use filter, for example
var AllValues = WholeRange.getValues().filter( row => row[5] != '');
will reduce AllValues to only those there column 6 isn't empty

Correct script to send only the last row of data in Google Sheets

The script I have is sending out the information in the format I want. The problem I have is that it is sending out each row as an indiviual email instead of only sending out the latest data. I only want the last row of data to be sent out.
function CustomEmail() {
var sheet = SpreadsheetApp.getActiveSheet();
lastRow = sheet.getLastRow();
startrow= 2;
var range = sheet.getRange("A2:Z1000");
var UserData = range.getValues();
for (i in UserData) {
var row = UserData[i];
var name = row[2];//market
var senderEmail = ''
if (name === 'South')
{senderEmail = 'tom#no.com';}
else if (name === 'West')
{senderEmail = 'bob#bob.com';}
else if (name === 'East')
{senderEmail = 'non#no.com';}
var AgentOwner = row[18];//Agent Owner
var address = row[20];//Address
var City = row[21];//City
var State = row[22]//state
var Incident = row[17]//incident type
var Date = row[4]//date and time
emailBody = "New Security Incident Report from: " +AgentOwner+ "\nAddress: " +address+ "\nCity: " +City+ "\nState: " +State + "\nIncident: " +Incident + "\nDateTime:" +Date
MailApp.sendEmail(senderEmail,"Security Incident Report", emailBody);
}
}
Try this -
function CustomEmail() {
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getRange(sheet.getLastRow(), 1, 1, sheet.getLastColumn())[0];
Logger.log(row);
var name = row[2]; //market
var senderEmail = '';
if (name === 'South') {
senderEmail = 'tom#no.com';
} else if (name === 'West') {
senderEmail = 'bob#bob.com';
} else if (name === 'East') {
senderEmail = 'non#no.com';
}
var AgentOwner = row[18]; //Agent Owner
var address = row[20]; //Address
var City = row[21]; //City
var State = row[22]; //state
var Incident = row[17]; //incident type
var Date = row[4]; //date and time
emailBody =
'New Security Incident Report from: ' +
AgentOwner +
'\nAddress: ' +
address +
'\nCity: ' +
City +
'\nState: ' +
State +
'\nIncident: ' +
Incident +
'\nDateTime:' +
Date;
MailApp.sendEmail(senderEmail, 'Security Incident Report', emailBody);
}
Edit:
Go to script, paste new code, run the function, then in menu, View > Log and see if the row values are logged properly. If any issues with data indices, adjust them accordingly.

Google Script Time-Based Trigger -> Asking for Authorization all the time

So I have this google script function that reads information from a google spreadsheet and sends an email with the data. I set up a time-based trigger that activates every day at a certain hour but the problem is that every time it triggers the script ask for authorization so basically what I'm receiving is the email with this "time-based" error that asks for authorization.
The function self-works perfectly when I manually execute it and confirm the authorization myself.
I set up the time-based trigger via code and the trigger option of the scripts but none of them seems to work.
Do you guys know a way to always keep the authorization on so the trigger can work and send the email with the data?
so to add some additional information here, this is the code I'm using right now:
The spreadsheet is shared between two people, me and a co-worker.
If I manually execute this script, it will ask for authorization and then send to my email the data I need. My problem comes when I tried to set up a trigger to automatically execute this script. Every time the trigger execute the script I get an email saying that it needs authorization.
Function: emailCarts
Error Message: Authorization is required to perform this action. Activation: Time-Based
function emailCharts(sheet,emails,emailSubject){
var ss = SpreadsheetApp.openById("SPREADSHEET_ID");
var sheet = SpreadsheetApp.openById("SPREADSHEET_ID").getSheetByName("Graficos");
var emailSubject = 'Reporte Automático Reclamos y Sugerencias ' + Utilities.formatDate(sheet.getRange("B2").getValue(),ss.getSpreadsheetTimeZone(),"dd/MM/yy");
var emails = 'MY_EMAIL'; // your email ID
var charts = sheet.getCharts();
var sheet2 = SpreadsheetApp.openById("SPREADSHEET_ID").getSheetByName("Tabla");
var schedRange = sheet2.getDataRange();
var body = '<div style="text-align:left;display: inline-block;font-family:
arial,sans,sans-serif">'
body += '<H1>'+ 'Reclamos Abiertos ' +'</H1>';
body += getHtmlTable(schedRange);
body += '</div><br>';
debugger;
if(charts.length==0){
MailApp.sendEmail({to: emails,subject: "ERROR:"+emailSubject,htmlBody: "No hay
gráficos en el spreadsheet"});
return;
}
var chartBlobs = new Array(charts.length);
var emailBody = "Estimados,<br><br> Junto con saludar, se hace envío del reporte
automático de los Reclamos/Sugerencias/Felicitaciones Abiertos y Cerrados,
correspondiente a la fecha: "
+ Utilities.formatDate(sheet.getRange("B2").getValue(),ss.getSpreadsheetTimeZone(),"dd/MM/yy");
var emailImages = {};
for(var i=0;i<charts.length;i++){
var builder = charts[i].modify();
builder.setOption('vAxis.format', '#');
var newchart = builder.build();
chartBlobs[i] = newchart.getAs('image/png');
emailBody = emailBody + "<p align='center'><img src='cid:chart"+i+"'></p>";
emailImages["chart"+i]= chartBlobs[i];
}
for (var i = 0; i < emails.length; i++){
MailApp.sendEmail({to: emails[i], subject: emailSubject, htmlBody: emailBody+body, inlineImages: emailImages});
}
}
function getHtmlTable(range){
var ss = range.getSheet().getParent();
var sheet = range.getSheet();
startRow = range.getRow();
startCol = range.getColumn();
lastRow = range.getLastRow();
lastCol = range.getLastColumn();
// Read table contents
var data = range.getValues();
// Get css style attributes from range
var fontColors = range.getFontColors();
var backgrounds = range.getBackgrounds();
var fontFamilies = range.getFontFamilies();
var fontSizes = range.getFontSizes();
var fontLines = range.getFontLines();
var fontWeights = range.getFontWeights();
var horizontalAlignments = range.getHorizontalAlignments();
var verticalAlignments = range.getVerticalAlignments();
// Get column widths in pixels
var colWidths = [];
for (var col=startCol; col<=lastCol; col++) {
colWidths.push(sheet.getColumnWidth(col));
}
// Get Row heights in pixels
var rowHeights = [];
for (var row=startRow; row<=lastRow; row++) {
rowHeights.push(sheet.getRowHeight(row));
}
// Future consideration...
var numberFormats = range.getNumberFormats();
// Build HTML Table, with inline styling for each cell
var tableFormat = 'style="border:1.5px solid black;border-collapse:collapse;text- align:center" border = 1.5 cellpadding = 5';
var html = ['<table '+tableFormat+'>'];
// Column widths appear outside of table rows
for (col=0;col<colWidths.length;col++) {
html.push('<col width="'+colWidths[col]+'">')
}
// Populate rows
for (row=0;row<data.length;row++) {
html.push('<tr height="'+rowHeights[row]+'">');
for (col=0;col<data[row].length;col++) {
// Get formatted data
var cellText = data[row][col];
if (cellText instanceof Date) {
cellText = Utilities.formatDate(
cellText,
ss.getSpreadsheetTimeZone(),
"dd/MM/yy");
}
var style = 'style="'
+ 'color: ' + fontColors[row][col]+'; '
+ 'font-family: ' + fontFamilies[row][col]+'; '
+ 'font-size: ' + fontSizes[row][col]+'; '
+ 'font-weight: ' + fontWeights[row][col]+'; '
+ 'background-color: ' + backgrounds[row][col]+'; '
+ 'text-align: ' + horizontalAlignments[row][col]+'; '
+ 'vertical-align: ' + verticalAlignments[row][col]+'; '
+'"';
html.push('<td ' + style + '>'
+cellText
+'</td>');
}
html.push('</tr>');
}
html.push('</table>');
return html.join('');
}

Google Sheet two lines cell with getValue()

I made a small script to send text via email from a spreadsheet.
I got the text of the cells using .getValue() but when my cells have two or more lines (Ctrl+enter) it just put them on the same line in the table I'm sending in the email.
I'd like to know if there is a way to keep the GoogheSheet formatting when extracting it with .getValue() or if I need to reprocess the string, and if so, how do I make any RE detect the new line...?
Here is the coding I used to extract the cells:
function readInList(debR, col){
/* Documentation
La routine lit chaque cellule d'un range de 1 col par 5 row et stock les valeurs dans une liste au format texte.
retourne cette liste
*/
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var stopRow = debR + 5;
var opCol = col;
var rangeList = [];
var i;
for (i=debR; i < stopRow; i++){
var cell = sheet.getRange(i, col);
rangeList.push(cell.getValue());
}
return (rangeList);
}
So the Mail sends a reconstructed table with the text, and all of this is inseted inside a html Mail:
function weeklyReport() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var rowMonth = [31,28,31,30,31,30,31,30,31,30,31,30];
var today = new Date();
var todayYear = today.getYear();
var todayMonth = today.getMonth();
var todayDate = today.getDate();
// Calc the number of rows depending of months that have passed
var rowCell=0;
var i = 0;
do {
rowCell+=rowMonth[i];
i++;
} while (i < todayMonth);
rowCell+=3 + todayDate
var range1 = readInListD(rowCell-4, 1);
var range2 = readInList(rowCell-4, 4);
var subject = 'Weekly report Clem Michard';
var greetings = 'Hi, ';
var sentence = 'please find my weekly report below:';
var table = textToTable(range1, range2);
var signature = 'Clem';
var tables = today;
var cmEmail= '***';
var owaEmail = '***';
var headEmail = '***';
var htmlBodyA =
"<html>"+
"<head>"+
"<style>"+
"table, th, td {"+
"border: 1px solid black;"+
"border-collapse: collapse;"+
"}"+
"</style>" +
"</head>"+
"<body>"+
"<p>" + greetings + "</p>"+
"<p>" + sentence + "</p>"+
"<pre>" + table + "</pre>"+
"<p>" + signature + "</p>"+
"</body>"+
"</html>";
/*- Message envoyé aux particpants avec un e-mail valide -*/
MailApp.sendEmail({
to: headEmail,
bcc: cmEmail,
subject: subject,
name: "Clément Michard",
replyTo: cmEmail,
htmlBody: htmlBodyA})
}
And use this to compose the table:
function textToTable(col1, col2){
/*
This method converts a list of str into an HTML table
takes 2 lists to build a table.
*/
var listC1, listC2, text, lLen, i, j;
listC1 = col1;
listC2 = col2;
lLen = listC1.length;
text = "<table><tr><th>" + "Date" + "</th><th>" + "Report" + "</th></tr>";
for (i = 0; i < lLen; i++){
text += "<tr><td>" + listC1[i] + "</td><td>" + listC2[i] + "</td></tr>";
}
text += "</table>";
return(text);
}

Categories

Resources