Google I/O 2011: Developing Apps, Add Ins and More with Apps Script

Uploaded by GoogleDevelopers on 11.05.2011


COREY GOLDFEDER: Hi, welcome to Apps, Add-ins and more with
Apps Script.
If you can say that three times fast
I'll give you a cookie.
I'm Corey.
I'll be presenting this.
I'm an engineer in Google Apps Script.
I'll be presenting along with Drew who's also an Apps Script
engineer and James Ferreira who's one of our users.
Before we begin, here are some important links.
If you like to tweet about the conference, or even Buzz,
io2011 for the conference, googleapps for the track.
And if you'd like to give us feedback, there's a short link
up there, please go ahead and use it.
OK, so let's begin.
Can I get a show of hands, has anyone in the audience used
Google Apps Script?
Not bad, not bad.
Those of you at home on YouTube, you can also raise
your hands if you like.
We won't be watching, but it makes you feel part of the IO
So let's define some terms. An add-in, an
app, and app script.
Well, an add-in is an extension to Google Apps that
provides integrated glue-logic.
Think of it as a plug-in adding functionality to an
existing Google App.
An app on the other hand, is a full scale application with
its own user interface at its own URL that interacts with
the rest of the Google Apps suite.
An apps script is Google's cloud scripting language,
which lets you build both add-ins and apps that live
entirely in the cloud and participate in
the Google Apps suite.

This is Bob.
Those of you who came to our IO session last year may
remember Bob as the guy who automated everything at Acme
Corp. Well, Bob no longer works for Acme Corp. Don't
worry, he wasn't fired.
In fact, he did so well that he retired.
Then the housing bubble came and all of Bob's friends were
losing their homes.
So Bob sprang into action as a second career helping his
friends refinance their mortgages.
Sure, why not?
The problem is that this is pretty labor intensive and Bob
is a guy who doesn't like to do a lot of labor.
So today, we're going to help Bob build a mortgage
It's going to automate a lot of his workflow process.
This is going to involve a lot of pieces, from debugging to
GUIs, to how to deploy an app, using Gmail, writing
documents, things like blobs and conversions that will
become clearer as we go through then.
So let's step through it one piece at a time.
Here's the app we want build today.
This is Bob's calculator.
On the top left is a panel showing emails from Bob's
Gmail accounts that have something to do with
refinancing a mortgage.
Below that is a panel showing the most recent--
I'm sorry, the currently selected email.
And on the top right is a mortgage calculator where Bob
can fill in the amount, the rate, and the years.
Or even have it auto-populated from an email.
On the bottom is a button that says,
generate reply with quote.
When Bob clicks that button, the person who got the email
gets back from him a quote for a new mortgage.
Looks pretty cool.
How do we build it?
Well the first thing we need is to talk about the basics of
a Mortgage calculation app and how to debug it.
This is a calculate monthly payment function.
You take in the principal, the amount of money, the rate, and
the number of years of the term of the loan and it gives
you back the expected monthly payment.
And I'm not going to lie, I took this
directly from Wikipedia.
Now if you test this according to Wikipedia with $100,000 at
a 4.0 rate and 30-year mortgage, you should get a
$477 monthly payment.
So let's see what happens.

We run the function.
Take a look at the logs.
And that is not the value that Wikipedia
told us would be there.
Something's wrong.
Well luckily for us, this year Google Apps
Script launched a debugger.
We can set a break point and start debugging and see what's
going on at every line of code.
Like any other debugger, we have step into, step
over, and step out.
And here we're using step into to step through the code line
by line, see the values changing in the bottom panel
as the code executes.
That looks good.
That looks good.
Still looking good.

And the denominator is clearly wrong on the bottom.
OK, well we can fix that.
Let's get out of debugging mode.
Ah, there it is.
As with everything else, a misplaced parenthesis is the
problem with our program.
OK, so we can fix it.

Run it again.

And there it is, the value that God and Wikipedia
intended, $477.
Great, we have a calculate monthly payment function.
But of course, we don't want Bob to have to come into the
script and edit the code every time he wants to calculate a
new monthly payment.
What we need is a GUI.
Now, here's another question for you guys, how many of you
have tried to build a UI using Google Apps
Script, using UiApp?
OK, a few people.
It's pretty difficult because you have to construct your
entire UI in code, which is sometimes
complicated and painful.
Which is why today, we're happy to announce the Apps
Script GUI Builder.
This is a drag and drop GUI Builder.
I'm sure you're familiar with the type.
You can create a UI in it, use it from Apps Script, and this
is live today.
You can go turn it on right now, it's in the file menu and
we'll show it to you in a minute.


