Google form to answer sheet to separate sheet to email - google-apps-script

I am trying to work out a solution to something and whilst I can get snippets of help from the weeb I cannot pin it down to what I want it to do. So, what I want to achieve:
A google form is submitted which creates a record in a google spreadsheet.
using the query function I take that information instantly to another sheet in the same spreadsheet. Whilst in there it goes through some if statements which creates a unique ID for the submission, separates the date and the time of the submission into separate columns and adds a email address that needs to be notified of this submission. For the purpose of this test, the submitter and the notification emails are the same.
the script monitors the second sheet and, on form submission (trigger), takes the information from the last row in a certain sequence to create an email:
function formsubmission(e){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetbyName('email');
var startRow = 2;
var lastRow = e.sheet.getLastRow();
var formid = e.sheet.column[1];
var notificationemail = e.sheet.column[2];
var formdate = e.sheet.column[3];
var formtime = e.sheet.column[4];
var submitter = e.sheet.column[6];
var yn = e.sheet.column[7];
var subject = formid + "submitted";
var message = "Thank for answering" + yn + "on" + formdate + "at"+ formtime;
MailApp.sendEmail (notificationgroup, subject, message,{
cc: submitter,
});
}
Needless to say that the above script does not work.
If any of you kind people want to help. The form is test form to which the above refers is here and the related spreadsheet is here.
I would prefer not to have a separate sheet but the one accepting submissions does not allow for any functions or anything else in it.
Any help to make the above script work would be greatly appreciated.
Thank you

Related

how do i send an email with info from a row with criteria from one of its column using google app script

I want to write a script that will send an email based on the criteria of a single column.
This is for an inventory management system that will send emails to remind that certain items are low in count.
eg.
if row 5's column J is = "reminder", send values of row 5's column B and C to my email. (col B and C is item description and quantity count respectively)
I just started learning about google app script so I'm not sure how to write it myself, but from other forum posts, this is what I got.
var values = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
values.forEach(function(row) {
var indent = row[10]; //column j
if (indent !== '') {
var EditedRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("store list").getRange(indent);
var Edited = EditedRange.getValue();
}
// Fetch the email address
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("mail").getRange("B2");
var emailAddress = emailRange.getValue();
// Send Alert Email.
var message = Edited;
var subject = 'For Action: Indent' ;
MailApp.sendEmail(emailAddress, subject, message);
});
}
I split the code up and tested emailing and apparently the email portion of the codes work, but it is the retrieving of data that is not working and I don't really know how to get it working.
To get started, have a look at the Apps Script reference
There you will see that to retrieve the value of a single cell it is bets to use the method getValue() instead of getValues()
You need to specify the range (cell) wrom ehre you want to get the value
The easiest way to do so is with the method getRange() specifying A1 notation
A simple sample would be:
var sheet = SpreadsheetApp.getActiveSheet();
var checkValue = sheet.getRange("J5").getValue();
if (checkValue == "reminder"){
var B5Value = sheet.getRange("B5").getValue();
var C5Value = sheet.getRange("C5").getValue();
var message = B5Value + " and " + C5Value;
var emailAddress = "you need to define the email address of the recipient either in the code or a cell of the sheet";
var subject = "Define here your subject";
MailApp.sendEmail(emailAddress, subject, message);
}
Please make sure to dedicate enough time to study the Apps Script documentation to understand this code and be able to troubleshoot and perform simple modifications.

Collect Responses From Google Form?

