Modify form navigation via script - google-apps-script

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.

Related

What is the difference between pagebreakitem and sectionheaderitem in google app script (google form)?

I found there are two ways to add a new section in Google form using pagebreakitem and sectionheaderitem in google app script which gives the same result. What is the difference between them?
Class PageBreakItem (addPageBreakItem()) and Class SectionHeaderItem (addSectionHeaderItem()) appear similar but are very different and do NOT give the same result when used in a script.
Key Differences
There key difference between the two is that PageBreakItem enables navigation from page to page. In addition, PageBreakItem can also have many section headers; whereas a SectionHeaderItem is created within a page. Each can have questions attached.
Class PageBreakItem
This example is from the Google documentation
var pageTwo = form.addPageBreakItem().setTitle('Page Two');
var pageThree = form.addPageBreakItem().setTitle('Page Three');
// Make the first two pages navigate elsewhere upon completion.
pageTwo.setGoToPage(pageThree); // At end of page one (start of page two), jump to page three
pageThree.setGoToPage(FormApp.PageNavigationType.RESTART); // At end of page two, restart form
Though the method refers to a "page", the form describes the component as a "section" - no doubt the cause of some confusion.
Class SectionHeaderItem
This example is also from the Google documentation , plus an extra section header added by me.
var item = form.addSectionHeaderItem();
item.setTitle('Title of new section');
As you can see, a new page is not created, but a section is inserted into a page.

click through several links on webpage and extract information from each?

