How to send mails with some functionality using google apps script - javascript

I am new to Google Apps Script. I have a sheet that collects some "Order Number" from form submit. I want to send mails through an event (On form submit) from my spreadsheet. The form will serve an order number. When the form is submitted, it will match the older submitted order numbers throughout the whole column. If it got matched once, the mail won't be sent. If it doesn't match then it will send a mail to the email address next to the order number.
The email address will come from another sheet on the same spreadsheet using VLOOKUP. I managed to do this.
Sorry if I make any mistake with my English.
Edit:
I tried map() , filter() , indexOf() these methods. But I too new with this.
function search(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Copy of orderStatus");
var lr = ss.getLastRow() - 1;
var keyword = ss.getRange("H5").getValue();
var dataSource = ss.getRange(2, 2, lr, 1).getValues();
var mapped = dataSource.map(function(r){
return r[0]});
var showPos = mapped.indexOf(keyword) + 2;
var getMail = ss.getRange(showPos, 4).getValue();
var filted = mapped.filter(filterlogic);
}
var filterlogic = function(r){
if(r !== "zil20200010"){
return true;
} else {
return false;
}
}

On form submit, select the column (range) where you store all the order numbers and create a TextFinder and store it in a variable using the createTextFinder(findText) method for the specified range.
Get the TextFinder from the previous step and search the order number using the findNext() method.
If findNext() returns null then move to the next step. else, do nothing.
Get the email address to which you plan to send the order number.
After having the email address, use the sendEmail(recipient, subject, body, options) method to send the email. If you'd like, you can use HTML in the body to make it more professional.
For additional information, read:
the reference guide on creating TextFinders,
the reference guide on finding text using a TextFinder,
and the reference guide on GmailApp.
Sample code:
// imagine you store all the order numbers in column C, starting from row 2 to the last row in the column:
var emailRecipient = test#test.com;
var ordernumber = 123;
var RangeToSearch = sheet.getRange(2,3,sheet.getLastRow());
var TextFinder = RangeToSearch.createTextFinder(ordernumber);
var found = TextFinder.findNext();
if (found == null) {
MailApp.sendEmail({
to: emailRecipient,
subject: "New Order! Order Number: " + ordernumber,
htmlBody: html
});
}

First of all, thanks to all of you who helped me to reach this point. I found the solution to my problem after some "trial and error". I wanted to limit sending emails.
This code takes the Range. Get its values in an array. I mapped that array to act as a string. Then I added .pop() to that string, it removes our last/newly submitted data in that range. Then I used .includes() method to search my value in the mapped array, and assigned it to a variable called final (just came to my mind). This variable returns true/false depending on search results. If the order number does not exist then it returns false. After that, we set an if statement to execute our mailing function. If our order number does not match and return final as false our mailing function happens. Else it does nothing (means no email sents). And that's it!
Here is the code that solved my problem
function orderStatus(e) {
try {
var theirMail, subject, message;
var ourName, theirName;
var sSheet, orderNum, cosmetics, orderSts, phNum, lr,dataSource, mapped, final;
ourName = "My Company Name";
orderNum = e.namedValues["Order Number"].toString();
sSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("orderStatus");
lr = sSheet.getLastRow() - 1;
dataSource = sSheet.getRange(2, 2, lr).getValues();
mapped = dataSource.map(function(r){
return r[0].toString()});
mapped.pop();
final = mapped.includes(orderNum);
orderSts = sSheet.getRange(sSheet.getLastRow(),1).getValue();
theirMail = sSheet.getRange(sSheet.getLastRow(),4).getValue();
theirName = sSheet.getRange(sSheet.getLastRow(),5).getValue();
phNum = sSheet.getRange(sSheet.getLastRow(),6).getValue();
subject = "Order status notification from " + ourName + " to " + theirName;
if (final == false){
message =
"<div style='text-align: left; padding-left: 30px;'><h2>Dear <b>" + theirName +
",</b></h2><p>Your order no is <b><span style='font-size: 14px;'>" + orderNum +
"</span>.</b> <b><span style='font-size: 14px;'>Your order has been processed.</span>" +
"</b></p><p>We packaged your order and dropped it to the logistics. You will recieve phone call on <b><span style='font-size: 14px;'>" + phNum +
"</span></b> from logistics.<br>Thanks for purchasing from <b><span style='font-size: 14px;'>" + ourName +
"</span></b>.</p><p>Best regards,<br><b><span style='font-size: 14px;'>"+ourName+"</span></b></p></div>"+
"<p style='text-align: center;'><br><b>For further information please visit our facebook page <a href='https://www.facebook.com/' target='_blank' rel='noopener'>"+ourName+"</a>.</b></p><hr />";
textbody = message.replace("<br>", "\n\n");
cosmetics = {name: ourName, htmlBody: message};
MailApp.sendEmail(theirMail, subject, message, cosmetics);
}
}
catch (e) {
Logger.log(e.toString());
}
}