COREY GOLDFEDER: So what can the GUI Builder do for you?
Well of course, it can let you build a user interface easily.
It could also let you decorate it later, and
this is really important.
You can build a functional interface, make it work, and
then worry about styling it after the fact.
You can script it as usual, and we're going to go into
that in detail in a moment.
And finally, as with everything in Google Apps
Script, you can deploy it fast. We barely have the word
deploy in our dictionary.
One-click deployment is what we're all about.
The GUI Builder helps you reduce development time
because you can iterate quickly on the UI as you're
building the script.
It also reduces code size because you can separate out
the UI and the styling from Business Logic and in fact,
you don't even need to have explicit code for your UI, it
just works.
And finally, it actually helps you with the correctness of
your code because the Builder helps you avoid
common UiApp pitfalls.
You can't put widgets in panels that don't support
them, you can't set values that aren't allowed.
The Builder prevents common UI of errors.
And if it works in the Builder, it
will work in UiApp.

Building a GUI should be fast and intuitive because you guys
are focused on application design, not on website design.
You don't want to deal with CSS quirks.
You don't want to deal with setting values browser by
browser, so we do that for you.
The GUIs real WYSIWYG down to browser
quirks like I just said.
On the left is a UI from the Builder showing in Firefox.
On the right is the same UI showing in Chrome.
Notice that there are slight differences.
These are done by the browser, so they look native to each
browser in each OS.
However, the functionality will be the same.
Most importantly, what you see in the Builder is what you
will see in that browser.
So if you open this same UI in Chrome, you will see the app
as it will show in running Chrome.
If you open in Firefox, you will see it as it shows if run
in Firefox.
I have not mentioned Internet Explorer because we support
all modern standard compliant browsers.
We do have rudimentary Internet Explorer support and
more should be coming, but it works right now very well in
Firefox and Chrome.
OK, so how do you build a UI?
You can use Draw or Drag to create widgets.
Dragging's when you just click on the pallet, drag a
widget right off.
Drawing is when you select an item on the pallet, carefully
place and draw like you were drawing in a paint program.
And these are the same widgets as in UiApp, so you should be
immediately familiar with them.
Not all the UiApp widgets are available.
You can expect the rest of them to come shortly and more
widgets to be added both to the Builder and UiApp in the
days to come.
You can lay out or group widgets using panels.
Nested panels can create complex effects and flow
panels, like Flow Panel or Vertical Panel, et cetera, can
let you create resolution independence using both flow
panels and percentage sizing so that your UIs show up
correctly on everything from mobile
devices to large screens.
You can even try different resolutions without resizing
your browser.
Because as we'll see in a moment, there's an application
window inside the Builder that can be independently re-sized.
And a lot more of this is coming too in future versions
of the near future, you can expect things like snap to
grid, dragging guidelines as you drag near something, all
that is on its way.
Each widget in the Builder exposes only the properties
that it supports.
So you can focus on exactly what you need.
And also, so that you can't set a value that
won't make any sense.
Everything is checked as you type, every value is validated
and you get immediate feedback.
You see the effect in the Builder as you type it and if
it can't be applied to that property, to that widget, it
won't be saved.
So if it works in the Builder, it will work in your app.
And finally, you can add behaviors, event handlers,
directly from the Builder and we'll see an example
of that right now.
So here's the Builder.
We load it from the file menu.
That menu item is live today.
And here it is, a floating application window.
On the right side is a properties bar, editable
On the left side is a widget palette with
more widgets to come.
Let's start building Bob's mortgage calculator.
Just the simple building blocks.
A flow panel to hold the emails as they come in.
An absolute panel for the calculator, top right area.
And a label at the bottom to hold the text of the currently
selected email.
Once we've dropped items on the application, we can edit
them either by dragging them or resizing them as so.

Or, by using the Properties bar to edit the currently
selected widget or widgets.
Changing the text, everything is changed live.
Changing the color.
If you edit it here, you'll see the result immediately.
So how are we going to interact with this UI in code?
If we want to get a reference to an element in the UI, we
need to use its ID property.
So let's set some IDs.
The top left panel, well that's the emails panel.

The top right panel, that's the calculator.
Great, so now we have references that
we can use in code.
Let's actually start building the calculator.
We'll need a calculate button.
Rip it off, place it where we like it.
We'll give it an ID, some text.