I am quite new to Google Scripts and attempting to learn, but documentation is either conflicting, non-existent, or not working for me.
The goal is to have a script that collects responses from a Google Form and sends emails based on one of the user input fields (a drop down box where the user can select their location). Problem being that I cannot retrieve the Form responses. I am receiving an error that the "getItemResponses();" is not a function. How do I get responses from a Form? All the other parts I have figured out.
Flow - I have setup a trigger by going to Edit -> Current projects' triggers -> created a new trigger that on submit it runs my function. What is supposed to happen is (later in the script) sendMail sends a mail message as me to the var "respondent". However, I receive the error "getItemResponses();" is not a function when just attempting to run from the script editor and filling out a test form submissions (via email on the latter).
Thank you for any help in advance. Please note, again, I'm new at the Google Scripts.
function sendEmails(e) {
// Get active form and responses
var formResponse = e.response;
var itemResponses = formResponse.getItemResponses();
// Assign responses to variables
var respondent = itemResponses[0].getResponse();
var district = itemResponses[1].getResponse();
var urgency = itemResponses[2].getResponse();
var type = itemResponses[3].getResponse();
var topic = itemResponses[4].getResponse();
// TAM email address. Used in sendTo field later
var sendTo = "person#email.com";
MailApp.sendEmail(sendTo,"subject","message body");
if(type == "Option 1") {
MailApp.sendEmail(respondent,"subject","message body");
}
}
Issue:
form.getResponses() returns an array of FormResponse, as you can see here. An array of responses does not have a method called getItemResponses() and this is the reason you code is failing. What you're doing right now is getting all the responses corresponding to a form, and not the one that was just submitted.
You should use the method getItemResponses() from a single FormResponse instead.
Solution:
Assuming that:
You want the script to run (and, if the conditions are met, send an email) every time the form is submitted.
You have installed an onFormSubmit trigger, connected to your form.
If that's the case, you should be using the trigger event object to get the FormResponse. You should replace this:
var form = FormApp.getActiveForm();
var formResponses = form.getResponses();
var itemResponses = formResponses.getItemResponses();
With this:
var formResponse = e.response;
var itemResponses = formResponse.getItemResponses();
Update:
Your form does not have 5 items, but 4. First item is actually the respondent email, and as such, it has to be retrieved via FormResponse.getRespondentEmail(). Because of this, itemResponses only gets to index 3, not to 4, and itemResponses[4] is undefined. That's the reason behind your new error. You should do this instead:
var respondent = formResponse.getRespondentEmail();
var district = itemResponses[0].getResponse();
var urgency = itemResponses[1].getResponse();
var type = itemResponses[2].getResponse();
var topic = itemResponses[3].getResponse();
Reference:
Event Objects: Form submit
Form.getResponses()
FormResponse.getRespondentEmail()
While it is possible to do what you want to do from the form its self it will be difficult as a beginner since as you noticed there aren't many example scripts to work off.
It will be much easier to do this from the responses sheet and there are plenty of examples around for processing form data from a spreadsheet.
The example below is a simple (untested) script to send a reply on form submission.
function onFormSubmit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var respSheet = ss.getSheetByName('Form responses 1');
var rowIndx = e.range.getRow();
var formData = respSheet.getRange(rowIndx, 1, 1, respSheet.getLastColumn()).getValues();
var respondent = formData[0].getResponse();
var district = formData[1].getResponse();
var urgency = formData[2].getResponse();
var type = formData[3].getResponse();
var topic = formData[4].getResponse();
MailApp.sendEmail(respondent, district + ' ' + topic, "Your reply was recieved and is being processed");
respSheet.getRange(rowIndx, 5).setValue('Email send to ' + respondent);
}

Automated emailing using information from a google form and different spreadsheets?