Related

Populate email subject line with form entries in Google Scripts

I am completely new to Google Scripts. I experimented with the script found here (as written by Snipe and edited by Govoni in the first comment).
What I am trying to do is combine both scripts, to get an email on form submit that would:
only show answered questions (it works)
format questions in bold (it works)
populate the subject line (I can't get it to work)
The code below works.
function newResponse()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formName = ss.getSheetByName('Form Responses 1');
var lastRow = formName.getLastRow();
var lastColumn = formName.getLastColumn();
var email = "sample#myemail.com";
var name = "My Email";
var subject = 'New form response: ';
var body = '';
var cell = '';
for (var i = 1; i <= lastColumn ; i++)
{
var title = formName.getRange(1,i).getDisplayValue();
var cell = formName.getRange(lastRow, i).getDisplayValue();
if (cell != '' && cell != 0)
{
body = body + '<b>'+ title + '</b>: ' + cell + '<br>';
};
};
MailApp.sendEmail({
to: email,
name: name,
subject: subject,
htmlBody: body
});
}
So, to try and add variable entries to the subject line I changed 'function newResponse()' to 'function newResponse(e)' and added this line before MailApp:sendEmail:
// The email subject line should look like this: "New form response: Item (Company, Country)"
// Item, Company and Country are the 2nd, 3rd and 4th columns from my form
subject += e.namedValues[title[1]].toString() + " (" + e.namedValues[title[2]].toString()+ ", "
+ e.namedValues[title[3]].toString()+ ")";
But when I do this, it doesn't send an email at all. If I change e.namedValues and instead put something like [title[0]], it then returns the first letter of the last question answered.
I am not quite sure what to try next?
From your code snippet, I suppose title variable holds a string, so title[0] is the first character of the string. e.namedValues[title[1]] will be undefined if no questions are single-character. undefined.toString() will throw an error, crashing the entire script.
You'll need to save an array of titles of all columns in the sheet.
var titles = [];
for (var i = 1; i <= lastColumn ; i++) {
var title = formName.getRange(1,i).getDisplayValue();
titles.push(title);
var cell = formName.getRange(lastRow, i).getDisplayValue();
...
}
Afterwards, you'll be able to use e.namedValues[titles[1]]. Note that I use titles, the array.
Subject is not a member of the advanced parameters object its just a mailapp.senEdmail parameter.
Try:
sendEmail(email, subject, '', {name: name, htmlBody: body});

Javascript - using form field values to determine which email address to use

