Problems retrieving formResponse title - google-apps-script

I'm working on Google Apps Script which should process data submitted from the Google Form.
Problem is that I'm getting this error after execution of itemResponse.getItem().getTitle():
Execution failed: Failed to retrieve form data. Please wait and try again. (line 20, file "Code") [0.664 seconds total runtime]
Example:
I created a sample form with sample questions (question1, question2 ... question10).
In Script editor i created a simple script to log the question titles:
function checkSubmitted() {
var form = FormApp.getActiveForm();
var formResponses = form.getResponses();
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
var itemResponses = formResponse.getItemResponses();
Logger.log(itemResponses.length);
for (var j = 0; j < itemResponses.length; j ++) {
var itemResponse = itemResponses[j];
var item = itemResponse.getItem();
Logger.log(item.getTitle()); //this is the problematic line
Logger.log(item.getId());
}
}
}
Sometimes it gets logged just 9 question sometimes about 16 question, looks to me like it is random, because in some forms with fewer question this code get through some formResponses and than it die on third question.
Any suggestions what could be wrong?

I'm having the exact same problem with a script that was working fine just yesterday. Honestly, I think there's a problem with the platform. Googling it return no results but this very post. The closer I've seen is this, and the answers did not help.

Related

How to make a statement that checks if there's a response to an item in a google form

I want to make some kind of statement that checks if an item in the form has a response or not. Like if the item has no response it does nothing further but if it does it will continue on.
If you have a look at the documentation
https://developers.google.com/apps-script/reference/forms/
You will find a couple of useful methods. So, getItemResponses() returns a string object and allows you to check if the string is not empty (which would mean that there is no response) .
Example code:
// This code gets all the form responses and checks if the response to question number 3 empty
function myFunction()
{
// Open a form by ID and log the responses to each question.
var form = FormApp.openById('1DUR5CfnI3Dk3LfFC4tiYJiaKRGd1DViYwQBWi9jxC4A');
var formResponses = form.getResponses();
var formResponse;
var itemResponses;
var itemResponse;
//i loops through different submissions of a form, e.g. if 3 users submitted a form - there will be three entries for formResponse
for (var i = 0; i < formResponses.length; i++)
{
formResponse = formResponses[i];
itemResponses = formResponse.getItemResponses();
// j loops through the different questions of each submitted form
for (var j = 0; j < itemResponses.length; j++)
{
itemResponse = itemResponses[j];
// the if loop checks if the response is an empty string
if(j==2&&(itemResponse.getResponse()==""||itemResponse.getResponse()==" "))
{
Logger.log('There is no response for question %s in form submission #%s', (j + 1).toString(),(i + 1).toString())
}
}
}
}
Useful for you could be also isRequired()
to make the response to a question obligatory and thus, make sure that there will be a response to the item. Hope this helps!

Getting the body of individual emails from gmail to google sheets

I'm really new at using Google Apps Script, so if what I'm trying doesn't make sense, or just isn't possible please let me know.
Everyday I get several emails that look like the following:
Your Name: FirstName LastName
Phone Number: 555 867 5309
Email Address: FakeEmail#email.com
What do you need help with? Request someone makes.
I'm attempting to automatically send the body of these emails to a new line in a Google Sheet when they come in.
As of right now I have every email get the label "myLabel" when it comes in. I then run the following script, which is a slightly modified version of something I found here:
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var label = GmailApp.getUserLabelByName("MyLabel");
var threads = label.getThreads();
for (var i=0; i<threads.length; i++)
{
var messages = threads[i].getMessages();
for (var j=0; j<messages.length; j++)
{
var msg = messages[j].getBody();
ss.appendRow([msg])
}
threads[i].removeLabel(label);
}
}
I'm attempting to run this code with a timer trigger every 15 minutes. The issue I've run into is that every time the code runs it pulls from every email in the thread. I would like it to just pull from the emails that are new since the last time it ran. Any advice would be greatly appreciated.
Why not mark the messages as read when you finish processing them? Here is a sample from one of my scripts.
var pendingEmailLabel = "MyLabel";
var threads = GmailApp.getUserLabelByName(pendingEmailLabel).getThreads();
for (var t = 0; t < threads.length; ++t) {
var thread = threads[t];
var messages = thread.getMessages();
for (var m = 0; m < messages.length; ++m) {
var message = messages[m];
if (message.isUnread()) {
// INSERT YOUR CODE HERE THAT TAKES ACTION ON THE MESSAGE
message.markRead();
}
}
}
}

Using a script to edit data from a form submission

