Getting a Google Form Script generated email to pipe data into Reponse Sheet - email

I am currently trying to setup an approval workflow. I'm fairly junior when it comes to some of this stuff. But so far have it working at respectable level to fit our needs with the assistance of an example.
I was using the template/example from Email Approval using Google Script and a Form.
The issue I am running into, with a lack of functionality is that at the time of Accept or Deny via the Email that is generated for approval I would like it to then record that data back into the Google Form row in the last column that the email was generated from.
I may end up adding 2nd timestamp, reply email etc later.
So then that row would show the initial form filled out and then either blank/accepted/deny as the status.
Thank you for any time or assistance.

The approval workflow that James Ferreira originally wrote was intentionally very basic. Enhancing it to provide correlation between approvals and the original requests is simple in concept, yet complicates the code because of details and limitations.
Things that need to considered:
Form responses include a timestamp, which we can use as a sort of "serial number" for responses, since it has a very high probability of being unique in an application like this.
We can pass this identifier along with the rest of the URL embedded in the approval email, which will give it back as a parameter to the webapp, in turn.
Passing an object like a timestamp between applications can be troublesome. To ensure that the URL embedded in the approval email works, we need to encode the string representation of the timestamp using encodeURIComponent(), then decode it when the webapp consumes it.
Searching for matches is simplified by use of ArrayLib.indexOf() from Romain Vaillard's 2D Array library. This function converts all array data to strings for comparisons, so it fits nicely with our timestamp.
Alternatively, we could put effort into creating some other identifier that would be "guaranteed" to be unique.
The approval-response web app (doGet()) does not understand what "activeSpreadsheet" means, even though it is a script contained within a spreadsheet. This means that we need a way to open the spreadsheet and record the approval result. To keep this example simple, I've assumed that we'll use a constant, and update the code for every deployment. (Ick!).
So here's the Better Expense Approval Workflow script.
// Utilizes 2D Array Library, https://sites.google.com/site/scriptsexamples/custom-methods/2d-arrays-library
// MOHgh9lncF2UxY-NXF58v3eVJ5jnXUK_T
function sendEmail(e) {
// Response columns: Timestamp Requester Email Item Cost
var email = e.namedValues["Requester Email"];
var item = e.namedValues["Item"];
var cost = e.namedValues["Cost"];
var timestamp = e.namedValues["Timestamp"];
var url = ScriptApp.getService().getUrl();
// Enhancement: include timestamp to coordinate response
var options = '?approval=%APPROVE%&timestamp=%TIMESTAMP%&reply=%EMAIL%'
.replace("%TIMESTAMP%",encodeURIComponent(e.namedValues["Timestamp"]))
.replace("%EMAIL%",e.namedValues["Requester Email"])
var approve = url+options.replace("%APPROVE%","Approved");
var reject = url+options.replace("%APPROVE%","Rejected");
var html = "<body>"+
"<h2>Please review</h2><br />"+
"Request from: " + email + "<br />"+
"For: "+item +", at a cost of: $" + cost + "<br /><br />"+
"Approve<br />"+
"Reject<br />"+
"</body>";
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
"Approval Request",
"Requires html",
{htmlBody: html});
}
function doGet(e){
var answer = (e.parameter.approval === 'Approved') ? 'Buy it!' : 'Not this time, Keep saving';
var timestamp = e.parameter.timestamp;
MailApp.sendEmail(e.parameter.reply, "Purchase Request",
"Your manager said: "+ answer);
// Enhancement: store approval with request
var sheet = SpreadsheetApp.openById(###Sheet-Id###).getSheetByName("Form Responses");
var data = sheet.getDataRange().getValues();
var headers = data[0];
var approvalCol = headers.indexOf("Approval") + 1;
if (0 === approvalCol) throw new Error ("Must add Approval column.");
// Record approval or rejection in spreadsheet
var row = ArrayLib.indexOf(data, 0, timestamp);
if (row < 0) throw new Error ("Request not available."); // Throw error if request was not found
sheet.getRange(row+1, approvalCol).setValue(e.parameter.approval);
// Display response to approver
var app = UiApp.createApplication();
app.add(app.createHTML('<h2>An email was sent to '+ e.parameter.reply + ' saying: '+ answer + '</h2>'))
return app
}

So, I tried this, but there an issue with the formatting for date when it's in the data array. In order to get this to work, you have to reformat the time stamp in the doGet using formatDate.
I used the following to get it to match the formatting that appears in the array.
var newDate = Utilities.formatDate(new Date(timestamp) , "PST", "EEE MMM d yyyy HH:mm:ss 'GMT'Z '(PST)'");
Lastly, of course update the indexof parameter that is passed to newDate.

Related

How to send a conditional email based on the value of a cell from a form response?

I have a formula that calculates a number based on the response from a google form. Depending on what this number I want to send an email using details from the from as well as a pre typed email in another cell.
In Col1 is a time stamp, in col14 is an employee start date. My formula in Col33 works out how many days they have been employed at the time of submitting the form.
I want to send an email to the person if the number of days is less than 182.
I have an email pre typed out and can place this anywhere. At the moment I have it in all cells in col36. The email address will be in column32.
I have tried a number of different codes and none of them are sending the email no matter what the trigger I have set up is. I have very basic knowledge on apps script so my current code might be completely wrong, but it should show roughly what I'm getting at.
function sendEmail() {
var values = SpreadsheetApp.getActiveSheet().getDataRange().getValues()
for (i in values.length) {
var data = values[i][33];
var emailAddress = values[i][32];
var message = values[i][36];
if (data < 182); {
MailApp.sendEmail(emailAddress, "Flexible Working Request", message);
}
}
}
The current results have just been deleting the data in col33, Col34 & Col36 on the new form response row only.
Sorry if this question has been answered elsewhere, any other answer I found to similar issues I could not get to work.
I got someone who is much better at google apps script at work to give me a hand
It is to do with google forms pushing down formulas to the side
So we had to move the formula calculating the number of days to another sheet and then used this formula which worked
function sendEmailv2() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form responses
1');
var scrip = Session.getScriptTimeZone();
var date = sheet.getRange(sheet.getLastRow(),14).getValue();
var sub = sheet.getRange(sheet.getLastRow(),1).getValue();
Logger.log(date);
var fortmat = Utilities.formatDate(new Date(date), scrip, "dd/MM/yyyy");
var Subfortmat = Utilities.formatDate(new Date(sub), scrip, "dd/MM/yyyy");
var emailAddress = sheet.getRange(sheet.getLastRow(),32).getValue();
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet4');
var message = sheet2.getRange(1,1).getValue();
var days = sheet2.getRange(sheet2.getLastRow(),2).getValue();
if (days<182){
MailApp.sendEmail(emailAddress, "Flexible Working Request", message,{noReply:true});
}
}
Thanks!
You don’t need to go over all the columns to get a single cell value, so there is no need for a for loop. You can do it directly with:
var sheet = SpreadsheetApp.getActiveSheet().getSheets[0];
var cell = ["A33"];
var days_value = sheet.getRange(cell).getValue();
Then you can just make an if condition to send the email:
if (days_value < 182){
MailApp.sendEmail(emailAddress, "Flexible Working Request", message);
}
Hope this helps