Javascript newbie here, so apologies if this is incredibly basic and not the prettiest coding.
I'm creating a form that I want to have sent to a different email address depending on which team someone selects (e.g. if you select Sales it will generate an email to Team X, Refunds will email Team Y etc).
So far I've got to the stage where I can click a button to generate an email and attach the form as a PDF, but I don't know how to make it variable depending on the field value.
Current code:
var callerName = this.getField("CallerName").value;
var customSubject = this.getField("WhichTeam").value;
//I've used a fake email address for the next line variable, but this is the one I want to change depending on the "WhichTeam" field value
var mailtoUrl = "mailto:Email#email.com?subject=Callback Referral for " + customSubject;
this.submitForm({
cURL: mailtoUrl,cSubmitAs: "PDF"});
Hope this makes sense. Grateful for any help/advice?
Thanks
You can try using an object to contain the emails with the teams as they values. And to also use a template string to insert the value into the mailtoUrl.
var emails = {
refunds: 'refundsTeamEmail',
sales: 'salesTeamEmail',
}
var callerName = this.getField("CallerName").value;
var customSubject = this.getField("WhichTeam").value;
// ex. customSubject value is 'refunds'
// emails[customSubject] would be the same as doing emails.refunds
// which return the value of 'refundsTeamEmail'
var mailtoUrl = `mailto:${emails[customSubject]}?subject=Callback Referral for ` + customSubject;
this.submitForm({
cURL: mailtoUrl,cSubmitAs: "PDF"});
I think this is the simplest way to do it as the value will change each time you run the function to send the email without having to create or call other functions.
Having just said the last thing, you could also use a switch case in another function to return the value. If you want to. Something like:
function fetchEmail(email) {
switch(email) {
case 'refunds':
return 'refundsTeamEmail'
case 'sales':
return 'salesTeamEmail'
default:
return ''
}
}
var callerName = this.getField("CallerName").value;
var customSubject = this.getField("WhichTeam").value;
// ex. customSubject value is 'refunds'
// emails[customSubject] would be the same as doing emails.refunds
// which return the value of 'refundsTeamEmail'
var mailtoUrl = `mailto:${fetchEmail(customSubject)}?subject=Callback Referral for ` + customSubject;
this.submitForm({
cURL: mailtoUrl,cSubmitAs: "PDF"});

Google Sheets keeps sending emails

Been building a landing page to start an email list. Decided to use Google Sheets as the backend to store emails & Google Scripts to send the first welcome message.
I hooked up an HTML page to Google Sheets with an API. The user submits their name & email, and then it goes to the Google Sheets. When the document is edited, this function gets triggered which sends a welcome message.
To prevent duplicate messages from going out, I put a simple system in place. When a user has been emailed, the third row (C) is filled in with "EMAIL_SENT" automatically.
When the function is triggered, it should only send the user an email if if there is no "EMAIL_SENT" but every time a new user submits their info, every single email on the list gets another welcome message.
I will attach an image of the spreadsheet
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'EMAIL_SENT';
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow();
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 3);
// 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 emailAddress = row[0]; // First column
var nameThisMan = row[1]; // Person's name
var emailSent = row[2]; // Third column
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
var message = "Hey there " + nameThisMan + "," + "\n \n Thanks for joining the email list! You’re about to be getting some AMAZING programming resources. Here’s the link to the top 10 open source Github repos PDF. \n https://www.dropbox.com/s/wm8ctsdojlsoss6/10%20Most%20Useful%20Open%20Source%20Repos%20for%20Developers.pdf?dl=0\n\n And here’s the link to the archive of all the resources from this email list. These are from all past emails. \n https://docs.google.com/document/d/1hWmGNYkn0czRI29JJu9HgUVC6L4AsNYBxwt45ABnT6w/edit?usp=sharing \n \n Thank you again for joining the list! I will do my best to give you absolutely amazing programming resources. \n \n best, \n Michael Macaulay, Techtime.";
var replyTo = "TechTimeDev#gmail.com";
var subject = "Welcome to TechTime's Email List";
MailApp.sendEmail(emailAddress, replyTo, subject, message);
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
function sendEmails2() {
var sheet=SpreadsheetApp.getActiveSheet();
var startRow=2;
var numRows=sheet.getLastRow()-startRow+1;
var dataRange=sheet.getRange(startRow, 1, numRows, 3);
var data=dataRange.getValues();
for (var i=0; i < data.length; ++i) {
var row=data[i];
var emailAddress=row[0];
var nameThisMan=row[1];
var emailSent=row[2];
var replyTo="TechTimeDev#gmail.com";
var subject="Welcome to TechTime's Email List";
if (emailSent!='EMAIL_SENT') {
var message="Hey there " + nameThisMan + "," + "\n \n Thanks for joining the email list! You’re about to be getting some AMAZING programming resources. Here’s the link to the top 10 open source Github repos PDF. \n https://www.dropbox.com/s/wm8ctsdojlsoss6/10%20Most%20Useful%20Open%20Source%20Repos%20for%20Developers.pdf?dl=0\n\n And here’s the link to the archive of all the resources from this email list. These are from all past emails. \n https://docs.google.com/document/d/1hWmGNYkn0czRI29JJu9HgUVC6L4AsNYBxwt45ABnT6w/edit?usp=sharing \n \n Thank you again for joining the list! I will do my best to give you absolutely amazing programming resources. \n \n best, \n Michael Macaulay, Techtime.";
MailApp.sendEmail(emailAddress, replyTo, subject, message);
sheet.getRange(startRow + i, 3).setValue('EMAIL_SENT');
}
}
}
The method getLastRow() will return you the index of the last row with content. In the example you have provided this would be 3. However, what you actually want for performing getRange() is the number of rows you need to take. If you use three you would be taking an extra empty row and therefore, you would be getting the wrong values.
To change this to get the number of rows you need, you can simply do:
var numrows = sheet.getLastRow() - 1; instead of var numRows = sheet.getLastRow();
as you need to subtract from the index the number of rows you are not wanting to get in your range (in your case as you are ignoring the first row only 1 needs to be subtracted).