And of course, some behavior.
The GUI Builder is aware of your script.
So all the function in your script are available to set as
event time that is right there in the Builder.
When you click on Calculate, the calculate function will
now be called.
Oh, and we need a button at the bottom for
that reply with quote.
Same thing.
Replace it, re-size it, give it an ID, give it some text,
wait for the video to catch up with me.

Generate reply with quote, and so on.
OK, so let's go back to the calculator on the top and
continue building that.
We'll need some labels for the fields.
And notice as these are drawn that the component tree in the
top right is showing you the hierarchy, the panel based
hierarchy of your UI.
You can actually select things and edit them
directly from that tree.
We need a label for the results.
We'll put a dollar sign in there so that it looks nice
when there's nothing showing yet.

And some text boxes to hold the actual fields.

Now, as I said before, the way you get it referenced to an
element in the UI is through its ID.
So we're going to set the ID as Text Amount, Text Rate, and
Text Years.
And of course, we'll set the labels to match.

This next part is really interesting.
Each email that came in showed its from and its subject on
its own row.
What we're going to do now is build a single email row,
which we can use as a template to stamp out multiple copies
of the same piece of the UI.
So here we put a flow panel, we call it row, and we're
going to copy that over and over in the app.
We set some sizing on it, 100% width, get rid of its border.

And now let's drop some labels on it.
A label for From and a label for Subject.
And you can see that the interaction with these widgets
is pretty natural.
You size them or you edit them as you'd expect in any other

A label for subject.
Notice the blue boxes.
The blue box shows where the widget will go when
you let go of it.
So if you're dragging it or resizing it, that's where it
will end up.
When you're doing this on an absolute panel, it's not the
most obvious thing because it's directly behind what
you're dragging.
When you're working on a flow panel, it's actually really
helpful to see the entire UI re-flowing as you're dragging.
We have From, we have Subject.

100% width.
And now let's just add some styling.
From should be bold.
And let's drag all the widgets that we want
to be the same color.
Select them all with Control.
Set a nice color.
And this is the decorate it later part that I mentioned.
Once we built the UI, we can worry about the way it looks.
Nice yellow backgrounds.

A different color for the label at the bottom.

And there it is, Bob's calculator app, exactly as we
showed it before.

So, we can build a UI.
What can we do with it in script?
The first thing we need to do with a Builder component, and
here I'm going to define a term.
We call the UI you just built a component.
The first thing you can do is load it in with a new
function, UiApp loadComponent.
Everything you do in the Builder has 100% compatibility
with UiApp code and components act exactly as if you had
typed in the code to create them.
Here's how you show the app, show the UI you just created
as its own web page.
This is standard if you ever use UiApp or if you look at
our existing UiApp code.
You write a doGet function.
You create an application, var app equals
You add to it the loaded component.
And this is the only new part, app.loadComponent.
And you return the app.
This will show that UI that you just created
as its own web page.
Well, we can do more than that.
Builder components can be edited in apparently.
Builder components can be edited in something, in code.
Here we're loading a component in from the GUI.
We're grabbing a single widget from it.
So we're using the IDs that I mentioned, app.getElementbyID
and grabbing out button one.
And then we're changing the text.
So were editing the UI from the Builder.
It's not static.
You can use it just as if you had created the code yourself.
You can also add new UiApp widgets inside
of a Builder component.
So here we're loading a component.
Grabbing out panel one from it, again same way as before,
using its ID to get a reference to it.
And then adding a new button inside.
And this button is completely a UiApp.
This is not from the Builder.
So UiApp and the Builder can totally interact.
You can even pull out parts of a component.
Here we're loading a component, grabbing a panel.
Again, an inner panel, not the entire component.
And only adding part of the component to the app.
The only part that will show now in the app
is that inner panel.
And I'll show an example of this in a
moment actually working.
Finally, you can add the same component to the
app multiple times.
This how we achieve using that row as a template over and
over again.
Now of course, there's a problem because every element
in a UiApp must have a unique ID.
And these IDs are coming from the Builder.
So you can use the optional prefix property and set a
prefix for each version that you load in.
No longer will there be a calculate button.
There'll be a one calculate and a two calculate.
And this is how we can distinguish them in code.

