Google forms, and reordering pages
14/05/2015 Leave a comment
I had to design a somewhat large online suvery in Google forms, and was missing a way to move pages around. It seems this functionality is not part of the system. And, even though you can control page order by linking them, this wrecks havoc with the progress bar, that is only calculated by page number, not order. So, I wrote this Google App Script to fix it. It is rather crude, and I do not understand the project model, and what not, but you can probably google that part.
Also, I only needed to move pages forward. If you need to move pages backward, you will either have to write that code, or move all other pages forward. Use the “MovePages” function to control it, run it from the toolbar.
Here goes:
// Code to reorder pages, and get some information when working with many pages. // by Mads Bondo Dydensborg <mads@dydensborg.dk> // Page handling in forms are weird. A page consists of a pagebreak and a number of items. // Expect the first page, that are only items, and you can not change the first two items, which // are not even part of the items array. // Call this to move a number of pages. function MovePages() { // movePageForward( 28, 17 ); for ( var i = 30; i <= 37; ++i ) { // movePageForward( i, i - 9 ); } } // Helper/info function // Show alert box with all titles of all pages function listTitles() { var firstItem = FormApp.getActiveForm().getItems()[0]; var titles = "Page 1 : 'Your Title'\n"; var count = 1; var titles = titles + getAllPageItems().map( function(item) { ++count; return "Page " + count + " : " + item.getTitle() + ""; }).join("\n"); FormApp.getUi().alert("List of pages", titles, FormApp.getUi().ButtonSet.OK ); } ///////////////////////////////////////////////////////////////////////////// // These numbers are based on the users perspective. // The first page is called "1", and does not usually have a page_break to begin with! // This method moves a page forward, function movePageForward(pageNumber, toBeforePageNumber) { // Check bounds checkPageBounds(pageNumber); checkPageBounds(toBeforePageNumber); // Check ordering, as this moves forward if ( pageNumber <= toBeforePageNumber ) { throw new Error( "This method can only move pages forward" ); } Logger.log( "Moving page " + pageNumber + " to before page " + toBeforePageNumber ); // Forward approach: Identify item index number to move to // Collect all item instances // Ask the form to move them var beforeIndex = getPageItem(toBeforePageNumber).getIndex(); // FormApp.getUi().alert( "Moving to index : " + beforeIndex ); Logger.log( "Moving page " + pageNumber + " to index " + beforeIndex ); // Collect items var movingPageItems = getPageItems(pageNumber); // Move them all! var form = FormApp.getActiveForm(); for( i = 0; i < movingPageItems.length; ++i ) { Logger.log( "Moving item with global index : " + movingPageItems[i].getIndex() + " to index : " + (beforeIndex + i) ); form.moveItem( movingPageItems[i], beforeIndex + i); } } ///////////////////////////////////////////////////////////////////////////// // Get all items related to a given page. function getPageItems(thisPageNum) { Logger.log("Getting items for page number: " + thisPageNum ); checkPageBounds(thisPageNum); var thisPageItems = []; // Used for result var thisPageBreakIndex = getPageItem(thisPageNum).getIndex(); Logger.log( "This is index num : " + thisPageBreakIndex ); // Iterate from this, until we meet a PAGE index type // Get all items var form = FormApp.getActiveForm(); var allItems = form.getItems(); thisPageItems.push(allItems[thisPageBreakIndex]); Logger.log( "Added pagebreak item: " + allItems[thisPageBreakIndex].getIndex() ); for( var i = thisPageBreakIndex+1; ( i < allItems.length ) && ( allItems[i].getType() != FormApp.ItemType.PAGE_BREAK ); ++i ) { thisPageItems.push(allItems[i]); Logger.log( "Added non-pagebreak item: " + allItems[i].getIndex() ); } return thisPageItems; } ///////////////////////////////////////////////////////////////////////////// // Get all the pagebreak items function getAllPageItems() { // Get the form var form = FormApp.getActiveForm(); // All the pagebreak items var pageItems = form.getItems(FormApp.ItemType.PAGE_BREAK); return pageItems; } ///////////////////////////////////////////////////////////////////////////// // Get the max page number in user numbering function getMaxPageNumber() { var pageItems = getAllPageItems(); // Number of pageBreaks + 1, is user number (2 pb => 3 pages => 3 is max number) return pageItems.length + 1; } ///////////////////////////////////////////////////////////////////////////// // Check bounds, throw if outside // user page number function checkPageBounds(thisPageNum) { if ( thisPageNum < 1 ) { throw new Error( "Illegal page number, must be >=1 : " + thisPageNum ); } if ( thisPageNum == 1 ) { throw new Error( "Unable to handle first page, as it has no pagebreak" ); } if ( thisPageNum > getMaxPageNumber() ) { throw new Error( "Not enough pages in form to reference page number : " + thisPageNum ); } } ///////////////////////////////////////////////////////////////////////////// // Returns the item (page_break) at this page num // pagenum is based on 1, as the users sees it // We can't return for the number 1, as it has no pagebreak. function getPageItem(thisPageNum) { checkPageBounds(thisPageNum); // Get the page it. First page is out of bounds, page 2 is array index 0 // So, substract 2 return getAllPageItems()[thisPageNum - 2]; }