getValue not working on sheets

I'm trying to set up an email alert system based on a project tracking sheet my team uses at work. I need it to send an email when a task's status is changed to "Done" in column K. I got the code to work on a test sheet, but when I copy it to the live sheet the getValue() code stops working? Since the email is sent based on if() statements, the script runs, but doesn't actually work. I'm not sure if it's a permissions issue since I am not the owner of the live sheet?
I hope that is descriptive enough -- I have taught myself javascript in order to get this working and it seems so close, but I am stuck!!
Here is a screenshot of what the project tracking sheet looks like.
function emailUpdate(e) {
var emailInfoRange = sheet.getRange("B:O");
var edit = e.range.getA1Notation(); // Gets edited cell location
var editColumn = edit.substring(0,1) // Gets column of edited cell
var editRow = edit.substring(1,3) // Gets row of edited cell
if(editColumn == "K") { // gets all relevent information needed for email
var taskTypeCell = emailInfoRange.getCell(editRow,1);
var taskType = taskTypeCell.getValue();
var requestedByCell = emailInfoRange.getCell(editRow,3);
var requestedBy = requestedByCell.getValue();
var emailRequestCell = emailInfoRange.getCell(editRow,4);
var emailRequest = emailRequestCell.getValue();
var projectIdCell = emailInfoRange.getCell(editRow,5);
var projectID = projectIdCell.getValue();
var taskDescriptionCell = emailInfoRange.getCell(editRow,6);
var taskDescription = taskDescriptionCell.getValue();
var claimedByCell = emailInfoRange.getCell(editRow,9);
var claimedBy = claimedByCell.getValue();
var taskStatusCell = emailInfoRange.getCell(editRow,10);
var taskStatus = taskStatusCell.getValue();
if(taskStatus == "Done") {
if(emailRequest == "Yes" || emailRequest == "yes") { // Determines if status is "Done", and email notification is "Yes" or "yes"
var emailAddress;
var getEmailAddress = function(personelArray) { // Defines function to search email address arrays for the one that belongs to requestedBy
for (var i = 0; i < personelArray.length; i++) {
if(requestedBy === personelArray[i]) {
emailAddress = personelArray[i+1];
} } }
// Searches through all email arrays to find the one belonging to requester
getEmailAddress(specialistsAndEmails)
getEmailAddress(coordinatorsAndEmails)
getEmailAddress(managersAndEmails)
// Sends email
MailApp.sendEmail(emailAddress,
"AUTOGEN: " + taskType + " for " + projectID + " " + taskDescription + " completed by " + claimedBy + ".", "This email has been automatically generated by an edit to the work available sheet. \n"
+ "PLEASE DO NOT REPLY");
} else (Logger.log("No email requested"))
} else (Logger.log("Status not changed to done"))
} else (Logger.log("Update not to status cell"))
}
I would make the following changes to help prevent issues with string manipulations. Which could be the cause for your issues with getValues().
function emailUpdate(e) {
var emailInfoRange = sheet.getRange("B:O");
var edit = e.range // Gets edited cell location
var editColumn = edit.getColumn() // Gets column of edited cell
var editRow = edit.getRow() // Gets row of edited cell
if(editColumn == 11) // Column K should correspond to column number 11, if i can count correctly.
{
/// Remainder of the code should be the same as above
}
}
So instead of converting the range to A1 notation, you should get column number and row number using getColumn and getRow() on the range object. This will prevent issues with text to number manipulation and could be the cause of your problems.