So now we've built a UI for Bob's mortgage calculator.
How can we get this application out to the world?
How can we deploy it?
So there are a couple different ways that code from
Google Apps Script can be deployed.
The first is as an add-in, either to a spreadsheet or
more recently to a Google site with more integrations coming.
In a spreadsheet you can use is at the custom function, or
as a dialogue with its own user interface that might be
raised from an integrated user menu.
And the key here is when you're publishing a Google
Apps Script as an add-in, it runs as
the user at the keyboard.
What does that mean?
It means that when you load a spreadsheet that has an
add-in, you, the guy running the spreadsheet, are the user
who's being referenced by the script.
So if it's referencing contacts or calendar, it's
referencing your contacts and your calendar.
In contrast, the other way to publish a Google Apps Script
piece of code is as an app on its own with its own URL and
its own user interface not inside of an existing app.
In that case, it executes as the publisher.
And this is ideal for things that want to
be run as role accounts.
So if, for example, you build an HR based system, you can
always run it as HR at your domain.
Let's see what it looks like to do a custom function.
Well we created a calculate monthly payment function and
we debugged it, so it should work.
And all we need to do to make it work is go to a
spreadsheet, type equals calculate monthly payments and
a couple of parameters and bang, it works.
No deployments.
If it's a visible function in your script, visible just
means it doesn't end with an underscore, so that you can
hide implementation details.
But if it's a visible function in your script, then you can
just use it in a spreadsheet immediately.
You can return a single value to overwrite that cell, or an
array or a double array to overwrite a range.
A slightly more complex, but still pretty easy integration,
is to use a custom dialogue raised from a custom menu.
The special onOpen function lets you add menus to a
spreadsheet as it's opened.
Pretty easy code.
Spreadsheet app, get active spreadsheet.
Add a menu, mortgage, with a sub-menu of calculator that
calls a function [? showcalc. ?]
Let's see how that works.
Someone clicks on mortgage calculator.
Hey, there is the same little calculator app that was in the
top right corner of Bob's application.
And just like I promised, this is an example of showing just
part of something for the Builder inside an app.
So all we did was we added the component from the Builder to
a script, to an app, only showing the inner panel.
So we loaded it, but only added an inner panel and the
calculator works exactly as we like without the email
integration that we showed before.

How do you distribute something like this?
Well, there are two ways.
You can publish it to the public script gallery.
And this public script gallery is really public.
It's accessible from any spreadsheet.
And for safety reasons, you can only publish to the script
gallery from a non-domain account,
from a account.
This is important because we don't want you to accidentally
leak your personal company enterprise assets into the
public script gallery.
In contrast, if you'd like to publish something to your
domain, you can use the template gallery.
That's local to your domain and the entire spreadsheet
gets saved with the script.
So it's pretty nice if you have a spreadsheet that
assumes a certain layout--
I'm sorry, if you have a script that assumes a certain
layout of your spreadsheet, you can publish it to your
domain template gallery and the entire spreadsheet gets
put up there.
And this helps you save your corporate assets from being
leaked out.