I'm new to google scripts so please bear with me. I'm working on automating communication for a 2 condition study signup using a google form and google sheets. Essentially, when a participant submits a form, I need to send a confirmation email (trigger is form submission) with the date they chose, and a new unique ID based on their condition (I have two separate lists of premade IDs I need to use). Right now, I have the main form response sheet and then I'm using = query to separate the survey responses into sheets for the two conditions based on a multiple choice question in the survey ('Morning' and 'Evening'). I have the ID lists filled into the corresponding sheets so that when the = query sorts the responses, they are automatically "assigned" an ID as the rows fill. I have the code working to send emails without the IDs, just using the name and date in the first sheet of the spreadsheet (the form response sheet), but am running into problems grabbing the ID from the other corresponding sheet to put into the email.
Here is what I have:
function IntialEmails(e){
var ss = SpreadsheetApp.openById('MyownSpreadsheetID'); //not including real ID for privacy reasons
var type = e.values[4];
if (type == 'Condition A') {
var sheet = ss.getSheets()[1];
ss.setActiveSheet(sheet);
}
if (type == 'Condition B') {
var sheet = ss.getSheets()[2];
ss.setActiveSheet(sheet);
}
var userName = sheet.values[0];
var userEmail = sheet.values[2];
var date = sheet.values[4]; //Using date from corresponding spreadsheet based on survey format
var ID = sheet.values[5]; // Should be from corresponding sheet
var subject = "Study Signup Confirmation and Participant ID";
var templ = HtmlService
.createTemplateFromFile('My html'); //not including real ID for privacy reasons
templ.date = date;
templ.ID = ID;
templ.userName = userName;
var message = templ.evaluate().getContent();
MailApp.sendEmail({
to: userEmail,
subject: subject,
htmlBody: message
});
}
I am super stuck, and continuously getting errors. This code throws back the error 'TypeError: Cannot read property '0' of undefined' If anyone can help me out it would be much appreciated!
If you want to get a value from a sheet you can do something like this:(Even I wouldn't normally do it this way I'm kind of following the same method that you used. I'm going to assume that you have your id's or what ever data in rows. But obviously I don't know since you didn't provide that information.
function initEmails(e) {
var ss=SpreadsheetApp.getActive();
var shts=ss.getSheets();
var sh=(e.values[4]=="Condition A")?shts[1]:shts[2];
var vs=sh.getRange(1,1,sh.getLastRow(),7).getValues();
for(var i=0;i<vs.length;i++) {
if(vs[i][7]!='USED') {
var userName=vs[i][0];
var userEmail=vs[i][2];
var date=vs[i][4];
var ID=vs[i][5];
var subject = "Study Signup Confirmation and Participant ID";
sh.getRange(i+1,8).setValue('USED');//this provides a way to keep track of which row was used last
}
/*.............I have no idea what your trying to do beyond this point.
}
But I don't think that you going to be able to insert these values into your html template this way:
templ.date = date;
templ.ID = ID;
templ.userName = userName;
Normally, templates are filled with desired data during the evaluate process by using scriptlets.
Templated HTML

Delete the emails stored in a Google Form's responses

Background:
I am trying to create a google form that will be filled out by people, and then send a second form to be filled by someone else (couple). The form response needs to be anonymous, but the responses will also need to be linked.
My solution so far - using a unique ID for linking (kudos -> How to assign a unique ID to a google form input?) then using the email inputted to send off a message with a pre-made link to the next form with the ID and then delete the email address from the sheet.
The Question
The next sanitation which I am stuck on - is removing the email address form the Google Form response. One way would be to use deleteAllResponses() but that will also delete the basic data analysis pre-done by Google that I intend to use (to save time on creating some of the graphs).
I tried to find a way to access the response object and delete/modify the email field, but was unable to achieve that.
Would appreciate the help.
function myFunction() {
//delete the last email that was added
function deleteEmails(Row){
sheet.getRange('B'+Row + ':B'+Row).clearContent();
}
//delete all responses - would like to change this to only delete/modify the email field.
function deleteResponses() {
var form = FormApp.openById('The form ID');
form.deleteAllResponses();
}
//get the data on the sheet
var sheet = SpreadsheetApp.openById("The sheet ID").getSheetByName('Form Responses 1');
var StartRow = 1;
var LastRow = sheet.getLastRow();
var Range = sheet.getRange(LastRow, 2, 1, 62)
var AllValues = Range.getValues();
//if the person disagrees to fill the form - dont send an email
if (AllValues[0][1] != 'disagree') {
var SendTo = AllValues[0][0];
var body = "Thank you for answering pfa a link for the sedond form";
//send the actual email
MailApp.sendEmail({
to: SendTo,
cc: "",
subject: 'Thank you for answering',
htmlBody: body,
});
}
//delete emails and responses
deleteEmails(LastRow)
deleteResponses()
}

Google Apps Script failing onFormSubmit with concurrent responses

I've setup a Google Form and linked Sheet to record form responses and then create and email the respondent a letter from the submitted data. This has been working fine and has started getting quite popular among colleagues, but now a problem has arisen with onFormSubmit when two users submit the form at the same time.
Essentially, the script is setup to run on the last row of the sheet onFormSubmit but if two responses are submitted concurrently it only runs the script on the last entry, potentially twice.
I'm thinking it might be possible to get around this by setting up a column to be marked if the script completed and then setting up a time-drive trigger to run on any rows that haven't been marked but this feels a bit clunky as respondents usually require the letter immediately.
Is there another way to approach the problem so that onFormSubmit makes sure the script actually runs on the row created by the original form submission and not simply the last row? Any help would be much appreciated, here's an example of my code:
function createLetterFromForm(){
// Get data from sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
// Define range and data in each column
var data = sheet.getRange(sheet.getLastRow(), 1, 1,
sheet.getLastColumn()).getValues(); // Range (last entry submitted)
for (var i in data){
var row = data[i];
// Pick the right template
if (row[9]=="A"){
var templateid = "xxxxxxxxxxxx";} // Template 1
if (row[9]=="B"){
var templateid = "xxxxxxxxxxxy";} // Template 2
// Make copy and set active
var folder = DriveApp.getFolderById("zzzzzzzzzzzzzz") // Folder for generated letters
var docid = DriveApp.getFileById(templateid).makeCopy(row[7]+" - Letter",folder).getId();
var doc = DocumentApp.openById(docid);
var docBody = doc.getActiveSection();
// Copy data to template
// address
docBody.replaceText("%FNAME%", row[2]);
docBody.replaceText("%SNAME%", row[3]);
docBody.replaceText("%ADDL1%", row[4]);
docBody.replaceText("%ADDL2%", row[5]);
docBody.replaceText("%ADDL3%", row[6]);
docBody.replaceText("%PCODE%", row[7]);
// other data
docBody.replaceText("%DATA1%, row[8]);
// etc.
// Share and Save doc
doc.addEditor(row[1]);
doc.saveAndClose();
// Email PDF to Respondee
var sendFile = DriveApp.getFilesByName(row[7]+' - Letter');
var recipient = row[1]
MailApp.sendEmail({
to:recipient,
subject: "Your Letter",
body:"Hello, \n\nHere's a PDF copy of the letter you created.",
attachments: [sendFile.next()]
});
}
}