The code below works perfectly and sends the email I need it to send on an "OnChange" trigger. However, it sends an email for EVERY checked box in row 7 which is overload, it just needs to send an email for newly checked boxes.
Any advice on how to add a condition in the below code for this?
function sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Service');
var data = sheet.getDataRange().getValues();
for (var i = data.length - 1; i >= 1; i--) {
if (sheet.getRange(i,7).isChecked()){
var name = sheet.getRange(i,1).getValue();
var last = sheet.getRange(i,2).getValue();
var body = name + " " + last
var subject = 'New Service Item in Stock'
MailApp.sendEmail('me#mycompany.com', subject, body);
}
}
}
I haven't tried anything because there is nothing I could find online to get me in the right direction.
https://i.stack.imgur.com/cKfLv.png
Try unchecking them after you send them:
function sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Service');
var data = sheet.getDataRange().getValues();
for (var i = data.length - 1; i >= 1; i--) {
if (sheet.getRange(i, 7).isChecked() && sheet.getRange(i,8).getValue() != "Sent") {
var name = sheet.getRange(i, 1).getValue();
var last = sheet.getRange(i, 2).getValue();
var body = name + " " + last
var subject = 'New Service Item in Stock'
MailApp.sendEmail('me#mycompany.com', subject, body);
sheet.getRange(i, 8).setValue("Sent");
}
}
}
Performance improvement:
function sendEmails() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName('Service');
var vs = sh.getRange(2, 1, sh.getLastRow() - 1, sh.getLastColumn()).getValues();
vs.forEach((r, i) => {
if (sh.getRange(i + 2, 7).isChecked() && r[7] == "Sent") {
let body = `${r[0]} ${r[1]}`;
let subject = "New Service Item in Stock";
MailApp.sendEmail('me#mycompany.com', subject, body);
sh.getRange(i, 8).setValue("Sent");
}
});
}
Related
I'm looking on form submit to send an email to the submitter if they filled any of the questions as false, but the script is sending emails to any submitter who entered all true as well. I know the if script works with numbers as I used it in another project but when I changed the question to true false it seems to have broken the if statement. I also know the rest of the script works because it worked before I added the "if (certification == 'FALSE') {" line.
var EMAIL_SENT = 'EMAIL_SENT';
var FALSE = 'FALSE';
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = 20;
var dataRange = sheet.getRange(startRow, 1, numRows, 20);
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[4];
var message = 'Test'
var emailSent = row[9];
var certification = row[5]
if (certification == 'FALSE') {
if (emailSent !== EMAIL_SENT) {
var subject = 'Self-Certification Alert';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 10).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
}
}
Please try amending to the following:
var EMAIL_SENT = 'EMAIL_SENT';
var FALSE = 'FALSE';
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = 20;
var dataRange = sheet.getRange(startRow, 1, numRows, 20);
var data = dataRange.getValues();
var error=0;
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[4];
var message = 'Test'
var emailSent = row[9];
var certification = row[5]
if (certification == 'FALSE') {
error++;
}
}
if (emailSent !== EMAIL_SENT && error >0) {
var subject = 'Self-Certification Alert';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 10).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
I ended up changing it to the following code and got it to work.
enter code here
var EMAIL_SENT = 'EMAIL_SENT';
var TRUE = 'true';
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = 20;
var dataRange = sheet.getRange(startRow, 1, numRows, 20);
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[4];
var message = 'Test'
var emailSent = row[9];
var certification = row[5]
if (certification !== true) {
if (emailSent !== EMAIL_SENT) {
var subject = 'Self-Certification Alert';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 10).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
}
}
I have a Google apps script JS function, which was executing and doing its job just fine. All of a sudden, an error started appearing: 'Script sendReply experienced an error'. When I try to open the Details, no info appears, just the same message with no actual details. The related Stackdriver logs appear only 10-15 minutes after execution, with Unknown outcome status.
The function itself continues working normally, successfully executing some HTTP requests with UrlFetchApp (if that matters). I'm really struggling to look for a root for that pop-up, as no changes to the script itself were made lately.
function sendReply() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.toast('Sending letters...');
var sheet = ss.getActiveSheet();
var sheetName = sheet.getSheetName();
var commentType = getCommentType(sheetName);
var startRow = 3;
var lastRow = sheet.getLastRow();
var numCols = sheet.getLastColumn();
var dataRange = sheet.getRange(3, 1, lastRow - 2, numCols);
var data = dataRange.getValues();
var numSent = 0;
for (var i = 0; i < data.length; i++) {
var row = data[i];
var ticketId = row[0];
var body = row[2];
var status = row[6];
if (status == "Done" && body !="") {
createComment(ticketId, body, commentType);
sheet.getRange(startRow + i, 7).setValue("Sent");
sheet.getRange(startRow + i, 9).setValue(new Date());
numSent++;
}
}
SpreadsheetApp.flush();
if (numSent > 0) {
ss.toast('Sent ' + numSent + ' new letters.')
} else {
ss.toast('No letters sent.')
}
dataRange.sort({column: 7, ascending: false});
}
Well we have this google form and the details are being added to google sheet with custom g apps scripts. When the details have been appended to the google sheet log, it should send email. If I run the sendmail() manually, it works but when I call it inside onFormSubmit(), it's not working. What could have gone wrong?
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var templateLink = sheet.getSheetByName("Template Link").getRange(1, 1).getValue();
var logSheet = sheet.getSheetByName("Log");
var formResponsesSheet = sheet.getSheetByName("Form Responses 1");
var formResponsesHeader = formResponsesSheet.getRange(1, 2, 1, formResponsesSheet.getLastColumn() -1).getValues();
var newFileName = e.namedValues['Name'][0] + "-" + e.namedValues['Date'][0];
var populatedDocsFolder = DriveApp.getFolderById("1yTSd7W0U4Gcsm6CIw8NtD022F-MA7CPx");
var templateDocID = DocumentApp.openByUrl(templateLink).getId();
var newDocID = DriveApp.getFileById(templateDocID).makeCopy(newFileName, populatedDocsFolder).getId();
var newDocLink = DriveApp.getFileById(newDocID).getUrl();
var newDoc = DocumentApp.openById(newDocID);
var newDocBody = newDoc.getBody();
for (i = 0; i < formResponsesHeader[0].length; i++) {
var thisHeader = formResponsesHeader[0][i];
var thisValue = e.namedValues[thisHeader][0];
newDocBody.replaceText("<<" + thisHeader + ">>", thisValue);
}
//Log
var name = e.namedValues['Name'][0];
var email = e.namedValues['Email'][0];
var date = e.namedValues['Date'][0];
logSheet.appendRow([name,email,date,newDocID]);
//Trigger
ScriptApp.newTrigger("sendEmail").timeBased().after(15000).create();
//sendEmail();
}
function sendEmail() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var logSheet = sheet.getSheetByName("Log");
var logSheetData = logSheet.getDataRange().getDisplayValues();
var templateName = sheet.getSheetByName("Template Name").getRange(1, 1).getValue();
for (i = 1; i < logSheetData.length; i++) {
if (logSheetData[i][4] == "") {
//SEND EMAIL
var name = logSheetData[i][0];
var email = logSheetData[i][1];
var date = logSheetData[i][2];
var id = logSheetData[i][3];
var pdfName = templateName + "-" + name + "-" + date;
//PDF EMAIL
try{
var doc = DriveApp.getFileById(id);
var blob = doc.getBlob().getAs('application/pdf').setName(pdfName + ".pdf");
var subject = 'Document Created';
//GmailApp.sendEmail(email, subject, "This is just a test", {attachments: [blob]});
MailApp.sendEmail(email, subject, "", {attachments: [blob], name: pdfName});
}catch(err){
continue;
}
//Log Sheet Update
logSheet.getRange(i + 1, 5).setValue("Sent");
}
}
}
function onOpen() {
SpreadsheetApp.getUi().createMenu("Custom Menu")
.addItem("Build Form Submit Trigger", "formSubmitTrigger")
.addSeparator()
.addItem("Send Email", "sendEmail")
.addSeparator()
.addItem("Mismatch Check", "mismatchCheck")
.addToUi();
}
function formSubmitTrigger() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
ScriptApp.newTrigger("onFormSubmit").forSpreadsheet(sheet).onFormSubmit().create();
}
function mismatchCheck() {
var result = "";
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var templateLink = sheet.getSheetByName("Template Link").getRange(1, 1).getValue();
var formResponsesSheet = sheet.getSheetByName("Form Responses 1");
var formResponsesHeader = formResponsesSheet.getRange(1, 2, 1, formResponsesSheet.getLastColumn() -1).getValues();
var docBody = DocumentApp.openByUrl(templateLink).getBody().getText();
var matches = docBody.match(/<</g); var noOfLessThanMatches = matches.length;
var matches = docBody.match(/>>/g); var noOfMoreThanMatches = matches.length;
var lessThan = docBody.search(/<</g);
var moreThan = docBody.search(/>>/g);
Logger.log([noOfLessThanMatches,noOfMoreThanMatches]);
result += "<b>Less Than Signs:</b> " + noOfLessThanMatches + "<br>";
result += "<b>More Than Signs:</b> " + noOfMoreThanMatches + "<br>";
result += "<br><b>Doc to Form Check</b><br>";
var newDocBody = docBody;
var reverseArray = [];
for (i = 0; i < noOfLessThanMatches; i++) {
var lessThan = newDocBody.search(/<</g);
var moreThan = newDocBody.search(/>>/g);
var subString = newDocBody.substring(lessThan + 2,moreThan);
Logger.log(subString);
var indexOf = formResponsesHeader[0].indexOf(subString);
if (indexOf > -1) {
result += subString + " - FOUND<br>";
} else {
result += subString + " - NOT FOUND<br>";
}
reverseArray.push(subString);
newDocBody = newDocBody.replace("<<" + subString + ">>","XX")
}
result += "<br><b>Form to Doc Check</b><br>";
for (z = 0; z < formResponsesHeader[0].length; z++) {
var thisString = formResponsesHeader[0][z];
var indexOf = reverseArray.indexOf(thisString);
if (indexOf > -1) {
result += thisString + " - FOUND<br>";
} else {
result += thisString + " - NOT FOUND<br>";
}
}
Logger.log(result);
var htmlOutput = HtmlService
.createHtmlOutput('<p>' + result + '</p>')
.setWidth(400)
.setHeight(500);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'RESULT');
}
UPDATE: I have pasted the whole code instead above so you guys can see
You have to register onFormSubmit as the function that handles the form submit trigger. Have you registered the function "onFormSubmit" like this:
ScriptApp.newTrigger('onFormSubmit').forForm(form).onFormSubmit().create();
You might also want to check the registered triggers by clicking on Edit > Current project's trigger from your Apps Script project.
[Edit] Since the trigger is created properly, change the first the line of the trigger code from:
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
to this:
function onFormSubmit(e) {
var sheet = SpreadsheetApp.openById(e.source.getDestinationId());
I am guessing this is a simple thing to do but I am not sure how to do it. I have a google script that I want to run daily that checks the values of cells within one column in google sheets individually and sends an email if the value drops below a certain threshold.
What I have so far is
function sendEmail() {
var data = SpreadsheetApp.getActiveSheet().getRange('E2').getValue();
if (data < 300){
var emailAddress = "emailaddress#email.com";
var message = "test body";
var subject = "test subject";
MailApp.sendEmail(emailAddress, subject, message);
}
}
EDIT
Here is where I am now. It works except for pulling the emails from the cells.
function sendEmail() {
function letThemKnow(num) { //This creates a function named letThemKnow which is passed the variable num from the if/else statements
var emailAddress = email[i]; //Sets the variable to the email address of
var message = "Greetings! This is an automated message to let you know your license for " + software[i] + " expires in " + num + " days.";
var subject = "Impending expiration of " + software[i];
MailApp.sendEmail(emailAddress, subject, message);
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getActiveSheet();
var lastRow = sh.getLastRow();
var data = sh.getRange(2, 5, lastRow, 1).getValues();
var software = sh.getRange(2, 1, lastRow, 1).getValues();
var email = sh.getRange(2, 7, lastRow, 1).getValues();
for (i = 0; i <= email.length; i++) {
for (i = 0; i <= software.length; i++) {
for (i = 0; i <= data.length; i++) {
var num = parseInt(data[i]);
if (num == 30) {
letThemKnow(num)
} else if (num == 14) {
letThemKnow(num)
} else if (num <= 7) {
letThemKnow(num)
}
}
} //
}
} //
Your for loop is starting at '0' and ending at '0'. Try this:
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getActiveSheet();
var lastRow = sh.getLastRow();
var data = sh.getRange(2,5,lastRow,1).getValues();
for (i=0;i <= data.length;i++){
var num = parseInt(data[i]);
if (num < 300) {
var emailAddress = "email#email.com";
var message = "test body";
var subject = "test subject";
MailApp.sendEmail({
name: "Your Name",
to: emailAddress,
subject: subject,
htmlBody: message
});
}
}
}
If the email is the same every time, you should probably define those variables outside the loop.
I am just starting Google Forms. I need to email the form owner (myself and some others) a response as soon the the user submit the data. I need the data in the email which would include fields and their values that were submitted by the user as soon as they submit the form.
I am unable to use add-on as per my google account settings via my employer where add-on are blocked.
I am exploring app scripts but with little success as I am very new. As there some sample codes to help me get started with create a basic script to send email.
I have the following Code:
function sendFormByEmail(e)
{
var email = "ownersemail#host.ca";
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
var subject = "New Hire: ";
for(var i in headers)
message += headers[i] + ': '+ e.namedValues[headers[i]].toString() + "\n\n";
subject += e.namedValues[headers[2]].toString() + " - starts " + e.namedValues[headers[15]].toString();
MailApp.sendEmail(email, subject, message);
}
Then I added this script in the form trigger like so:
I tried submitting the form but nothings heppens. How do I know that the script ran or there was a problem?
If I try to run this in the script editor :
It gives me an error :
TypeError: Cannot call method "getRange" of null. (line 7, file "Code")
Update
I tested the email functionality and it worked. So the problem has to be in Spread Sheet value retrieval.
function sendFormByEmail(e)
{
var email = "ownersemail#host.ca";
MailApp.sendEmail(email, "Test", "Test");
}
I also created a excel file on my google drive that holds these response from google form
Final Solution
function testExcel() {
var email = "ownersemail#host.ca";
var s = SpreadsheetApp.openById("GoogleDocsID");
var sheet = s.getSheets()[0];
var headers = sheet.getRange(1,1,1,sheet.getLastColumn()).getValues()[0];
var datarow = sheet.getRange(sheet.getLastRow(),1,1,sheet.getLastColumn()).getValues()[0];
var message = "";
for(var i in headers)
{
message += "" + headers[i] + " : " + datarow[i] + "\n\n";
//Logger.log(message);
}
MailApp.sendEmail(email, "Submitted Data Test", message);
}
Here is a shell for you to start with. I use this code for a very similar reason. This shell includes creating a Google Doc from template and adding data from the sheet into that Doc. You can use similar methods to set variables and add them into the email. I use an html template file(s) to manage exactly what is being sent each time.
The merge portion checks through the Doc (you can set it to look through html file) and finds my tags using RegEx; structed as so: <<columnHeader>>. In this way, You have a consistent template that replaces those tags with the data, in that column, for that row. Modify to your needs as you see fit.
This also displays the progress of the merge. That way, it won't repeat your emails/ merge.
NOTE: There are several data points missing as I removed the personal information; it won't run straight from this sample. You will have to add your document IDs, correct for variable placement, etc.
function mergeApplication() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("");
var formSheet = ss.getSheetByName("");
var lastRow = formSheet.getLastRow();
var lastColumn = sheet.getMaxColumns();
function checkAndComplete() {
var urlColumn = lastColumn;
var checkColumn = (urlColumn - 1);
var checkRange = sheet.getRange(2, checkColumn, (lastRow - 1), 1);
var check = checkRange.getBackgrounds();
var red = "#ff0404";
var yellow = "#ffec0a";
var green = "#3bec3b";
for (var i = 0; i < check.length; i++) {
if (check[i] == green) {
continue;
} else {
var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
var dataRow = sheet.getRange((i+2), 1, 1, (lastColumn - 2));
function mergeTasks() {
function docCreator() {
var docTemplate1 = DriveApp.getFileById("");
var docTemplate2 = DriveApp.getFileById("");
var folderDestination = DriveApp.getFolderById("");
var clientName = sheet.getRange((i+2), 2, 1, 1).getValue();
var rawSubmitDate = sheet.getRange((i+2), 1, 1, 1).getValue();
var submitDate = Utilities.formatDate(rawSubmitDate, "PST", "MM/dd/yy");
var typeCheck = sheet.getRange((i+2), (checkColumn - 1), 1, 1).getValue();
if (typeCheck == "Type 1") {
var docToUse = docTemplate1;
var emailBody = HtmlService.createHtmlOutputFromFile("").getContent();
} else {
var docToUse = docTemplate2;
var emailBody = HtmlService.createHtmlOutputFromFile("").getContent();
}
var docName = "" + clientName + " - " + submitDate;
var docCopy = docToUse.makeCopy(docName, folderDestination);
var docId = docCopy.getId();
var docURL = DriveApp.getFileById(docId).getUrl();
var docToSend = DriveApp.getFileById(docId);
var docInUse = DocumentApp.openById(docId);
var docBody = docInUse.getBody();
var docText = docBody.getText();
function tagReplace() {
var DOBCell = sheet.getRange((i+2), 3, 1, 1);
var rawDOB = DOBCell.getValue();
if (rawDOB !== "") {
var DOB = Utilities.formatDate(rawDOB, "PST", "MM/dd/yy");
} else {
var DOB = ""
}
var taggedArray = docText.match(/\<{2}[\w\d\S]+\>{2}/g);
var headerArray = sheet.getRange(1, 1, 1, (lastColumn - 2)).getValues();
var dataArray = dataRow.getValues();
dataArray[0][2] = DOB;
var strippedArray = [];
function tagStrip() {
for (var t = 0; t < taggedArray.length; t++) {
strippedArray.push(taggedArray[t].toString().slice(2, -2));
}
}
function dataMatch() {
for (var s = 0; s < strippedArray.length; s++) {
for (var h = 0; h < headerArray[0].length; h++) {
if (strippedArray[s] == headerArray[0][h]) {
docBody.replaceText(taggedArray[s], dataArray[0][h]);
}
}
}
docInUse.saveAndClose();
}
tagStrip();
dataMatch();
}
function emailCreator() {
var emailTag = sheet.getRange((i+2), (checkColumn - 9)).getValue();
var emailSubject = "" + clientName;
MailApp.sendEmail({
to: emailTag,
subject: emailSubject,
htmlBody: emailBody,
attachments: [docToSend.getAs(MimeType.PDF)],
replyTo: "",
});
}
tagReplace();
statusCell.setBackground(yellow);
emailCreator();
urlCell.setValue(docURL);
}
statusCell.setBackground(red);
docCreator();
statusCell.setBackground(green);
}
mergeTasks();
}
}
}
checkAndComplete();
}