Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8179223
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 6, 20262026-06-06T23:57:15+00:00 2026-06-06T23:57:15+00:00

I’ve been reading Google Script and the book goes through several uses for Google

  • 0

I’ve been reading “Google Script” and the book goes through several uses for Google Apps script and walks you through building an app.

I’ve gone through a section for about creating forms dynamically from templates and I’m running into an issue I can’t get around. When accessing the published URL, it returns “Error Encountered: Unknown macro showForm” What puzzles me is I’ve tried using firebug in mozilla and debug in the script editor but no errors are identified. Anyone able to help point out where I should be looking or a direction to help troubleshoot to get this going
?

Here is the Code. Its broken into three pieces. Code.gs, GS Objecgts.js, and Documents API.js

CODE.GS

    var templateFolderId = '<<Enter Folder ID>>';

function doGet(e){
  var app = UiApp.createApplication().setTitle('Template Creator');

  //What this app is about
  var grid = app.createGrid(6, 2).setId('grid').setCellPadding(5);
  app.add(grid);

  grid.setWidget(0,0, app.createLabel("This App will allow you to create a form from"+
                                 " a template in Google Docs."));

  //create UI here
  // File Chooser  
  var fileChooser = app.createListBox().setName('fileChooser').setId('fileChooser')
                   .addChangeHandler(app.createServerChangeHandler('showForm')  
                   .addCallbackElement(grid)); 
  grid.setWidget(2, 0, fileChooser);



  //set the file Names in the listBox by calling on the DocsList service
  fileChooser.addItem('Choose Template');
  var files = DocsList.getFolderById(templateFolderId).getFiles();
  for (var i = 0; i < files.length; i++) {
    fileChooser.addItem(files[i].getName());
  }



  // Submit the form button  
  var button = app.createButton('Submit').setId('button')
              .addClickHandler(app.createServerClickHandler('createDoc')
                              .addCallbackElement(grid))
              .setVisible(false);

  grid.setWidget(4, 0, button);


  /*
  *  @returns body text from doc
  */
function getTemplateText(fileName){
  var files = DocsList.getFolderById(templateFolderId).getFiles();
for (var i = 0; i < files.length; i++) {
  if (fileName == files[i].getName()){  
     var text =  DOCS_LIST_API.GdocToFormat(files[i].getId(), 'txt');
    return text.getContentText();
      }  
    }       
}

  // function returns an array of unique form keys
function createKeys(templateFile){
  var templateTxt = getTemplateText(templateFile); 
  var templateVars = templateTxt.match(/\{\%[^\%]+\%\}/g);
  var templateKeys = [];
  var oneEach = "";
  for (var i in templateVars) {
    var keyObject = {};
    keyObject.text = templateVars[i].replace(/\{\%|\%\}/g, '');
    keyObject.id = camelString(templateVars[i]);
    if (oneEach.match(keyObject.text) == null){                 
      templateKeys.push(keyObject);  
    }
    oneEach += " " + keyObject.text;
  }   
  return templateKeys;
}

  function showForm(e){
  var app = UiApp.getActiveApplication();
  var flexTable = app.createFlexTable();
  var keys = createKeys(e.parameter.fileChooser);

    for (var i in keys) {
    var text = (keys[i].text);

    if(/^instruction/i.test(text)){       
  flexTable.setWidget(parseInt(i),0,app
                      .createLabel(text.substring(text.indexOf(':')+1)));      
    }else{
      var questionPanel = app.createHorizontalPanel();
      flexTable.setWidget(parseInt(i),0,questionPanel);    
      questionPanel.add(app.createLabel(text).setWidth('100px'));
      questionPanel.add(app.createTextBox().setName(keys[i].id));  
    }
  }

    flexTable.setWidget(keys.length+1,0,app.createLabel('________'));
  flexTable.setWidget(keys.length+2,0, app.createHorizontalPanel()
                                  .add(app.createLabel('Output file name: ').setWidth('100px'))
                                  .add(app.createTextBox()
                                        .setName('outputFile').setWidth('200px')
                                        .setValue('Copy of '+ e.parameter.fileChooser)));
  flexTable.setWidget(keys.length+3,0, app.createHorizontalPanel()
                                  .add(app.createLabel('Google Email: ').setWidth('100px'))
                                  .add(app.createTextBox()
                                        .setName('email').setWidth('200px')));

    app.getElementById('button').setVisible(true);        
  app.getElementById('grid').setWidget(3,0, flexTable);
  return app;  
}

  function createDoc(e){
  var app = UiApp.getActiveApplication();
  var keys = createKeys(e.parameter.fileChooser);
  var files = DocsList.getFolderById(templateFolderId).getFiles();

for (var i in files) {
  if (e.parameter.fileChooser == files[i].getName()){   
    var copyId = files[i].makeCopy(e.parameter.outputFile).getId();
    var doc = DocumentApp.openById(copyId)
    var copy = doc.getActiveSection();
    for (var i in keys) {
      var text = keys[i].text;    
      if(/^instruction/i.test(text)){ 
        if (copy.findText(keys[i].text) != null)
          copy.findText(keys[i].text).getElement().removeFromParent();
      }else{
        copy.replaceText('{%'+keys[i].text+'%}', e.parameter[keys[i].id]);
      }        
    }
    doc.saveAndClose();   
    doc.addEditor(e.parameter.email); 
     }
   }

app.getElementById('grid').setWidget(3,0, app.createAnchor('Open your Document', 
doc.getUrl())
                                  .setStyleAttribute('font-size', '18px'));
  app.getElementById('button').setVisible(false); 
  app.getElementById('fileChooser').setItemSelected(0, true);

  return app;  
}

  return app;  
}

