RESOURCE_EXHAUSTED when extracting from Google Form to Google Sheet - google-apps-script

I'm trying to extract questions and multiple choice options of a Google Form to a Google Sheet. I've found a solution here (Is it possible to export questions and multiple choice options from a Google Form to a Google Sheet?), in the answer by alberto vielma (answer of Oct 28 '19 at 12:06).
However, I'm running into an error ("We're sorry, there was an unexpected error while creating the Cloud Platform project. Error code RESOURCE_EXHAUSTED.") when trying Alberto's script.
This surprised me, because I've used the script succesfully a few months ago... Does anyone have an idea what exactly went wrong?
(I created a new topic, because the 'tips' about answering suggested I shouldn't "contribute" to above mentioned topic if I only had extra questions.)
For your convenience, I'll copy Alberto's script here:
var form = FormApp.openById('YOUR-FORM-ID');
// Open a sheet by ID.
var sheet = SpreadsheetApp.openById('YOUR-SHEET-ID').getSheets()[0];
// variables for putting the questions and answers in the right position
var question_position = 0;
var answers_position = 0;
// main function to run
function getFormValues() {
form.getItems().forEach(callback);
}
// Iterate over all questions
function callback(el){
// check if the question is multiple choice
if (el.getType() == FormApp.ItemType.MULTIPLE_CHOICE) {
// change the type from Item to MultipleChoiceItem
var question = el.asMultipleChoiceItem();
var choices = question.getChoices();
// set the title of the question in the cell
sheet.getRange(question_position +1, 1).setValue(question.getTitle());
var i = 0;
// set the answers in the right cells
for (i; i < choices.length; i++){
sheet.getRange(answers_position + 1, 2).setValue(choices[i].getValue());
answers_position++;
}
question_position += i;
answers_position++;
}
question_position++;
}

This was a known issue impacting some users earlier today (which appears to be no longer persistent.) Ref https://issuetracker.google.com/issues/194826559?pli=1

Was there any value written to your spreadsheet when you got the error?
I wonder it deal with usage limits because you have many setValue to spreadsheet.
Maybe you can try to first push the all single values (questions and choices) to an array values. And finally use setValues(values) to reduce the number of calls of setValue.
Or you could try to add some Utilies.sleep(milliseconds) in each loop.

Related

Using Gmail labels in Apps Script for Sheets

I am trying to evaluate emails with an existing label called "TestLabel" (applied via a simple Gmail filter on receipt), then once processed via a script called "extractDetails", remove the label. My problem is that old emails, that previously had the label but have already been processed, continue to meet the condition in subsequent executions. I have verified (at least visually) that the label is no longer attached. I have also turned off "conversation" view in Gmail, hoping/believing that the nested thread was the issue. Strangely, not all previous emails get reprocessed - but, for example, the most recent 35 or so from a list of hundreds. The only thing I've found that solves this is permanently deleting the prior emails, but I'd like to avoid doing so, and I am also curious to simply solve the problem.
My code is as follows:
function getGmailEmails(){
var label = GmailApp.getUserLabelByName('TestLabel');
var threads = label.getThreads();
var i = 0;
for(var i = threads.length - 1; i >=0; i--){
var messages = threads[i].getMessages();
for (var j = 0; j <messages.length; j++){
var message = messages[j];
extractDetails(message);`
}
threads[i].removeLabel(label);
threads[i].markRead()
threads[i].moveToArchive(); ;
}
}
Thank you to this community for your assistance. Hopefully I posed this question properly.
Edit: This short script returns a value of 57, when the verfied # of labelled messages in Gmail is 2. The other 55 emails were, at one point, also labelled the same but have been processed and the label has been removed.
function getLabel () {
var label = GmailApp.search('label:TestLabel');
Logger.log(label[0].getMessageCount());
}
Further edit:
I changed the applied label to a new one in the Gmail Filter and the script. Oddly, the legacy emails still are captured - not only without the original label, but most certainly without the new one. I'm baffled.

Converting "Create Multiple Choice Form Question from spreadsheet" script to "Create Checkbox etc." script - error?

Question: What is causing the error in this script when replacing "asMultipleChoiceItem()" with "asCheckboxItem"? And is there an obvious way to correct it?
Short version: I am trying to implement a checkbox version of the solution (found here), by replacing "item.asMultipleChoiceItem()" with "item.asCheckboxItem()"; however, I'm encountering an error on debugging "Invalid conversion for item type: MULTIPLE_CHOICE." (debug image here). I'm having trouble troubleshooting to identify/understand, and therefore figure out how to correct, the error.
My code:
function DeptUpdate() {
// User settings
var OPTIONS_SPREADSHEET_ID = "1q21HxRkwXxVtiw7D5fuO-w0JCQtZRd-A35gRtmJUwKk";
var OPTIONS_SHEET_NAME = "Present";
var OPTIONS_RANGE = "A:A"; // We have the options, listed in column A
var itemNumber = 1; // which question on form does this apply to
//
var options2DArr = SpreadsheetApp.openById(OPTIONS_SPREADSHEET_ID).getSheetByName(OPTIONS_SHEET_NAME).getRange(OPTIONS_RANGE).getValues();
var options = options2DArr.reduce(function(a, e) {
if (e[0] != "") {
return a.concat(e[0]);
}
return a;
}, []);
var form = FormApp.openById("1JHZoCdJrsRIltMwKqWGZizRQuy-2Ak2-XET83s04goc");
var item = form.getItems()[itemNumber - 1];
item.asCheckboxItem()
.setTitle("SELECT NAME")
.setChoiceValues(options)
.showOtherOption(true);
}
Long version:
Goal: Google script in Google sheets, on trigger, updates targeted form's checklist options to reflect the items listed in the defined range (excluding blanks).
Purpose/Context: This is one part of a series of forms and spreadsheet that allow me to track arrivals, hall passes out/in, and departures from a study hall in which any 10-20 students from a pool of 120 possible may attend any given day. Spreadsheet is linked to forms to provide a "head's up display" of which students are present, and which are signed out to other locations (this all works fine). Restricting Hall Pass Out and Departure form answer choices (student names) to only those check in as "present" drastically cuts down on time and user errors in the logging system. Currently works with multiple choice, but students frequently arrive/leave in groups. Checkbox (multiple response) would further expedite the tracking process. Spreadsheet is otherwise set up to process multiple response entries; just need the form to appropriately update.
Process/Attempts: I've read of others who adjusted similar (different purpose) scripts to change from dropdown/multiple choice to checkbox without issue ("I just change this and it worked, great!" is the extent of what I've read), but as soon as I change to checkbox, I get the attached error for both the showOtherOption field, and (if that is removed), the setChoiceValues field. I'm thinking it could possibly be an issue with the checkbox item reading the array differently than the multiple choice item does? However, I haven't be able to find anything in the documentation or Q/A posts on a significant difference between the two functions parameters. At this point, I'm just a little flummoxed on what might be causing the issue.
Background: I have no formal (or significant informal) coding training, but have tweaked and adapted a variety of codes for about a decade. I understand the basic processes/concepts of code and programming logic, but lack a substantial/cohesive vocabulary.
I'm including a link to a dummy copy of the spreadsheet and the form, in case that's helpful.
Spreadsheet
Form
Thank you in advance for any insights!
Brandy
The problem is that you have a ListItem but try to convert it to a CheckboxItem
This is not directly possible. There is a feature request on Google's Public Issue Tracker for this feature. I recommend you to give it a "star" to increase visibility.
In the mean time, if you want to convert an item type, you need to do it manually by creating a new item, passing it the title and choice from the old one and deleting the old item:
Sample
function DeptUpdate() {
// User settings
var OPTIONS_SPREADSHEET_ID = "1wHE6b5ZuAKJTM4N7t6nlB5SdU9h24ueuxon4jnH_0sE";
var OPTIONS_SHEET_NAME = "Present";
var OPTIONS_RANGE = "A:A"; // We have the options, listed in column A
var itemNumber = 1; // which question on form does this apply to
//
var options2DArr = SpreadsheetApp.openById(OPTIONS_SPREADSHEET_ID).getSheetByName(OPTIONS_SHEET_NAME).getRange(OPTIONS_RANGE).getValues();
var options = options2DArr.reduce(function(a, e) {
if (e[0] != "") {
return a.concat(e[0]);
}
return a;
}, []);
var form = FormApp.getActiveForm();
var listItem = form.getItems()[itemNumber - 1];
listItem
.asListItem()
.setTitle("SELECT NAME")
.setChoiceValues(options)
var title = listItem.getTitle();
var choices = listItem.asListItem().getChoices();
var checkboxItem = form.addCheckboxItem();
checkboxItem.setTitle(title)
.setChoices(choices)
.showOtherOption(true);
form.deleteItem(listItem);
}

Is it possible to export questions and multiple choice options from a Google Form to a Google Sheet?

We have a series of Google Forms that contain multiple choice questions, each with 4 possible answers.
I would like to be able to export the question and all possible answers to a Google Sheet for all of the questions and answers in that Google Form.
For example:
Q1: What is the capital of England?
A: London
B: Paris
C: Madrid
D: Helsinki
I've tried a variety of add-ons. There are loads that allow Google Sheets > Google Form, but nothing in reverse (that I can find), so I assume it will be a script of some kind.
Any help would be really appreciated.
Thanks. Liam.
In the following code, which I made using Apps Script, you can find a way to extract questions and answers from a google form and then put the values in a certain sheet of your choice
// Open a form by ID.
var form = FormApp.openById('YOUR-FORM-ID');
// Open a sheet by ID.
var sheet = SpreadsheetApp.openById('YOUR-SHEET-ID').getSheets()[0];
// variables for putting the questions and answers in the right position
var question_position = 0;
var answers_position = 0;
// main function to run
function getFormValues() {
form.getItems().forEach(callback);
}
// Iterate over all questions
function callback(el){
// check if the question is multiple choice
if (el.getType() == FormApp.ItemType.MULTIPLE_CHOICE) {
// change the type from Item to MultipleChoiceItem
var question = el.asMultipleChoiceItem();
var choices = question.getChoices();
// set the title of the question in the cell
sheet.getRange(question_position +1, 1).setValue(question.getTitle());
var i = 0;
// set the answers in the right cells
for (i; i < choices.length; i++){
sheet.getRange(answers_position + 1, 2).setValue(choices[i].getValue());
answers_position++;
}
question_position += i;
answers_position++;
}
question_position++;
}
Docs:
If you're wondering where I got all this info you can check these two links:
Spreadsheet
Google Forms
I got almost the same problem that you were dealing with, I created a little script with the documentation for my own purposes but I think it may help you to understand how to retrieve the information.
You need to be aware of these two API:
https://developers.google.com/apps-script/reference/forms (forms) and https://developers.google.com/apps-script/reference/spreadsheet (sheets)
Google Form mapping
Then, I would check how to post it into a Google Sheet through the API.
Check you have all the permissions set.
This seems like you'd need an Apps Script add-on or a manually developed Apps-Script script. Try to find a freelancer or a coworker to build it for you.
Sheets is the easiest to work with: https://developers.google.com/apps-script/reference/spreadsheet/
I needed a script to convert some Google Forms to the GIFT Moodle format. I modified #alberto-vielma script to obtain a SpreadSheet with the questions and choices in Moodle GIFT format.
Just copy and paste the values in the the SpreadSheet in a text file to import into Moodle.
// Open a form by ID.
var form = FormApp.openById('YOUR-FORM-ID'); // YOU GET IT FROM THE URL
// Open a sheet by ID.
var sheet = SpreadsheetApp.openById('YOUR-SPREADSHEET-ID').getSheets()[0];
// variables for putting the questions and answers in the right position
// Change this number to the line you want the question starts
var question_position = 1;
// main function to run
function getFormValues() {
form.getItems().forEach(callback);
}
// Iterate over all questions
function callback(el){
// check if the question is multiple choice
if (el.getType() == FormApp.ItemType.MULTIPLE_CHOICE) {
// change the type from Item to MultipleChoiceItem
var question = el.asMultipleChoiceItem();
var choices = question.getChoices();
// set the title of the question in the cell
var qRange = sheet.getRange(question_position++, 1);
qRange.setValue(question.getTitle() + " {");
var i = 0;
// set the answers in the right cells
for (i; i < choices.length; i++){
var choiceRange = sheet.getRange(question_position++, 2);
var current = choices[i];
var prefix = current.isCorrectAnswer() ? "'=" : "~";
choiceRange.setValue(prefix + current.getValue());
}
var qRangeEnd = sheet.getRange(question_position++, 1);
qRangeEnd.setValue("}");
question_position ++;
}
}

Service error: Spreadsheets(line... with .setColumnFilterCriteria

This question is an extension from another.
Apply basic filter to multiple values in a spreadsheet column
I am experiencing an error, specifically Service error: Spreadsheets (line 8, file "Filter") with the following code:
function testFilter() {
var ss = SpreadsheetApp.getActive();
var monthlyDetailSht = ss.getSheetByName("Monthly_Detail");
var filterRange = monthlyDetailSht.getRange(2,12,359,1).getValues(); //Get L column values
var hidden = getHiddenValueArray2(filterRange,["Apple"]); //get values except Apple
var filterCriteria = SpreadsheetApp.newFilterCriteria().setHiddenValues(hidden).build();
var rang = monthlyDetailSht.getDataRange();
var filter = rang.getFilter() || rang.createFilter();// getFilter already available or create a new one
//remove filter and flush
if(monthlyDetailSht.getFilter() != null){monthlyDetailSht.getFilter().remove();}
SpreadsheetApp.flush();
filter.setColumnFilterCriteria(12, filterCriteria);
};
//flattens and strips column L values of all the values in the visible value array
function getHiddenValueArray2(colValueArr,visibleValueArr){
var flatArr = colValueArr.map(function(e){return e[0];}); //Flatten column L
visibleValueArr.forEach(function(e){ //For each value in visible array
var i = flatArr.indexOf(e.toString());
while (i != -1){ //if flatArray has the visible value
flatArr.splice(i,1); //splice(delete) it
i = flatArr.indexOf(e.toString());
}
});
return flatArr;
}
I have used a Logger.log(hidden) to capture the values returned by the function and it is a list of all of the other "fruits" repeated as many times as they are available in column L. I am using fruits as a substitute for the sensitive data.
So here goes my question. Why am I getting that error now when it was working perfectly fine for a couple of days? How can I correct this?
Attempted fixes:
I've tried to add rows to the end of my data. Did not fix.
I tried removing filter, flushing, setting filter. Did not fix. (updated code above with what I did to flush in case anyone else is interested.)
It's working now. A couple of things I want to note for people who stumble upon this with their google searches. First, the issue was in fact an error on Google's side. Using the same code I have above it now works. I did not change it.
Second, I was able to record the filtering through the macro recorder and that code worked when my original code did not. This may help people who are on a time crunch and can't wait for google to get their stuff together. I'm still not sure what specifically in my original code caused the error, but my guess is that it does not matter. I've dedicated a full day to researching this error and it seems sporadic with not a single culprit. My issue may not be the same as yours if it happens in the future.
Hope that helps!

Google Drive - How to Autopopulate Google Spreadsheet with Concatenate functions when users submit data via webform?

I have a Google Drive Spreadsheet in which I'm trying to have a formula autopopulate all the way down the rows, as users submit data via a webform attached to the spreadsheet. The tricky part is that I use a CONCATENATE function already, to perform a concatenation of the data submitted on several columns into one single cell.
However, for the CONCATENATE function to work, I have to "apply" it to newly submitted rows.
Is there a way to automate the filling of this formula down the rows in the spreadsheet?
I've tried to place an ArrayFormula function to it, even setting the range (A1:A), but I couldn't find the proper syntax for it work, if it may like this.
The function goes:
=CONCATENATE(CHAR(10)&X14&V14&Y14&J14&" "&K14&" "&L14&M14&N14&O14&" "&P14&" "&Q14&R14&S14&CHAR(10)&T14&"."&CHAR(10)&U14&"."&CHAR(10)&W14&CHAR(10)&CHAR(10)&CHAR(10)&I14&CHAR(10)&Z14&" "&AA14&CHAR(10)&AB14&AC14&AD14&AE14&AF14&AG14&AH14&"."&CHAR(10)&AI14&AJ14)
Any suggestion will be greatly appreciated.
(Answered by the OP in a question edit. Transformed into a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
I've found a little script from the Script Gallery of Google Spreadsheet (AutoFormulas, by tuxincarnate[#]gmail[dot]com), which solves the trick! Just tested it with a dozen of submissions from the webform and it does what it promises, autopopulate with formulas down the columns where applied.
// Updates all rows except the last to have the same formulas as row 3 (allowing for a header and different row 2 formula)
// To activate this functionality, the last row in the column should have the value '(auto)'
function UpdateFormulas() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetCount = ss.getNumSheets();
for (var sheetIndex = 0; sheetIndex < sheetCount; ++sheetIndex) {
var sheet = ss.getSheets()[sheetIndex];
var rowCount = sheet.getMaxRows();
var columnCount = sheet.getMaxColumns();
if (rowCount < 5) continue;
for (var columnIndex = 1; columnIndex <= columnCount; ++columnIndex) {
if (sheet.getRange(rowCount, columnIndex).getValue() == '(auto)') {
var row3Range = sheet.getRange(3, columnIndex);
for (var rowIndex = 4; rowIndex < rowCount; ++rowIndex) {
if (sheet.getRange(rowIndex, columnIndex).isBlank()) {
row3Range.copyTo(sheet.getRange(rowIndex, columnIndex));
}
}
}
}
}
}
#David Tew wrote:
Whilst you have a solution already, you might like to consider for the future the following formula, which is what you were originally looking for (You don't need to use CONCATENATE since you are choosing the columns to join together with & symbol)
=arrayformula(CHAR(10)&X2:X&V2:V&Y2:Y&J2:J&" "&K2:K&" "&L2:L&M2:M&N2:N&O2:O&" "&P2:P&" "&Q2:Q&R2:R&S2:S&CHAR(10)&T2:T&"."&CHAR(10)&U2:U&"."&CHAR(10)&W2:W&CHAR(10)&CHAR‌​(10)&CHAR(10)&I2:I&CHAR(10)&Z2:Z&" "&AA2:AA&CHAR(10)&AB2:AB&AC2:AC&AD2:AD&AE2:AE&AF2:AF&AG2:AG&AH2:AH&"."&CHAR(10)&‌​AI2:AI&AJ2:AJ)
this should go in the second row
The OP wrote:
#DavidTew showed me a clear and easy way to have it solved. The ArrayFormula should go alone, telling it to put together the ranges for every column into every single row. Works like charm. Proper syntax is: =arrayformula(A2:A&B2:B&C2:C), in order to have contents from cells A2, B2 and C2 "concatenated" into the cell where the ArrayFormula is applied. The most important issue is that by using this function, it autpopulates all the way down the rows as users submit data via a webform attached to the spreadsheet.