Here's what it looks like.
You click, sorry, Share, Publish script, and then you
get this publisher script dialogue.
You fill it out with the information you like and bang.
There it is in the public script gallery.
The flow for the template gallery is fairly similar.
OK, how about publishing a fully capable web app with its
own user interface?
Well the word publish in this context means something
slightly different.
Rather than showing the code, publishing the code so that
someone else could run the app, we mean actually
publishing the app as an executable that someone else
could use at a URL directly.
Here's the app.
We'd like to just make this exist at some web page.
So in the sharing menu there's a publish a service menu item.
You can select how you want it to be run.
You can have it only available to yourself for a personal
script or maybe something you're testing, to members of
your domain, or to anybody, where anybody either defines
any Google user, or really, anybody, any anonymous user on
the internet.
And here's the best part.
As soon as you click Enable service, that URL you see
there is live.
That is the entire deployment process of Google Apps Script.
When you want to undeploy it, uncheck the box.
That's all it takes.
No XML, no manifest. I can't stress this enough.
OK, so I'm going to hand this over to Drew now.
Because although I've spoken a lot about how to build the UI,
I haven't actually told you what to do with it.
DREW CSILLAG: Well, Corey showed you how to build this
nice, fancy facade for building this mortgage
Unfortunately he kind of hand waved over what I would
consider the difficult parts, the business logic.
And some of you may have guessed by the stuff that's in
there as going, how on earth did they actually read the
stuff out of the inbox?
Well I get to announce that we're rolling out the Gmail
service in the next couple of days, which will allow you to
full access--
full fidelity access to the Gmail inbox.
It's not through some IMAP thing or some of the other
ways that people have done this in the past.
So I was going to say this gives us a great way to be
able to do all sorts of stuff.
As far as the way the API works, if you've used Gmail--
anybody here use Gmail?
If you use Gmail, when you see the API you're going to be
like, oh duh.
That's just the way it's supposed to work.
And you can do all the normal things: compose, you can check
labels, all sorts of stuff.
In Gmail, just as in the interface, there are the main
three things.
There's threads, which contain messages, and those messages
can be labeled.
And they could be labeled multiple times.
The interface to deal with labels is pretty
You can create them, you can delete them, and you can get
them by either you could get all of them or get a specific
one that you're looking for.
Within the threads, you can get threads either by your
inbox, priority inbox, we even allow you to get it from your
spam if you actually want to look at your spam.
And we provide convenience methods to get things like the
number of unread messages in those threads.
They can also be marked as Important or Unimportant for
like the priority inbox within Gmail, you can mark them as
Read or Unread and you can move them around as well.
This is my personal favorite one because I use this all the
time, I use search for everything.
And through the search interface is really the longer
form version of being able to get all the things I just
talked about before.
And in the case of going back to the mortgage app, this is
how we're going to get the emails that we display in that
upper left pane.
Just like whatever you could put in that search box is the
same thing that you could put as the argument to corrected right there.
And then iterate over the threads, maybe do some
additional filtering or data munging if you want as you
loop over them, and then return the messages back.

Well the other thing that the mortgage app did is that at
the end of the day, it could send a quote to the person who
originally sent the email asking for the quote.
So also rolling out in the next couple of days is access
to Google Documents.
This allows you to write them, edit them, create them, the
whole nine yards.
And of course, if you're going to work with a document, you
need to do one of two things.
You need a document to start with.
So you can either create a new one, you can give it a name.
Or you can get an ID from one and open it by that.
And the IDs that we use here are, when you've got a Google
Document open, it's got a long string of random looking text
in the URL bar, that's what the ID is and that's what you
would pass in.
Within the document, if you're familiar with the W3C DOM,
it's different here.
The DOM for documents is a little different, but it will
be very familiar to you.
Within the document there's the body, there's paragraphs,
headers, footers, list items, tables, all that.
For right now, headers and footers are read only.
They will be read/write very soon.
So in our case, what we wanted to do for the mortgage app is
that we have this template document that's going to
contain the relevant information for the quote that
we're going to send them.
And so what we did is we made a template document and we put
in these placeholder fields right here, the start and end
with percent.
There's nothing magical about them, it's just something
handy that we're going to use to do a
little magic in a minute.

And Google Docs doesn't yet support fields, so we can't
use that for field substitution.
We've got this template document.
And then we're going to write a little JavaScript function.
And what it does is it goes to the DocsList and gets the file
with the original ID of the template.
You could do this by name if you wanted to.
And then we make a copy of it, and then we get the ID of the
document we just made a copy of.
Using that we use the document app to open it up.
We get the body content of the document and then we just do
basic search and replace for all the items that we wanted
to put in there.
And then we return the document and that'll become
important a little bit later.

Now I'm going to take a little bit of a tangent and talk
about something called blobs for a reason that will become
clear very shortly.

First, what's a blob?
It kind of looks like that funny-looking fish.
It's something ill-defined or amorphous.

Some people may have the notion of a binary large
object from a database, please cast that from your mind.
It reminds all of bad things and we don't want to talk
about them.
We have a bunch of different sources and sinks of data
within Google Apps Script.
And it might be you're in something, something and
you're putting it into your DocsList, or you're going to
query JDBC and then post that to some website, or do a file
upload into JDBC or email attachment.
I mean, you kind of get this Cartesian product of different
ways to interact with things and very quickly, this gets
out of hand.
And nobody wants to deal with any of this stuff.
So hence, the blob.
Anytime you're going to deal with some massive data that's
got a name, a type, and some measure of content to it, this
allows us to treat all these things the same way,
regardless of where they come from and regardless of where
they're going to be going to.