GS Objects.gs

/*
   ObjService

   Copyright (c) 2011 James Ferreira

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

/**
 * ObjService
 * @author James Ferriera
 * @documentation http://goo.gl/JdEHW
 *
 * Changes an object like e.parameter into a 2D array useful in 
 * writting to a spreadsheet with using the .setValues method
 *
 * @param   {Array}   headers    [header, header, ...] 
 * @param   {Array}   objValues  [{key:value, ...}, ...]
 * @returns {Array}              [[value, value, ...], ...]
 */
function objectToArray(headers, objValues){
  var values = [];  
  var headers = camelArray(headers);  
  for (var j=0; j < objValues.length; j++){
var rowValues = [];
for (var i=0; i < headers.length; i++){
  rowValues.push(objValues[j][headers[i]]);
}  
values.push(rowValues);
  } 
  return values;
}


/**
 * Changes a range array often returned from .getValues() into an 
 * array of objects with key value pairs.
 * The first element in the array is used as the keys (headers)
 *
 * @param   {Array}   range   [[key, key, ...],[value, value, ...]] 
 * @returns {Array}           [{key:value, ...}, ...] 
 */
function rangeToObjects(range){
  var headers = range[0];
   var values = range;
  var rowObjects = [];
  for (var i = 1; i < values.length; ++i) {
    var row = new Object();
    row.rowNum = i;
    for (var j in headers){
      row[camelString(headers[j])] = values[i][j];
    }
   rowObjects.push(row); 
  }   
  return rowObjects;
}

/**
     * Changes a range array into an array of objects with key value pairs
 *
 * @params  {array}    headers  [key, key, ...]
 * @params  {array}    values    [[value, value, ...], ...]
 * @returns {array}    [{key:value, ...}, ...]  
 */
function splitRangesToObjects(headers, values){
  var rowObjects = [];
  for (var i = 1; i < values.length; ++i) {
    var row = new Object();
    row.rowNum = i;
    for (var j in headers){
      row[camelString(headers[j])] = values[i][j];
    }
   rowObjects.push(row); 
  }   
  return rowObjects;
}



/**
 * Removes special characters from strings in an array
     * Commonly know as a camelCase, 
 * Examples:
 *   "First Name" -> "firstName"
 *   "Market Cap (millions) -> "marketCapMillions
 *   "1 number at the beginning is ignored" -> "numberAtTheBeginningIsIgnored"
 * @params  {array} headers   [string, string, ...]
 * @returns {array}           camelCase 
 */
function camelArray(headers) {
  var keys = [];
  for (var i = 0; i < headers.length; ++i) {
    var key = camelString(headers[i]);
    if (key.length > 0) {
      keys.push(key);
    }
  }
  return keys;
}    


