Tuesday, May 6, 2014

UI Services in Google Apps Script

In this post I review the basics of creating user interfaces in Google Apps Script.  Addtionally, since most of this code is semi complex and may be the first time that many of you have seen these function calls I will be explaining all of the code on a line by line basis starting with step 6.

Due to the complexity of this item and the lack of documentation I've created a video titled Google Apps Script Tutorial How to create UI using Apps Script 

1)  Create a new script and paste in the following code. (tip: If you are unsure on how to create a script see steps 3-5 on This Blog Post on How to Send a Custom Email from a Google Script)


function BuildUI() {
  //create the application itself
  var app = UiApp.createApplication();
  app.setTitle("My Frist UI Interface");

  //create panels and add them to the UI
  var panel = app.createVerticalPanel();

  //create a text box
  var text1 = app.createTextBox();
  text1.setName('TextBox1');

  //create a submit button
  var button = app.createButton('Please Click Me');

  //add the text box and the button to the panel
  panel.add(text1);
  panel.add(button);

  var handler = app.createServerHandler("submitButton");
  button.addClickHandler(handler);
  handler.addCallbackElement(panel);
 
  //add the panel to the application
  app.add(panel);

  var doc = SpreadsheetApp.getActive();
  doc.show(app);
}

function submitButton(e){
  var app = UiApp.getActiveApplication();
  var textValue = e.parameter.TextBox1;
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.appendRow([textValue]);
  return app.close();
}

2.  SAVE the work and then select the Build UI Function:


3.  Run the function..


4.  Go BACK to your spreadsheet and then do the following..

5.  It works!!


6.  Line by line breakdown of the UI code...

var app = UiApp.createApplication();
This used to Create a new UiInstance, which you can use to build a UI.  A "UiInstance" referrers to the entire user interface itself. 

app.setTitle("My Frist UI Interface");
This sets the title of the application itself.  If this application will be run as a service, this will be used as the title of the page. If this application will be run as a dialog (for example inside a spreadsheet) it will be the title of the dialog's window.

var panel = app.createVerticalPanel();
This creates a panel (which will later be added to the application) that lays all of its widgets out in a single vertical column.  There are a total of 16 different types of panels that all allow the widgets in your application to flow in different directions.  You can read about those panels here...

var text1 = app.createTextBox();
text1.setName('TextBox1');
This creates a text box which is pretty self explanatory.  The important line of code here is the ".setName('TextBox1');"  Without setting the name you would never be able to later access the text box.  In the created function "submitButton(e)" you can reference the value that the user has typed in to the text box by calling "e.parameter.TextBox1"  Note the same value name from ".setName('TextBox1');" and "e.parameter.TextBox1"

var button = app.createButton('Please Click Me');
This creates a submit button for the form which again is very self explanatory.  In this line of code the "Please Click Me" just references the wording on the actual button but does NOT represent a variable name for the button.  IF you needed to reference a certain button later you could use the following when declaring...
var button = app.createButton('Please Click Me').setId("submit");
and then in function "submitButton(e)" you could reference the above item by using the id like this..
var subButton1 = app.getElementById(“submit”);

subButton1.setStyleAttributes({background: "black", color: "green"});
Note the same id in the following 2 items...
".setId("submit");" and ".getElementById(“submit”);"



panel.add(text1);
panel.add(button);
These 2 lines add the actual items to the vertical panel.  Without adding the items in they would not be visible to the end user and would continue to simply be variables that you could manipulate.

var handler = app.createServerHandler("submitButton");
This creates a server-side click handler object called handler as part of the UiInstance application called app. A click handler performs an action in response to a mouse click. Server-side means that the actions are performed by a server, in this case Google's Apps Script server. The argument ('submitButton' ) means the handler action is to run function submitButton(e).  Note that in the past Google scripts had a separate handler specific to buttons that was referred to as "createServerClickHandler()" but that function has since been deprecated and you should not use "createServerHandler()" instead.

It should be noted that you can add multiple click handlers to a button. The calls to the click handlers are asynchronous. That means that after the browser has requested that the server run a click handler function, it doesn't wait for a response, and continues immediately to the next line of code. This is important, because browser JavaScript is single-threaded, and if the code waited for the server to respond, nothing else could happen until the response came back, including users clicking on buttons in the app or doing anything else. This also means that server function calls may not execute in the order you expect.

button.addClickHandler(handler);
This associates the click handler to the already-defined button object called button.  Without this association the clicking of the button would not like to the defined server handler variable which was declared as "handler."

handler.addCallbackElement(panel);
This line is adds all widgets that have previously been added to the panel (in this case text1 and button) to this ServerHandler as a "callback element."  When a ServerHandler is called, any widgets added here, as well as any current child widgets of those widgets, are considered as callback elements. The value of each of these widgets is added to the information sent to the script processing the event.

app.add(panel);
This adds the panel AND all items that have previously been added to the panel to the actual application itself.  Without adding the panel to the application the panel and its associated items would not be visible to the end user and would continue to simply be variables that you could manipulate.

var doc = SpreadsheetApp.getActive();
doc.show(app);
This gets the actual spreadsheet that is open and then shows the application to the end user.

function submitButton(e){
This is how you create a JavaScript function, which will be a custom Spreadsheet function named submitButton. Notice that when you are creating a function which is intended to be called as a custom Spreadsheet formula, you tell the function to accept some input value (in this case "e").  Appscript generates this object and passes along to submitButton function.  Using object e we can get the value of user-submitted variables by later referencing the variables by referencing "e.parameter..."

var app = UiApp.getActiveApplication();

This gets the active UiInstance (application).

var textValue = e.parameter.TextBox1;
This creates a variable "textValue" and stores the user submitted variable from the text box within the variable "textValue."

var sheet = SpreadsheetApp.getActiveSheet();
This gets the active SHEET from within the active spreadsheet that is open.

sheet.appendRow([textValue]);
This writes the value of the variable "textValue" to the next line of the open sheet as referenced above.

return app.close();
This closes the application itself and returns you to normal view of the active spreadsheet.

7.  Finished!
Nicely done!!  Be sure to check out the rest of the blog for tips on writing custom code for Google Docs and Google Apps.






8 comments:

  1. Thank u so very much for posting such a wonderful Information.
    t20 cricket games download | IPL 2016 App

    ReplyDelete
    Replies
    1. You're very welcome. Please let me know if you have any other questions or comments.

      Delete
  2. TypeError: Cannot read property "parameter" from undefined. (line 33, file "Code")
    Dismiss

    I keep on getting this error when I try to run the code.
    Thanks in advance.

    ReplyDelete
  3. Dan-

    Would you have an example of how to create the UI with two checkboxes instead of text boxes and how to have the code execute a different script based on which option was checked? I would like the final product to look like this:
    1. Press a button that executes a script to open the UI.
    2. UI opens with two checkbox options
    3. Check box 1 and a script executes function A
    4. Check box 2 and a script executes function B.

    Could you help me at all with this?

    ReplyDelete
  4. Hi
    it is probably a bit late, but when I submit data, all columns filled with the value "undefined"

    ReplyDelete
  5. Bro,
    Thanks so much for this wonderful information, you put it in a way that is so easy to understand, so bad UI service is already deprecated, well it doesn't matter, I can still use it haha. Greetings from Perú.

    ReplyDelete
  6. Your blog provided us with valuable information to work with. Each & every tips of your post are awesome. Thanks a lot for sharing. Keep blogging, showbox android app

    ReplyDelete
  7. It seems as if the createapplication is depreciated. Would you be able to update it to html service instead? thank you!

    ReplyDelete

Pages