Blobs are fairly simple things.
They have a name, like I said.
They have a content type, which is like the
RFC style mime type.
And then they have content, either as
bites or as a stream.
You can treat them either way, depending upon what you want
to do with them.
The idea with a blob is that for a lot of times you're
dealing with data, you don't necessarily care about the
specific format of the data that's in there.
Say you get a JPEG image from someplace.
Most people aren't going to go parsing through the thing,
they just want to ship it off to something else.
But there's some cases where if you've gotten an RSS feed
from someplace, you want to be able to shuffle through the
thing to parse it apart.
And in some cases, depending upon what you're doing in your
scripts, you may actually in fact, want to create a blob
from scratch from code.

So the question is, OK, we've got these ideas of a blobs.
What can we do with them?
Well, say we'll get a bunch of blobs from the attachments of
this particular sites page that we've got.
And then we've got a URL fetch that we're going to do, go
fetch an image from someplace.
And I've got an image of my DocsList that I want to
include too.
And then, using the new zip functionality that we've added
to the utilities interface, which we also have an unzip,
which works the expected way.
We can now zip all these different things regardless of
where they came from and produce a
zipped blob named
And then from there, we can take all that and then mail it
all as a attachment to
And this all just works.
One of our co-workers that we were talking with and she had
started using it and had mentioned, it's almost like
magic when she used these things.
And yeah, it is kind of cool.
So why am I talking about blobs for all of this?
Spreadsheets and documents are blobs also
in this whole thing.
And one of the things we need to do if we're going to mail
these things around depending upon who gets them is we might
need to convert them in some fashion to some form that they
can actually use.
Because maybe they don't want a link.
So Google Docs can convert automatically to PDF.
A lot of other types we can convert those to PDF too.
Things that generally would have some form of expected PDF
form that you would expect.
We can also convert between image formats for the image
formats that are listed there.
And we also have a whole bunch of other ideas of conversions
we'd like to be able to do.
Some things would be like take an image, crop it, rotate it,
you could do that as a conversion.
Or say, get the second page in a spreadsheet, get this data
range out of it, and convert that to a PDF, or an image, or
something else that you could do.
Some of the more cooler things we were thinking of is that
Google's got some really cool stuff that can do speech
recognition and stuff.
So maybe you could convert a WAV file to a Google Doc.
All sorts of crazy things that we can think of.
Or doing OCR automatically on the fly from an image.
There's a lot more things that we want to do,
so watch this space.
So how do we actually do the conversions?
Fortunately, it's actually a pretty
simple matter from code.
You just say, getAs and here's the content type that I want.
So in this particular case, I've got a photo in my
DocsList and it's a JPEG as it starts off and I
want it as a PNG.
Just say, getAs image PNG.
And it's that simple.
Or, if I've got my attachments before, I can--
arrays in JavaScript have a bunch of couple of nifty
methods that I kind of forget that they're there.
But there's a neat one called map, which allows me to take
an anonymous function and say for each of the items that are
in those attachments, get them all as application PDF.
The map function is very similar and Python has a map
function that's very similar, and schemes
it's the same thing.
In the Java guava-libraries it's intervals.transform.
It shows up as it's a common thing, where it's basically
apply this function to every element in the original array
and return me array of those results.
Or to spell it out a little bit more clearly, SitesApp.
You get the original list of attachments.
You start off with an empty array of PDFs and then for
each of the blobs that were in the blobs array is you push a
converted one from the blobs array.
Or, going back to the mortgage example, we had that
createDocument function before and it returned the document
that it had produced.
So we're going to take that document and then we're going
to take the message also that we had some Gmail that we
originally started with, and we're going to reply to it.
And then we're going to take the document that we got that
we had created, we're going to convert it to PDF and attach
it to that reply.
And then it's going to send off.
And then we're going to mark the message as read, so that
therefore when we go back to that UI, we don't see it
anymore because it only looks for things that were unread.
So starting with this, we've already
got the email selected.
He's going to punch in the $240,000 at 4%, 25 years, come
up with this payment of $1,266.81 and he's going to
generate the reply.
He goes over to check his email and sure
enough there's the email.
And if you look at the attachments, there it is, the
PDF file we made.
And then opening it up as a PDF--
because Chrome nicely supports PDF files--

DREW CSILLAG: So we've done a bunch of
boring data entry apps.
But Apps Script doesn't always have to be that boring.
It can look really snappy and snazzy.
And here to talk about that is James.