Google Script maker to format a spreadsheet

This is my first time posting so bear with me if I leave any crucial details out.
Anyway, to summarize the problem: I have been trying to get a script to work on Google Script maker to format a spreadsheet which is hooked up to a form, to go straight to my email.
So basically User Form --> Spreadsheet --> My Email
The questions are pretty Standard:
What's the problem?
Where are you located
However the one question I'd like to use is "What is the priority of this problem?" High or low. I have it under multiple choice format so its a simple choice.
Psuedocode for what I want:
if (priority = low) put #priority low onto the email
Simple enough, however I can't seem to get it to work, here's my code:
function sendFormByEmail(e)
{
// Remember to replace XYZ with your own email address
var email = "email";
var subject = "Help Desk Form Submitted";
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
var priority = "";
if(message.indexOf("What is the priority of this problem? = Low")){
priority += "#priority low";
}
else
priority == "GFHHFFHAHFH ";
for(var i in headers){
message += headers[i] + ' = \t \t'+ e.namedValues[headers[i]].toString() + "\n\n"; }
if (message.indexOf("What is the priority of this problem? = Low"))
message += "This is a test";
else
message += "This is not a test";
MailApp.sendEmail(email, subject, message);
}
Let's look at the first instance of if(message.indexOf().... It's got some problems:
A few lines earlier, message was set to an empty string... so you won't find the "priority" string in it.
The if statement is treating the return of indexOf() as a Boolean. However, the return code from .indexOf() is -1 when an item is not found, which is "true-ish". If the string IS found, and is located at the start of the search subject, the return will be 0, which is "false-ish". If it is found at any other location, the value will be `>0', also "true-ish".
In the else, there's a typo. The comparison == should be assignment =, or += if you prefer.
Looking at the surrounding code, this piece looks like it was left-over from a previous version, and can be deleted.
Now look at the second instance.
The message should now be populated. However, the comparison is still using an incorrect Boolean interpretation of .indexOf().
The search string contains a batch of spaces... but the previous code that looped through responses used tabs to separate the "header" from the "value", so the search will always return '-1' (which will be interpreted as true).
There are a couple of other tidy-up items. You probably need:
function sendFormByEmail(e)
{
Logger.log(JSON.stringify(e));
var email = Session.getEffectiveUser().getEmail();
var subject = "Help Desk Form Submitted";
var message = "";
var s = e.range.getSheet(); // Sheet that received form response
var headers = s.getDataRange().getValues()[0];
for (var question in headers) {
message += headers[question] + ' = \t\t' + e.values[question] + '\n\n';
}
// Add text relative to the priority of the reported issue.
if (e.namedValues["What is the priority of this problem?"].toString() === "Low")
message += "This is a test";
else
message += "This is not a test";
Logger.log(message);
MailApp.sendEmail(email, subject, message);
}
PS: You can see why it would be advisable to keep form questions short, like "Priority", and leave the explanatory sentence to be helper text!

Categories