I've tried to create a Google Form with Google Apps Script without success.
My goal is to redirect to a new page depending on the results of multiple answers, not just one. I've got three questions and if some of them has a specific answer I've would like to go to another page.
It seems like its possible just for one question like this:
var choiceOne = item.createChoice('Vanilla', FormApp.PageNavigationType.CONTINUE);
var choiceTwo = item.createChoice('Chocolate', FormApp.PageNavigationType.SUBMIT);
Is it a way to solve the problem?
Related
When editing a Google form manually, you can usually click on an item, and on the side appears a menu, which includes the button "import questions". This button is very useful for me as it allows me to collect questions from past Google forms and import them to new Google forms.
But I'm looking through the Forms documentation, and I can't figure out how to do this via Google apps script programatically.
Here is the documentation:
https://developers.google.com/apps-script/reference/forms/form
The closest thing to what I want is the .moveItem() method, which moves an item from one spot in a form to another. But it only works within the same form. I want to know if I could do it across forms. And ideally, instead of moving the item, it would make a copy of the item in the new form.
I considered the .getItems() method, but there doesn't seem to be a general .addItem() method I could use on the new form. Would I have to go through the painstaking process of having to identify each item type, and specify how the details of each one should be copied to the new form, including things like point values of a question and whether or not the question is required?
I want to import from forms that have all kinds of content: video, images, multiple choice questions, grid questions, number scale questions, etc. I feel that if I have to specify the details of each item type, it would take too long, and I would be bound to miss something or run into an error that may be impossible to solve. Is there not an easier way?
And if specifying each item type is what I have to do to import everything properly, has someone else created that code already that I can re-use?
Issue:
In the current stage, unfortunately, it seems that Forms Service cannot copy all items. Ref1, Ref2 Ref3. And, unfortunately, moveItem can be used for the same Google Form as you say.
Workaround:
In your situation, as a workaround, how about copying the source Google Form? And, when there are some items you want to remove, you can remove them. I thought that this process can be achieved by Google Apps Script.
But, I'm not sure about your actual Google Form. So I'm not sure whether this is a suitable method.
Future:
Recently, Google Forms API was announced. Ref When this API got to be able to be used, your goal might be able to be achieved by retrieving the object from Google Form. Unfortunately, I'm still not sure about the detail of it.
I have a script for Google Sheets I am working on. I realize there are better ways to do what I am attempting (cough html/database cough), but I am required to make this spreadsheet work.
In short, I am trying to hide and unhide rows dynamically. There does not appear to be a way to get filters to update without redoing them, so I am attempting to use hideRows to hide them and unhideRows to reveal them as needed.
The hideRows command works below. The unhideRows command does not. At this time, they are literally this close together in the code. Originally, I was hiding on one sheet and unhiding on another, but set up like this to troubleshoot. There is no filtering on this sheet (because it didn't work, I turned it off). I tried setting the value in unhideRows directly to the value tested instead of a variable.
The row in question hides, but does not unhide.
I tried unhiding a different row just in case google was fumbling with hide this, unhide it back to back. I am not getting unhide to work.
{ //thisRow = the row number of a range, in this case 2 if output to screen
pImages.hideRows(thisRow);
pImages.unhideRows(thisRow);
}
Apparently, the answer is not to unhideRows() which is the one the documents alluded to, but showRows () which does make more sense in everyday language. Thanks again to Mr.Houdini on the Google forums.
I am creating a Google Form dynamically, and emailing it, using Google Apps Script.
I have all the users info, and have figured out how to record the response. However, I would like to add that person's email to the row in the sheet.
It would be ideal if there was a way, since we already collected their email, to pass this email in the "background" to the form we send, and it is attached with there answer in the responses sheet.
Thanks!
I was not able to rest until I got this worked out. This article from almost three years ago really helped.
Not exactly what I was going for, still open if anyone knows how to actually pass info in the background to a sheet.
var items = formName.getItems();
var itemOfInterest;
for(var i in items){
if(items[i].getTitle()=='QUESTION_TITLE'){
itemOfInterest=items[i];
}
}
var preFilledUrl =
schedForm.createResponse().
withItemResponse(itemOfInterest.asTextItem().createResponse(email)).
toPrefilledUrl();
This prefills that question box, so also giving the user the ability to edit before they send. It'll work.
I want to use a script to change the behavior of an existing Google Form so that after completing page 1, future respondents will go to another page (say, page 3).
I know this involves using .setGoToPage(), but I don't how to set the parameters to make this modification.
Take into account that the pages in the form are already created, so I just need to indicate that page 1 should go to page 3. To clarify, my problem is that I need to find "page 1" without its name being known so that, afterwards, I can apply the ".setGoToPage(pageThree);" command to page 3 (whose name is also not known).
The real goal here is actually to set page 1 to go back to itself so that no one can see the options of page two, essentially blocking the form from being used. I just worded it this way to be able to undo it later on. It must be a script because it will be added to another script that does other things. I cannot go into the form and do this manually.
function myFunction() {
var form = FormApp.openById("ID GOES HERE");
var item = form.getItems(itemType);
// here is where I need the rest of the script
.setGoToPage("PAGE THREE GOES HERE");
}
Good news, bad news. First the good news.
You were on the right track; you can get all the page break items via Form.getItems(FormApp.ItemType.PAGE_BREAK), which will result in an ordered array of sections. The "first page" (section 1) ends with page break #0, the second with page break #1, and so on.
So modifying the form to go to section 3 after section 1 is easy:
function myFunction() {
var formId = '--form-id--';
var form = FormApp.openById(formId);
var pageBreaks = form.getItems(FormApp.ItemType.PAGE_BREAK);
pageBreaks[0].asPageBreakItem().setGoToPage(pageBreaks[1].asPageBreakItem());
}
Don't forget the .asPageBreakItem() calls, since the results from .getItems() are generic Items, but you need a PageBreakItem specifically, in order to use .setGoToPage().
Now the Bad News... Sections end with page breaks, so there is none to set as a destination for the first section.
However, since you want to effectively disable the form, you could just stop accepting responses.
function myFunction() {
var formId = '--form-id--';
var form = FormApp.openById(formId);
form.setAcceptingResponses(false);
}
Excellent Mogsdad. I could not use the second option you gave because the goal is to make sure the users cannot see the rest of the form, because the form essentially is an exam, so just turning off responses would be insufficient.
BUT, you indirectly solved the problem because what I did was put an empty extra page in between page one and two (making page two really page three) and used your script but slightly modified and it has achieved what I was aiming for.
function myFunction() {
var form = FormApp.openById('FORM ID HERE');
var pageBreaks = form.getItems(FormApp.ItemType.PAGE_BREAK);
pageBreaks[0].asPageBreakItem().setGoToPage(pageBreaks[0].asPageBreakItem());
pageBreaks[1].asPageBreakItem().setGoToPage(pageBreaks[0].asPageBreakItem());
}
Grab page 2 and setGoToPage to FormApp.PageNavigationType.RESTART.
Page 2's pageNavigationType is where page 1 goes after you complete it without choosing an option that redirects you. To go to page 1, use FormApp.PageNavigationType.RESTART. To go to any other page, use that page as a pageBreakItem.
I realize this topic is nearly three years old but, as there is a better answer, I thought I'd reply for anyone who stumbles across it.
OK, I'm tired of searching for specific questions to help with a project, finding answers, changing my implementation which just adds more questions, realizing there's a better way to do things, etc. So allow me to ask for general assistance, I will then do my best to research how to do it and ask further questions if needed.
I'm writing a script to be used as a Gadget in a Google Site page
(I'm more than willing to share this if anyone wants to take a look
at it); right now I'm doing this just for me, but I want to write
this to be easily used by others.
This will list all user's Google Docs in a specified folder; when
selecting the document from the list, the contents will be displayed
for editing in another field.
The user will be able to define certain lines, starting wit a period,
to "mark" as chords that can be automatically transposed with the
push of a button; that is to say, the user clicks a button and all
A's go to A#, B to C, C to C# and so on, but only on the specified
"Chord" lines.
The user can then save this document back to the Google Docs for
printing if needed.
I've got the layout mostly. Some problems I'm coming across:
Doing a .find apparently finds all documents that have the given string in the name and
the contents. The fix would be to put the document IDs in a Hidden, but it doesn't seem
that a List returns the numbered item you clicked on, so how can I also get the ID
that's stored somewhere else?
I'd like the TextArea to be rich text for bolding and what-not; does
Google Apps have a text editor (it'd be awesome if I could just put
the Google Docs editor in a panel)? RichTextArea has been
deprecated, is there a replacement?
To do the transposing, I was planning on just putting every character
of the text area into an array, stepping through the array, when it
sees a "\n" followed by a "." to flip a var "on", then changing any
following characters, then if it sees another "\n" to turn the var
"off"; is there a better way to do this?
Or, is there way to add a script to a Google Document that would do
the transposing (I know you can do macros for spreadsheets, but there
doesn't really seem to be an equivalent for documents)? That way I can
just give out this macro and tell people to use on their existing document.
Since you asked, yes, separate questions would be appropriate, because the combination of questions is very specialized, while the individual problems might be more general, and of use to more people. But let me take a stab at it anyway...
[With the result of find()]... how can I also get the ID that's stored somewhere else?
DocsList.find() returns a list of File objects. Class File has a getId() method that returns the document ID you are used to seeing in Google Drive. To get the IDs of all your files:
var files = DocsList.getAllFiles();
for (var i in files) {
Logger.log(files[i].getId());
}
You should also look at DocsListDialog for creating a file picker that works on Google Drive.
RichTextArea has been deprecated, is there a replacement?
No, not in apps-script. You've just got TextArea. However, you may be able to embed a third-party rich text editor in your UI.
To do the transposing, ... is there a better way to do this?
Change the TextArea.value into an array of lines, then manipulate those, without needing to manage an on/off state. See How do I get information out of TextArea in Google App Script on the button click? and Javascript: Convert textarea into an array.
// aTextArea contains user's input. Probably a Johnny Cash song.
var inputText = e.parameter.aTextArea;
var inputLines = inputText.split('\n');
for (var i in inputLines) {
if (inputLines[i].charAt(0) == '.') {
// Transpose
}
}
// Put lines back together, if you wish
var outputText = inputLines.join('\n');
..is there way to add a script to a Google Document that would do the transposing...
Yes (capability extended to Docs and Forms since question was originally asked). No, Spreadsheets are the only document type that can be a container for scripts at this time.
Alternatively, you could employ a stand-alone script to operate directly on Docs! Perhaps with a script deployed as a Web App that lets users pick the target music to transpose from documents on their Google Drive, and that then writes a new copy of the document, transposed?