JAMES FERREIRA: Well hello everybody.
I guess we're a little early today.
Thank you.
So I'm really, really excited to be here talking to you all
today here at Google IO.
And I wanted to show you some of the things that you could
do with that new GUI editor and how we're
going to use that.
So as a developer that's always on the go, I'm hopping
from computer to computer, one of the things I really
appreciate about Google Script is that it's 100% web
So while I'm developing for the web, I can
do that on the web.
When Google Script put Script Gadgets into sites, as
developers, we gained a lot of ability to be able to engage
the viewers in a completely new way that's very
So now we can do things like hover over pop-up menus and
informational pieces.
And this also works great for the educational setting for
teachers to better engage students with the information
they want to get out to them.

I wanted to show you an app that we built.
It's called Andy.
And Andy's got a few tasks he wants to perform to you today.
And what we have here is we have a control panel that's a
set of buttons up at the top of the screen that move Andy.
So what we're going to do is we're going to head on over to
the calendar app and we're going to retrieve a list of
Andy's events for the day.
And we can format those in a way that matches our theme for
the application.
Now Andy can see that he's got some work that he
needs to get done.
So he's going to go up and do a little writing in Docs.

So here we have another list of Andy's Docs pulled from a
specific folder in his Google Documents.
And let's go ahead and create a document, so we can get a
little work done here.

Now you see that automatically updates the list there.
Well it's time for Andy to get social.
So let's go ahead and in order to do that we're going to have
to connect to a service that's outside Google Script.
So here we see we're pulling in the latest news and a Buzz
from Andy's friends using the URL fetch app.
So say thank you, Andy.
So these are the different scripts we used.
So what I want to do next is I want to show you how we go
about designing a UI like this and--
sorry, I have to stay close to the mike--
and how we make Andy move.
So when you're building an app in the UiApp, it's kind of
like painting a picture.
You add some [? gesso ?]
and some color and pretty soon you have mountains and trees
and airplanes and things like that.
In order to get depth of field in a painting, you paint over
the top of other things and that gives you that depth.
Well in the UiApp, when we add things to the UiApp, they add
in the order that they were placed on the page.
So they stack to the lowest point.
Here we've added a couple of grids to the
page that have stacked.
And what we can do next is we can add in--
and you'll be able to do this obviously, in the
GUI editor as well.
So we can add elements to each cell within a grid and create,
basically a traditional table or div type web page like you
would traditionally do.

What we'd like to do now is I'd like to show you a little
bit about how you can use CSS to position
objects on the page.
And we use the position fixed to set items above the page,
so that we can move them.
The problem with that is directly in our code, when we
start applying attributes, you have to write an attribute for
every single widget that you want to use.
And that gets really messy.
So you can do that by using a function that will cycle
through-- you create the CSS just as you normally would.
Write CSS in an HTML page.
And you use a function to apply that to whatever widget
you happen to want.
So here we have a function that will apply a given
element there.
So to make Andy move, what we're going to do first is
we're going to set some x-, y-coordinates in the script
That way we can access that property from anywhere in the
script by just calling it by, say, Get property x.

Once we've set those positions, then we can give
Andy a starting position by using, like I had said before,
we use the function, or we set a CSS element, the atAndy
element, and give him a position.
Then we can create the atAndy image and apply the CSS, and
then he'll be in his starting position.
To make him move we're going to need a couple of buttons.

First we're going to create the button, then we're going
to attach a click handler to it that's going to fire off
the function move, and we're going to set the idea of each
button to be the direction that it's going to press.

Here's the move function.
And the first thing we do in the move function is we're
going to get where Andy's currently at by
using the get property.
We're going to set x and y.
And then we're going to run through a series of if
statements where we're going to check the e parameter
source to find out which button was pressed.
And we're also going to use an additional if that if Andy
happen to be at the side or the top or the bottom, that
he's going to stop and it's just going to return the
Once we know which button's been pressed, then it's just a
simple matter of incrementing or decrementing the property.
And then we'll apply the CSS like we did before when we set
his original start position.

That's it.
COREY GOLDFEDER: So let me recap.
Once again, this is Bob.
And now Bob is really happy because not only is he helping
people, he's not wasting any time doing it.
Today we built Bob's mortgage calculator using the brand new
GUI Builder that like I said, is available today.
We were able to build a full app, as well as a spreadsheet
calculator add-in.
And we deployed it as a service and to the gallery.
We also showed you the new Gmail service, which is
launching in the next day or two.
Which is just as simple as using Gmail itself.
And finally, we showed you the document service.
Which finally has an API for scripting Google Documents.
I keep saying finally, but we have a lot more actually
because we showed you blobs.
Don't overthink it, it will just work.
Take objects, attachments from sites, attachments from Gmail,
post them directly to your DocList. Don't worry about the
type of the object, it will just work.
And conversions.
Some simple cases like Google Documents to PDF
were covered today.
Stay tuned for more and interesting ones.
Finally, James was kind enough to show us Andy App and some
expert tips on how to use Google Apps Script to do more
than just boring data entry.
So at this point, we'd like to take questions.
Drew, James, and I will answer any questions you have about
what we showed you today.