How to get email form submissions script to exclude blank response values from sheet?

I am editing an existing script that my team uses for a google form response sheet. The script automatically creates a message body using the headers and response cells for an order every time it is submitted, roughly like this:
Type of Order: Physical
Country: America
Digital Signature:
Favorite Color:
Favorite Food: Pasta
What I've been asked to do, is have the script read through the sheet and not include the header or response for questions that are not answered in any given submission. Like so, for the previous example:
Type of Order: Physical
Country: America
Favorite Food: Pasta
I should start by saying I have close to 0 experience in javascript or Google Apps. I have tried playing around with if clauses using both the len function and a negated isblank function to no avail. These all lead to undefined errors.
As you'll see, the original script was not created by me or the people who have been using it for the last few years.
Original script
function sendFormByEmail(e)
{
Logger.log('value of e is: ' + e);
var email = "xxx#xxx.com";
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
var subject = "Type A Request: ";
// The variable e holds all the form values in an array.
// Loop through the array and append values to the body.
// Insert variables from the spreadsheet into the subject.
// In this case, I wanted the new hire's name and start date in the
// email subject. These are the 3rd and 16th columns in my form.
for(var i in headers)
message += headers[i] + ': '+ e.namedValues[headers[i]].toString() + "\n\n";
subject += e.namedValues[headers[10]].toString() + " - " +
e.namedValues[headers[12]].toString();
MailApp.sendEmail(email, subject, message, {noReply:true});
// Based off of a script originally posted by Amit Agarwal - www.labnol.org
}
You can include a check for blank values inside the for loop.
if (e.namedValues[headers[i]].toString() === "") continue;

Custom Email script