It appears the data submitted to a Google Form is saved not just in the associated spreadsheet, but also in the Form itself I have an HTML interface that displays the data to internal staff in a Non-Profits account. Some of this data may change or may not be known at the time of submission. Other information is saved in additional fields in the associated spreadsheet. I can add and edit that data, but is it possible to edit the data in the form file as well?
It is possible to get the data saved as a response in the form itself, and you can submit new responses programmatically. I don't think you can alter existing responses with Google Apps Script. See https://developers.google.com/apps-script/reference/forms
// Open a form by ID and log the responses to each question.
var form = FormApp.openById('1234567890abcdefghijklmnopqrstuvwxyz');
var formResponses = form.getResponses();
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];
Logger.log('Response #%s to the question "%s" was "%s"',
(i + 1).toString(),
itemResponse.getItem().getTitle(),
itemResponse.getResponse());
}
}

Google Apps substring from null

I put my first Google Apps Script together to write emails to a spreadsheet. It works fine, except of the substring method I would like to use to shorten the message body. The script engine returns "cannot call substring from null […]". I found this thread (google apps script TypeError: Cannot call method "substring" of undefined) but the solution didn't help – or I didn't understand it which is about as likely.
Here's my script.
function labelToSpreadsheet() {
var threads = GmailApp.getUserLabelByName('newaddress').getThreads();
var spreadsheet = SpreadsheetApp.openById("onehellofanID")
var sheet = spreadsheet.getSheets()[0];
Logger.log (spreadsheet.getName());
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var shortendContent = messages[j].getPlainBody().substring(0, 500);
sheet.appendRow([messages[j].getSubject(), messages[j].getFrom(), messages[j].getReplyTo(), messages[j].getDate(), shortendContent]);
}
}
};
This was driving me nuts, as there was no reason your code wouldn't work, and I was getting the same error. I narrowed it down to the 'getPlainBody()' was returning 'null', but couldn't figure out why this was the case even when I used GMails own example.
I was almost going to call it a bug when I realized that what was happening was that some messages were returning nothing in the body. Specifically, some companies send out newsletters that aren't text content at all, but in fact are images with their content inside (Which was the case with the first message in the test label I had, thus driving me bonkers).
So, the issue here is that the label you're running this under has some messages where the content is only an image, no text whatsoever (Or potentially, is just completely blank), thus 'getPlainBody()' returns 'There's nothing there'(Null) and you can't get a substring of nothing.
A simple 'if' statement actually handles this error really well, as you can then tell the script to write to the sheet 'The content of this message was an image' (Or whatever you want).
This slightly modified version of your code works for me:
function labelToSpreadsheet() {
var threads = GmailApp.getUserLabelByName(LABELNAME).getThreads();
var spreadsheet = SpreadsheetApp.openById(SHEETID);
var sheet = spreadsheet.getSheets()[0];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
if(messages[j].getPlainBody() == null){
var shortendContent = 'This message was an image';
}else{
var shortendContent = messages[j].getPlainBody().substring(0, 500);
};
sheet.appendRow([messages[j].getSubject(), messages[j].getFrom(), messages[j].getReplyTo(), messages[j].getDate(), shortendContent]);
}
}
};
I'm giving myself a gold star for this one, it was annoying to figure out.

Get the current response onSubmit

Is there any way to find out the current response of the Google Form (programmatically)?
In the onSubmit function.
Looked over their documentation but I have to provide the respondId.
How do I find the respondId?
A snipped code from them about this is:
// Open a form by ID and log the responses to each question.
var form = FormApp.openById('1234567890abcdefghijklmnopqrstuvwxyz');
var formResponses = form.getResponses();
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];
Logger.log('Response #%s to the question "%s" was "%s"',
(i + 1).toString(),
itemResponse.getItem().getTitle(),
itemResponse.getResponse());
}
}
UPDATE:
function onSubmit(e) {
/* Get values entered by filling the form */
var itemResponses = e.response.getItemResponses();
var myWantedValue = itemResponses[COLUMN_NUMBER].getResponse();
}
Note: By passing the e(vent) as parameter the values can be accessed by submitting the live form, NOT by the script editor!
This code gives you the values for the last form response, is that what you're looking for ?
function myFunction() {
var formResponses = FormApp.getActiveForm().getResponses();
Logger.log(formResponses.length);
var formResponse = formResponses[formResponses.length-1];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
Logger.log('Last response to the question "%s" was "%s"',
itemResponse.getItem().getTitle(),
itemResponse.getResponse());
}
}
You are trying to read the exact response that triggered the execution of onSubmit(), to run another process on particular data, such as sending a confirmation email.
If the above is correct:
Instead of using the form as a data source for your later processing, try to read the Google Sheet storing the responses. It may seem the problem is the same: reading either data source (the form itself, or the sheet storing the data), doesn't point you to the exact entry that has triggered the onSubmit() event.
The difference is that in a sheet you can create a "reply_sent" column, to timestamp the instant each form response has been postprocessed, for example, having sent an automated reply based on its contents.
Then, when onSubmit() is run, it goes through all responses and processes not only the last one received, or the one having triggered the onSubmit() funtion, but also any other response that may have been left unreplied for whatever reason ("reply_sent" field blank). A last benefit from this approach is that your script is logging how it is behaving, since a date is recorded along with each response as it triggers obSubmit().
You cannot set up a custom confirmation message for each user.