/**
 * Removes special characters from a string
 * Commonly know as a camelCase, 
 * Examples:
 *   "First Name" -> "firstName"
     *   "Market Cap (millions) -> "marketCapMillions
 *   "1 number at the beginning is ignored" -> "numberAtTheBeginningIsIgnored"
 * @params  {string}  header   string
 * @returns {string}           camelCase 
 */
function camelString(header) {
  var key = "";
  var upperCase = false;
  for (var i = 0; i < header.length; ++i) {
    var letter = header[i];
    if (letter == " " && key.length > 0) {
      upperCase = true;
  continue;
   }
if (!isAlnum_(letter)) {
  continue;
    }
    if (key.length == 0 && isDigit_(letter)) {
      continue; // first character must be a letter
    }
    if (upperCase) {
      upperCase = false;
      key += letter.toUpperCase();
    } else {
      key += letter.toLowerCase();
    }
  }
  return key;
}

function isCellEmpty_(cellData) {
  return typeof(cellData) == "string" && cellData == "";
}
function isAlnum_(char) {
  return char >= 'A' && char <= 'Z' ||
    char >= 'a' && char <= 'z' ||
    isDigit_(char);
}
function isDigit_(char) {
  return char >= '0' && char <= '9';
}

Documents API.gs

    /*
*  Private for OAuth
*  @ returns OAuth headers 
*/
var DOCS_LIST_API = {};

DOCS_LIST_API.googleOAuth = function() {
  var oAuthConfig = UrlFetchApp.addOAuthService('google');
  oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/"+
         "OAuthGetRequestToken?scope=https://docs.google.com/feeds/");
  oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
  oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
  oAuthConfig.setConsumerKey('anonymous');
  oAuthConfig.setConsumerSecret('anonymous');
  return {oAuthServiceName:'google', oAuthUseToken:"always"};
}

/*
*  @ args     docID  String   the id for a Google Document
*  @ args     format String   can be, "txt", "odt", "pdf", "html", "rtf", "doc", "png", 
"zip"
*  @ returns  blob 
*
*/
DOCS_LIST_API.GdocToFormat = function(docID, format){
  var fetchArgs = DOCS_LIST_API.googleOAuth();   
  fetchArgs.headers = { "GData-Version": "3.0" };
  fetchArgs.method = 'get';
  var url = 'https://docs.google.com/feeds/download/documents/export/Export?id='+
                       docID+'&exportFormat='+format+'&format='+format; 
  return UrlFetchApp.fetch(url, fetchArgs); 
}

  // Run it twice  