I am trying to form a simple order system, which responds to the user with a estimated delivery date once it is inserted into google sheet.
Basically someone completes a google form, which populates the sheet and then I require the sheet to send an email confirmation once a delivery date is manually inserted into the "delivery date" column on the sheet.
Currently the script is:
function CustomEmail() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("B2:L1000");
var UserData = range.getValues();
for (i in UserData) {
var row = UserData[i];
var name = row[5];
var email = row[0];
var score = row[9];
MailApp.sendEmail (row[1], "ORDER CONFIRMATION", "Order Confirmation of: " + name + ". The estimated delivery date is " + score);
}
}
It seems to work but it emails all of the rows of data, so I receive multiple emails each time and it will duplicate. I need it to just send an email to the row which has had the date manually inserted in the sheet. The script is designed to email an email address which is captured through the form.
I would like it to email that line only, I have read that it would be best to use an "on edit" trigger. This works but it still sends an email to the whole sheet each time not just the particular line that is edited.
The email response arrives like this:
"Order Confirmation of: 300mm screws. The estimated delivery date is Thu Jan 17 2019 00:00:00 GMT-0000 (GMT)"
Apologies, this is my first attempt at any sort of script so very novice.
Cheers
Joe

Generate and send pdf through Google Forms to my email address - doesn't send, debugging to no assitance

I'm trying to send myself a form-based report as a pdf. The problem is, I don't receive any emails. Debugging doesn't help much, since that only tells me which values are "undefined" (they are being defined the instant one fills out the form and triggers the email by clicking send; in theory). My coding experience stems from the days of TurboPascal and .bat-files, and I have lately realised I need to shape up. Trying to figure out Android, and this is a little experiment at work. But I had forgotten the lost feeling of "what now?"...
Here's the code:
// Samfunnsutvikling kursrapport
var docTemplate = "TemplateIDinGoogleDoks";
var docName = "Kursrapport";
// When Form Gets submitted
function onFormSubmit(e) {
//Get information from form and set as variables
var email = "worker#work.no";
var namn = e.namedvalues.namn;
var arrangement = e.namedvalues.arrangement;
var dato = e.namedvalues.dato;
var referat = e.namedvalues.referat;
// Get document template, copy it as a new temp doc, and save the Doc’s id
var copyId = DocsList.getFileById(docTemplate)
.makeCopy(docName+' for '+namn)
.getId();
// Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
// Get the document’s body section
var copyBody = copyDoc.getActiveSection();
// Replace place holder keys,in our google doc template
copyBody.replaceText('keynamn', namn);
copyBody.replaceText('keyarrangement', arrangement);
copyBody.replaceText('keydato', dato);
copyBody.replaceText('keyreferat', referat);
// Save and close the temporary document
copyDoc.saveAndClose();
// Convert temporary document to PDF
var pdf = DocsList.getFileById(copyId).getAs("application/pdf");
// Attach PDF and send the email
var subject = "Kursrapport";
var body = "Kursrapporten frå " + namn + "";
GmailApp.sendEmail(email, subject, body, {htmlBody: body, attachments: pdf});
// Delete temp file
DocsList.getFileById(copyId).setTrashed(true);
}
The script/document is authorized to send emails, but, oddly, I had to authorize it twice. It is saved.
In general, you can add Logger.log() to print variable values or just messages to see how far does it reach.
It looks as attachments parameter expects Blob[] type, however you are passing just Blob. So, it should be:
GmailApp.sendEmail(email, subject, body, {htmlBody: body, attachments: [pdf]});
You may also want to replace DocsList with DriveApp class as-is since the first one is depricated.
Update
It turned out also that getActiveSection() was renamed to getBody().

What is the procedure to email the test score of a test conducted on google forms?

I have created a test through google form, and I want to send the score result to the participants. I have created a copy of the response and put scoring through if functions. And then in the next worksheet, I have summed the score. Now I want to send that calculated score to the participants. I have entered the script in the script editor and set trigger on form submit but I am getting errors.
Would the error be because the script takes the default sheet and not the one where I have created score function? If so, how do I change that?
Here is the code that I used:
function myFunction(e)
{
var userName = e.values[1];
var userEmail = e.values[2];
var score = e.values[3];
var subject = "Thank you for your participation: Find your Score";
var message = "Thank you, " + userName + " for choosing to participate in this test. Your score is " + score;
MailApp.sendEmail(userEmail, subject, message);
}
There are two ways. Send an e-mail from the form or send a notification from the result collection spreadsheet (limited to spreadsheet collaborators).
For the first, you have to use the script editor found under tools. There are several examples to get you started. I'd recommend you take a look at: http://www.labnol.org/internet/auto-confirmation-emails/28386/
For the second, you use the notifications option, see: https://www.maketecheasier.com/send-email-notifications-google-forms/
Here is the code that I used
function myFunction(e){
var userName = e.values[1];
var userEmail = e.values[2];
var score = e.values[3];
var subject = "Thank you for your participation: Find your Score";
var message = "Thank you, " + userName + " for choosing to participate in this test. Your score is " +score;
MailApp.sendEmail (userEmail, subject, message);}