I have access a webpage with a list of several hyperlinks, each of which are unique. This is it:
webpage I have access to that lists names from top to bottom. Each name is unique and is a hyperlink. I would like to click on these hyperlinks one by one and extract info from the resulting webpage.
Say I click the first name, say Adam, it then brings me to the following webpage:
alt:this is a page of the user's profile and includes info such as name, email status and more
My goal is to create a program that clicks the name at the top, and then takes the email address and puts it in an excel spreadsheet on my local machine. And then goes back to the original page, clicks on the name directly below the name that was previously clicked on, and then takes this names resulting email and throws it in the spreadsheet.
for those looking at the pictures, i would like to click on 'Adam' and then put his email into a spreadsheet, then go back, and then click on 'Adrian' and then put his email into a spreadsheet, and so on and so forth down the list.
What do I need to do/learn to create a tool that will do this for me?
I know a bit of Java and a tiny bit of html. I've been trying to look for a solution but the most I can get is excel vba to click on the first name, but not much more. Even if I got the vba to click on all the names, it seems I would have to type in an instruction for the vba to find each unique name, and I dont see much point in doing that since its probably faster to just do this manually then.
As i'm not a programmer (but would like to be soon :)) I have had some trouble asking this question since I don't know any technical terms.
Any thoughts/advice on how to do this?
With javascript and a little php you could make this happen. Since it appears this is something running in the browser it would probably be your best bet.
Make your program click links js has the ability to activate links. You could
click on body load
the first link on the page,
then have a counter that counts each time you click a link.
`Find out how many links there are in the document:`
var x = document.links.length;`
`Get the URL of the first link (index 0) in the document:`
`var x = document.links[0].href;`
Click the link you want to click
$(function(){
$('#myLink').trigger('click');
})
now that your on the next page you need to grab the email address that is on this page. If you know the css just grab the string that is in the element. at this point you can use javascript to go back to the previous page.
<button onclick="goBack()">Go Back</button>
Now you are on the original page. Your counter is one number higher. Use the counter to click the next link and your program will repeat the process pushing the new email to your array.
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.push("Kiwi");
once the program runs out of links to click or hits the limit of your counter you will need to create a txt file with javascript. write your array to the file with PHP. You can do this with an ajax call.
make an AJAX call to your php file passing the array. php can then write to the file.
Here is an example of making a text file and writing to it with javascript
Following this logic you can fairly easy make an application that activates the links in order of a page, pushes the email address to an array as a string. Goes back to the previous page and continues the process till you have all the links. At this point your program will write all the data in the array to a file.

Get value of textbox in a table (GAS)

I know that this is something discussed sooo many times, but I can't get the value of a textbox that is placed in a table. I know how to get the value of a textbox (e.parameter.textBoxName), usually it's working without any problems.
The only difference now is that I have a gadget containing 5 tabs, each with some intro text and a table. Each table contains approximately 30 rows, each with two textboxes and a button to submit the value of two textboxes in the specific row to a spreadsheet. Everything is working fine, all the names (and IDs as well) are unique, but the problem is that when I submit textboxes, I get "undefined" (in my spreadsheet).
I guess the problem lays somewhere in the complexity of the script, so this:
function buttonClick(e) {
var app = UiApp.getActiveApplication();
var theValue = e.parameter.textBoxName;
...something...
}
..is simply not enough to define which textbox it is. However I'm getting the button ID without any problem with
var buttId = new String(e.parameter.source);
I'm trying to get my head around this for a couple of days without any results. I'm not that good with GAS and I'm completely out when it comes to objective programming. Do you have some ideas how to get this value? I can get the ID of the table if that helps, but what to use then?
Thank you very much in advance!
EDIT:
I tried .addCallbackElement(textbox) to the textbox - I'm getting an error. I tried .addCallbackElement(textbox) to the submit button together with .addCallbackElement(button) and I'm still getting "undefined".
the callbackElement must be added to the handler, not to the widget nor to the button.
The easiest (and safest) way to get it done correctly is to choose the highest level parent as callbackElement.
I your case it would probably be the tab panel or eventually another panel that contains your 5 tabs if you used one.
Note also that there might be really a lot of widgets in the same UI without causing any issue... I have an app with about 200 textBoxes that works flawlessly and I'm not aware of any limit nor if a limit even exists...

Get TextBox Value from Google Apps Script

I am new to the world of Google's Apps Script, and I am trying to create a basic UI for my end user to query data (stored in google spreadsheets) and display the data in a formatted / user friendly way.
Since I want to start off simple and add in components as I learn Apps Script I decided to create a basic form that will allow me to enter text in a text box, then assign that value to a label (what I thought would be a simple exercise in creating basic form components, and retrieving / assigning values).
Unfortunately the stumbling block I ran into is that there is no getText() or TextBox.getValue() function. I tried searching through online forums / google etc to find out the way around this, but nothing I try seems to work (previous searched led me totry and work this out in an event handler).
My question is this. If I have a textBox ('textBox1') and a button ('button1') and a label ('label1'). How to I get my web app to assign the value I enter in textBox1 to label1 when I click button1?
I realize this is probably the most basic of questions, and I know it has been asked before....but no matter how hard I dig through these old posts I can't seem to figure what should be an easy bit of code out.
Thanks in advance.
Suppose you have code that looks like this:
var textbox = app.createTextBox().setName("textboxName");
var buttonHandler = app.createServerHandler("updateLabelText").addCallbackElement(textbox);
var button = app.createButton("Click me").addClickHandler(buttonHandler);
var label = app.createLabel().setId("label");
Then in your function:
function updateLabelText(e) {
var app = UiApp.getActiveApplication();
app.getElementById("label").setText(e.parameter.textboxName);
return app;
}
So the things to note:
The button handler is given the name of a function that you define somewhere else in your code.
The button handler also must be given a "callback element". This is required if you want to read the value of that element in your function. You can add a panel as a callback element and anything that's on that panel will be added to the callback.
Values of callback elements are passed back through e.parameter. The property name is the name of the element. Example: e.parameter.textboxName.
The label needs an ID so that you can reference it from your other function.

How to get text from textbox in GAS?

I run my GAS as an Apps-script-gadget on my web-page and use the GUI-builder. I have two questions:
1.
I know how to set text in a textbox:
app.getElementById("TextBox1").setText("BigSister");
But how do i get text from a textbox?
I tried:
app.getElementById("TextBox1").getText();
...getValue();
...value;
etc.
Nothing works...
2.
Is it possible to print a message window from the code to the screen f.Ex. for debugging purposes?
Any advice would be appreciated.
Within your handler code, you can access the value of the text box as
var value = e.parameter.TextBox1 ;
Before doing this you must have run the setName() method on your text box.
var tetxbox1 = app.createTextBox().setName('TextBox1');
I suggest you run through some of the tutorials at https://developers.google.com/apps-script/articles where you can find answers to many of your questions.
You can retrieve the value of your ListBox when it is passed back through a handler. It's passed in the parameter class under the Id of the ListBox. The following is a fool-proof method of retrieving that value:
function changeHandler(e)
{
var source = e.parameter['source']; //source is your Id of the element
var value = e.parameter[source]; //value is the selected item as ['a' | 'a,b,c']
//More code here
}
I'm still waiting for a solution to retrieve that value without a handler.
EDIT here is a workin example for you to test
online test
and the script + GUI is here
=======================
Srik answer is absolutely right - as usual ;-) - but to make things a bit more clear to you since you are using GUI builder here is a small screen capture that shows the relevant parameters.
As for your second question, the simplest thing to do to get a momentary showing window to 'print' some data to screen is to use a texBox or a textAreal (or anything else that allows to show text...) and play with the setVisible(true) & setVisible(false) to show/hide the widget. In the GUI builder you can put it anywhere in your UI, even over other elements that you normally use since it will be invisible most of the time (the visibility parameter is available in the GUI builder environment as well). It will behave exactly as a 'popup' in other environments...