function doOAuth(){
  try{
    DOCS_LIST_API.GdocToFormat();
  }catch(e){
  }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-06T23:57:17+00:00Added an answer on June 6, 2026 at 11:57 pm

    it seems there is an error in code.gs

    the “logical” version should be like this : (copy & paste in your script editor)

       var templateFolderId = '<<Enter Folder ID>>';
    
    function doGet(e){
      var app = UiApp.createApplication().setTitle('Template Creator');
    
      //What this app is about
      var grid = app.createGrid(6, 2).setId('grid').setCellPadding(5);
      app.add(grid);
    
      grid.setWidget(0,0, app.createLabel("This App will allow you to create a form from"+
                                     " a template in Google Docs."));
    
      //create UI here
      // File Chooser  
      var fileChooser = app.createListBox().setName('fileChooser').setId('fileChooser')
                       .addChangeHandler(app.createServerChangeHandler('showForm')  
                       .addCallbackElement(grid)); 
      grid.setWidget(2, 0, fileChooser);
    
    
    
      //set the file Names in the listBox by calling on the DocsList service
      fileChooser.addItem('Choose Template');
      var files = DocsList.getFolderById(templateFolderId).getFiles();
      for (var i = 0; i < files.length; i++) {
        fileChooser.addItem(files[i].getName());
      }
    
    
    
      // Submit the form button  
      var button = app.createButton('Submit').setId('button')
                  .addClickHandler(app.createServerClickHandler('createDoc')
                                  .addCallbackElement(grid))
                  .setVisible(false);
    
      grid.setWidget(4, 0, button);
    
    return app
      }
      /*
      *  @returns body text from doc
      */
    function getTemplateText(fileName){
      var files = DocsList.getFolderById(templateFolderId).getFiles();
    for (var i = 0; i < files.length; i++) {
      if (fileName == files[i].getName()){  
         var text =  DOCS_LIST_API.GdocToFormat(files[i].getId(), 'txt');
        return text.getContentText();
          }  
        }       
    }
    
      // function returns an array of unique form keys
    function createKeys(templateFile){
      var templateTxt = getTemplateText(templateFile); 
      var templateVars = templateTxt.match(/\{\%[^\%]+\%\}/g);
      var templateKeys = [];
      var oneEach = "";
      for (var i in templateVars) {
        var keyObject = {};
        keyObject.text = templateVars[i].replace(/\{\%|\%\}/g, '');
        keyObject.id = camelString(templateVars[i]);
        if (oneEach.match(keyObject.text) == null){                 
          templateKeys.push(keyObject);  
        }
        oneEach += " " + keyObject.text;
      }   
      return templateKeys;
    }
    
      function showForm(e){
      var app = UiApp.getActiveApplication();
      var flexTable = app.createFlexTable();
      var keys = createKeys(e.parameter.fileChooser);
    
        for (var i in keys) {
        var text = (keys[i].text);
    
        if(/^instruction/i.test(text)){       
      flexTable.setWidget(parseInt(i),0,app
                          .createLabel(text.substring(text.indexOf(':')+1)));      
        }else{
          var questionPanel = app.createHorizontalPanel();
          flexTable.setWidget(parseInt(i),0,questionPanel);    
          questionPanel.add(app.createLabel(text).setWidth('100px'));
          questionPanel.add(app.createTextBox().setName(keys[i].id));  
        }
      }
    
        flexTable.setWidget(keys.length+1,0,app.createLabel('________'));
      flexTable.setWidget(keys.length+2,0, app.createHorizontalPanel()
                                      .add(app.createLabel('Output file name: ').setWidth('100px'))
                                      .add(app.createTextBox()
                                            .setName('outputFile').setWidth('200px')
                                            .setValue('Copy of '+ e.parameter.fileChooser)));
      flexTable.setWidget(keys.length+3,0, app.createHorizontalPanel()
                                      .add(app.createLabel('Google Email: ').setWidth('100px'))
                                      .add(app.createTextBox()
                                            .setName('email').setWidth('200px')));
    
        app.getElementById('button').setVisible(true);        
      app.getElementById('grid').setWidget(3,0, flexTable);
      return app;  
    }
    
      function createDoc(e){
      var app = UiApp.getActiveApplication();
      var keys = createKeys(e.parameter.fileChooser);
      var files = DocsList.getFolderById(templateFolderId).getFiles();
    
    for (var i in files) {
      if (e.parameter.fileChooser == files[i].getName()){   
        var copyId = files[i].makeCopy(e.parameter.outputFile).getId();
        var doc = DocumentApp.openById(copyId)
        var copy = doc.getActiveSection();
        for (var i in keys) {
          var text = keys[i].text;    
          if(/^instruction/i.test(text)){ 
            if (copy.findText(keys[i].text) != null)
              copy.findText(keys[i].text).getElement().removeFromParent();
          }else{
            copy.replaceText('{%'+keys[i].text+'%}', e.parameter[keys[i].id]);
          }        
        }
        doc.saveAndClose();   
        doc.addEditor(e.parameter.email); 
         }
       }
    
    app.getElementById('grid').setWidget(3,0, app.createAnchor('Open your Document', 
    doc.getUrl())
                                      .setStyleAttribute('font-size', '18px'));
      app.getElementById('button').setVisible(false); 
      app.getElementById('fileChooser').setItemSelected(0, true);
    
      return app;  
    }
    

    EDIT : after saving, use this feature to test :enter image description here

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am reading a book about Javascript and jQuery and using one of the
We're building an app, our first using Rails 3, and we're having to build
I have a jquery bug and I've been looking for hours now, I can't
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I am writing an app with both english and french support. The app requests
I am using Paperclip to handle profile photo uploads in my app. They upload
I am trying to loop through a bunch of documents I have to put
I'm making a simple page using Google Maps API 3. My first. One marker

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.