I am creating a script that sends a custom email right after you send the form. It works perfectly but I wanted it to work also when I edit the form it sends a automatic email with the changes made.
function Initialize() {
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers)
ScriptApp.deleteTrigger(triggers[i]);
ScriptApp.newTrigger("SendGoogleForm")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit().create();
}
function SendGoogleForm(e) {
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "Please paste this!\n\n";
var subject = "Email: ID: ";
var email = "";
//
var form = FormApp.openById('*******************'); //this is the ID in the url of your live form
var formResponses = form.getResponses();
//
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
}
for(var i in headers) {
if ( e.namedValues[headers[i]].toString() != "") {
message += headers[i] + ': '+ e.namedValues[headers[i]].toString() + "\n";
}
}
subject += e.namedValues[headers[2]].toString();
email += e.namedValues[headers[1]].toString();
message += "Edit Link: " + formResponse.getEditResponseUrl();
MailApp.sendEmail(email, subject, message);
}
I've found a script that may help to send a email when it is edited but I am not sure how I can implement it(found it in google docs forums https://productforums.google.com/forum/#!topic/docs/-guIl5QlvKk):
function checkResponse() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Form Responses 1');
var lastRow = s.getLastRow();
var range = s.getRange('A' + lastRow + ':C' + lastRow);
var notes = range.getNotes();
var values = range.getValues();
var changedFlag = null;
var body = '';
for (var i = 0; i < notes[0].length; i++ ) {
if ( notes[0][i] == 'Responder updated this value.' ) {
changedFlag = true;
// We know only to send the changed values
// Add changed value to email msg
body += values[0][i];
// May also want to clear the note as it remains after future edits of other values as well
s.getRange(lastRow, i).clearNote();
}
}
if ( !changedFlag ) {
// Email the whole row of values
for (var i = 0; i < values.length; i++) {
body += values[0][i];
}
}
GmailApp.sendEmail(recipient, subject, body)
}
Related
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 have a script which pulls data from a defined tab name 'Master' in Google sheet, which is then sending an email triggering at a specific time.
My problem is I don't want script to send blank email if the table in 'Master' is empty. Script should stop sending email.
Otherwise keeps triggering email on mentioned time.
Can anyone please share their insight on this.
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Master");
var range = sheet.getDataRange();
var recipient = 'email#gmail.com'
var subject = 'Stock Report'
var date = Utilities.formatDate(new Date(), "GMT+1", "dd/MM/yyyy")
var schedRange = sheet.getRange("A1:L21");
var body = '<div style="text-align:center;display: inline-block;font-family: arial,sans,sans-serif">'
body += '<H1>'+ 'Low Stock Report ' +'</H1>';
body += '<H2>'
body += getHtmlTable(schedRange);
body += '</div>';
GmailApp.sendEmail(recipient, subject, "Requires HTML", {htmlBody:body})
//End sendNotification
}
How to check if the table is not empty
If your table is var schedRange = sheet.getRange("A1:L21"); you can check either its empty by retrieving its values and send it only in case a non-empty value is found.
You can implement a boolean variable - as soon as the first non-empty value is found in the table - it will be set to true and an email will be sent.
Sample:
function sendEmail() {
...
var schedRange = sheet.getRange("A1:L21");
var values = schedRange.getValues();
var send = false;
for (var i = 0; i < values.length; i++){
for (var j = 0; j < values[0].length; j++){
var value = values[i][j];
if (value !="" && value !=" "){
return send = true;
}
}
}
if (send == true){
var body = '<div style="text-align:center;display: inline-block;font-family:
...
GmailApp.sendEmail(recipient, subject, "Requires HTML", {htmlBody:body})
}
}
You can also do something like this:
var schedRange = sheet.getRange("A1:L21");
var values = schedRange.getValues();
if (values.flat(2).length>0) {
//Send
var body = '<div style="text-align:center;display: inline-block;font-family:
...
GmailApp.sendEmail(recipient, subject, "Requires HTML", {htmlBody:body})
}
Thanks to the fact that flat() will make a 2D array into a simple array, removing empty elements, we can use it to basically remove all blank values from the array, effectively checking if it's empty or not.
After applying sample code I am not getting email, I have tried both ways with and without data in Master Sheet but no email.I am not sure if i am doing the right way.
Sample:
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Master");
var range = sheet.getDataRange();
var recipient = 'alislife87#gmail.com'
var subject = 'Stock Report'
var date = Utilities.formatDate(new Date(), "GMT+1", "dd/MM/yyyy")
var schedRange = sheet.getRange("A1:L21");
var values = schedRange.getValues();
var send = false;
for (var i = 0; i < values.length; i++){
for (var j = 0; j < values[0].length; j++){
var value = values[i][j];
if (value !="" && value !=""){
return send = true;
}
}
}
if (send == true){
var body = '<div style="text-align:center;display: inline-block;font-family:
arial,sans,sans-serif">'
body += '<H1>'+ 'Low Stock Report ' +'</H1>';
body += '<H2>'
body += getHtmlTable(schedRange);
body += '</div>';
GmailApp.sendEmail(recipient, subject, "Requires HTML", {htmlBody:body})
}
}
I am new to Google App script.
I have form with multi choice option. For example i have two option like payment and balance. If i choose payment and click submit button some operation will happen. If i choose balance some other operation will happen. For that i am trying to read the selected option. But i couldn't. Below is the code i have tried to read. Can someone help.
I tried with this. It is giving all form responses. Also this one is giving values while running script. But trying via form it is not working.
function myFunctiontest() {
var form = FormApp.getActiveForm();
var formResponses = form.getResponses();
var itemr,title,res;
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j]
var item = itemResponse.getItem();//.asMultipleChoiceItem();
itemResponse.getItem().getType(),
itemResponse.getItem().getTitle(),
itemResponse.getResponse();
res = itemResponse.getResponse().;
if (item.getType() == 'MULTIPLE_CHOICE' && res == 'A')
{
itemr= itemResponse.getItem().asMultipleChoiceItem(),
title =itemResponse.getItem().getTitle(),
res = itemResponse.getResponse();
Logger.log('Response Type : ',itemr );
Logger.log('Response Type title :',title );
Logger.log('Response Type res:',res );
}
}
}
}
I'm giving below a function which I use to send an email (by referring to two other sheets) on receiving a form response.
You have to make a trigger "onFormSubmit" from the app script editer (click the clock icon).
function onFormSumbit(e) {
var emp = e.source.getActiveSheet().getRange(e.range.rowStart,2).getValue();
var lvss = SpreadsheetApp.openById("1ywKQViIU2k"); // leave applied
SpreadsheetApp.setActiveSpreadsheet(lvss);
var lvsht = lvss.getSheetByName("Form responses 1");
var lvlr = lvsht.getLastRow();
var vA =lvsht.getRange("A:L").getValues();
var html="<style>th,td{border:1px solid black;}</style><table>";
html+='<tr>';
for(var i=0;i< 12 ;i++) {//make title
html+=Utilities.formatString('<th>%s</th>',vA[0][i]);
}
html+='</tr>';
for (i=1;i<lvlr;i++){
if (vA[i][1]==emp){
html+='<tr>';
for (j=0;j<12;j++) {
if (j==0 || j==2 ){
vA[i][j]=Utilities.formatDate(vA[i][j],"GMT+05:30", "dd-MM-yy");
}//if date
if ( j==4 && vA[i][j] !=="" ){
vA[i][j]=Utilities.formatDate(vA[i][j],"GMT+05:30", "dd-MM-yy");
}//if date
html+=Utilities.formatString('<td>%s</td>',vA[i][j]);
}//for emp
html+='</tr>';
}//if
}//for
html+='</table><br>';
var empss = SpreadsheetApp.openById("1_87o"); // emp master
SpreadsheetApp.setActiveSpreadsheet(empss);
var empsht = empss.getSheetByName("Emp");
var emplr = empsht.getLastRow();
var empvals =empsht.getRange("A:H").getValues();
for (i=1;i<emplr;i++){
if (empvals[i][0]==emp){
var em1=empvals[i][7];
var name=empvals[i][1]
break;
}//if
}//for
var subject="Your Online Leave History of "+name;
if (em1=="") {} else {
//MailApp.sendEmail(em1, subject, html);}
MailApp.sendEmail({
to: em1,
subject: subject,
htmlBody: html
});
}
}
//
//
I am using the below mentioned apps script to get the email details in google sheets based on the label name updated in the particular cell.
function getBaEmails() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var ss = sheet.getSheetByName("Raw Data");
var row = 2;
ss.getRange(2, 1, ss.getMaxRows() - 1, 4).clearContent();
var label = ss.getRange("F1").getValue();
var pattern = ss.getRange("F2").getValue();
var threads = GmailApp.search("in:" + label);
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var msg = messages[m].getBody();
if (msg.search(pattern) !== -1) {
ss.getRange(row,1).setValue(
Utilities.formatDate(messages[m].getDate(),"GMT","MM-dd-yyyy"));
ss.getRange(row,2).setValue(messages[m].getFrom());
ss.getRange(row,3).setValue(messages[m].getSubject());
var id = "https://mail.google.com/mail/u/0/#all/"
+ messages[m].getId();
ss.getRange(row,4).setFormula(
'=hyperlink("' + id + '", "View")');
row++;
}
}
}
};
I am trying to update the apps script which helps to get the email details based on the dates.
For example : I need a email details from 08/01/2019 to 08/30/2019.
It would be great, if anyone help me to update the apps script.
Thanks in advance.
Try something like this:
You can always test your queries in Gmail
function gmailSearch(label,after,before) {
var label=label||'qs-vendors-google';
var after=after||'2019/01/01';
var before=before||'2019/08/01';
var html='';
var qry=Utilities.formatString('label:%s after:%s before:%s',label,after,before);
var results=GmailApp.search(qry);
for(var i=0;i<results.length;i++) {
var msgs=results[i].getMessages()
for(j=0;j<msgs.length;j++) {
html+=Utilities.formatString('<strong>Date:</strong> %s <strong>From: </strong> %s <strong>Subject: </strong> %s<br />',msgs[j].getDate(),msgs[j].getFrom(),msgs[j].getSubject());
}
}
var userInterface=HtmlService.createHtmlOutput(html).setWidth(1000);
SpreadsheetApp.getUi().showModelessDialog(userInterface, 'Search Results')
}
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();
}