AUDIENCE: They don't want to hear the question.
JAMES FERREIRA: We can hear you.
AUDIENCE: The question I have about this new Gmail access
service, which sounds really exciting is,
will this allow me--
it wasn't clear to me how the user is authenticated.
You say this actually uses the context like, for example, if
I'm trying to access the context of a user, do we have
to use OATH or something else like that to
authenticate the user?
JAMES FERREIRA: If you've used like the contacts apps
interface or the calendar app.
You know how you get the auth screen when you run it the
first time?
It's the same kind of thing.
AUDIENCE: So it will be the same thing for that?
JAMES FERREIRA: Exactly the same thing.
COREY GOLDFEDER: Yeah, we do the auth for you.
So all you need to do is click OK, I want to authorize this
and it will work.
So sounds like it's a dramatic simplification in terms of
setting that up for us.
JAMES FERREIRA: That was the idea.
Thank you so much for your work on this.

Do you have any plans to include search
as one of the services?
COREY GOLDFEDER: I don't think we have anything to
say about that now.
I don't think anyone's currently working on that.
But can never rule anything out in the future.

COREY GOLDFEDER: You can always use existing APIs.
So for example, any kind of existing REST based API can be
hit through URL fetch.
AUDIENCE: I can't remember from the
slide about the Gmail.
Does it access as well the contact and the
group in the contact?
Like if you say, want to do a mailing to a group in your
contact, can you do that?
COREY GOLDFEDER: You can access contacts through the
existing contacts apps.
So the new Gmail app doesn't support that because we
already have that support.
But it's there.
AUDIENCE: OK, but you can't--
can't you do like the example you had with the document
where you send to people-- where you place--
Let's say you have a group in your contact and your
and they want to use that template in their doc to send
the same email with the PDF attached to a group of people
replacing just the [INAUDIBLE].
JAMES FERREIRA: You have a contacts groups in your
contacts that you want to be able to--
AUDIENCE: Yeah, you have a group you want to--
JAMES FERREIRA: Within the contacts app, there's actually
a way to say get me this particular contact group and
then get the email addresses out of there.
So from there, yeah, you'd have the list of emails and
then you just do the message.reply like we did
before, just with a list--
with an array of email addresses
instead of the lone one.

AUDIENCE: So I saw the search in Gmail.
I didn't see one in Docs.
Is there a search function inside of the documents now?
COREY GOLDFEDER: Yeah, it's called Find.
It's docList.Find.
It's there.
We actually showed it in one of the slides.
AUDIENCE: Oh, I missed it.
Are you asking about in the DocsList or in the new
document app?
AUDIENCE: If you had a new document.
I guess if you have DocsList you can find by--
I didn't think about that.
So you said document open by ID basically, right?
JAMES FERREIRA: Yeah, it was document open by ID.
Going through the DocsList, you can search by name.

The document creation and updating features that you are
just showing, is there an API doing the same thing?
Or do you plan to do this?
JAMES FERREIRA: I don't think I understand the question.
I'm sorry.
AUDIENCE: Here we are using Google Script to create a
document and to add some custom data.
But on GData API for external application, we can't do this.
So is there a plan to add the possibility to create and
update documents from an external application?
COREY GOLDFEDER: We don't know.
We're not on that team.
We're just providing the glue as far as that goes.
The Docs people would be a better people
to ask about that.
AUDIENCE: OK, thank you.

AUDIENCE: Hi, I understand now we can add an image to a
Google spreadsheet.
COREY GOLDFEDER: In general, you mean, in spreadsheets?
AUDIENCE: Is it possible to assess the image using Google
Apps Script?
COREY GOLDFEDER: I don't believe
it's currently possible.
We try to catch up with spreadsheet features
as they come in.
So we will probably add that as we go on.
I do not think that's currently possible.
JAMES FERREIRA: I don't remember seeing it in the API
just yet, but we can look into it.

COREY GOLDFEDER: OK, are there any more questions?
Going once, going twice.
OK, thank everyone very much.