Friday, March 13, 2015

Simplifying Migration from VBA to Google Apps Script

Editor’s Note: Guest author Bruce McPherson is a contributor to the Excel Liberation website and blog. -- Eric Koleda

If you are new to Google Apps Script and the JavaScript programming language, migrating legacy automation code written in Microsofts Visual Basic for Applications (VBA) can be a daunting task. This blog post describes a Google Apps Script library which mimics the behavior and calling structure of common VBA functions, allowing you to more easily convert your existing applications.

Retaining compatibility

If you are planning to continue to use VBA, you can minimize both the work involved in maintaining the same capability in both platforms, and in porting from one to the other, by preserving backwards compatibility with VBA. This means breaking a few JavaScript conventions, but the result is worth it.

For example, JavaScript variables are normally written in lowerCamelCase, with classes being in UpperCamelCase. VBA is not case sensitive, and uses hungarian notation by convention, except for the built-in functions, which have a capitalized first letter. Since the objective here is to minimize change, I have decided to retain this capitalization for VBA functions replacements (for example CStr(), Mid() etc. ).

In VBA, indices (normally) start at 1, while in JavaScript they start at 0. Since these functions are to minimize change in application written in VBA, they also start at 1. For example Mid(x, 1, 2) means the first 2 characters of
string x in both VBA and JavaScript versions.

Enumeration of collections

JavaScript does not have a collection object. The vEquivalents library provides an implementation of a collection class so that continuity for migrated code that relies on the collection can be maintained. But how to enumerate through that collection? There are a number of ways, but the forEach() method of the collection most closely resembles the For Each member in collection approach VBA developers are familiar with. The syntax may seem a little fiddly at first, since it passes the code you want executed against each member of the collection as an anonymous function.

var coll = new collection();
// by index
for (var i=1; i <= coll.count() ;i++) {
DebugPrint (coll.item(i));
}
// by key
for (k in coll.keys()) {
DebugPrint (coll.item(k));
}
// forEach
coll.forEach(
function (item, index) {
DebugPrint (item, index);
}
);

Including vEquivalents in your Google Apps Script Project

With the great new libraries functionality, you can now include these scripts in your project by using the project key "MEQ3tE5y5_cTOAgUbUKSIAiz3TLx7pV4j", or you can make a copy of the scripts directly to include in your own project. You will find a selection of other scripts in the library, but the VBA equivalents are all in the module vEquivalents. Note that as you include external libraries in your project (see here for how), you need to prefix the functions with the library identifier (for example mcpher.CStr())

Examples

You can access the documentation here, and you will see that most of the common VBA functions are included. Some examples are

var x = Trim(s);
var x = Len(s);
var a = Split(s);
var x = Instr(1, s1, s2);
var d = DateSerial(y, m, d);
MsgBox(s);
var x = InputBox(s);
DebugAssert (b, s);
var w = ActiveSheet();

Going beyond the built-in VBA functions

Using the same approach, I have converted many other VBA utility classes and procedures built over time and added them to this library. This means that the implementation of something on either platform not only looks the same, but can be accomplished in hours or even minutes. For example, on my blog I publish a daily API, implemented in both VBA and Apps Script (both versions even use ScriptDB for the same parameter data). Heres a recent one.

function testUkPostcodes() {
mcpher.generalDataSetQuery ("uk postcodes", "uk postcodes", "postcode");
}

Public Sub testUkPostcodes()
generalDataSetQuery "uk postcodes", "uk postcodes", "postcode"
End Sub

You can find more projects that have been migrated this way here.


Bruce McPherson   profile | twitter

Bruce McPherson is a contributor to Excel Liberation website and blog, and advocate for open data.

Read more »

Introducing AdSense Management Services in Apps Script

Editors note: this announcement is cross-posted from the Google Ads Developer Blog, which caters to AdWords, AdSense, DoubleClick and AdMob developers. We hope you enjoy this latest addition to Google Apps Script — Ryan Boyd

Starting today, the AdSense Management API is available as part of AdSense Services in Google Apps Script. This means that you’ll be able to do things like:

  • Create AdSense performance reports for your AdSense accounts in a Google spreadsheet
  • Create a chart based on your AdSense reporting data and display it in a Google Spreadsheet
  • Embed your scripts in a Google Sites page, for instance to import a chart
  • Use triggers to schedule the execution of your scripts, for instance to periodically update the chart imported in the Google Sites page

Accessing the API from Google Apps Scripts is very easy. The following snippet of code shows how to generate a report and populate columns of a spreadsheet with the data retrieved:

function generateReport() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(Reports);
var startDate = Browser.inputBox(
"Enter a start date (format: yyyy-mm-dd)");
var endDate = Browser.inputBox(
"Enter an end date (format: yyyy-mm-dd)");
var args = {
metric: [PAGE_VIEWS, AD_REQUESTS, MATCHED_AD_REQUESTS,
INDIVIDUAL_AD_IMPRESSIONS],
dimension: [MONTH]};
var report = AdSense.Reports.generate(startDate, endDate, args).getRows();
for (var i=0; i<report.length; i++) {
var row = report[i];
sheet.getRange(A + String(i+2)).setValue(row[0]);
sheet.getRange(B + String(i+2)).setValue(row[1]);
sheet.getRange(C + String(i+2)).setValue(row[2]);
sheet.getRange(D + String(i+2)).setValue(row[3]);
sheet.getRange(E + String(i+2)).setValue(row[4]);
}
}
If you want to generate a chart from your data instead of populating the spreadsheet, that’s very easy as well:
function generateLineChart() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var startDate = Browser.inputBox(
"Enter a start date (format: yyyy-mm-dd)");
var endDate = Browser.inputBox(
"Enter an end date (format: yyyy-mm-dd)");
var adClientId = Browser.inputBox("Enter an ad client id");
var args = {
filter: [AD_CLIENT_ID== + adClientId],
metric: [PAGE_VIEWS, AD_REQUESTS, MATCHED_AD_REQUESTS,
INDIVIDUAL_AD_IMPRESSIONS],
dimension: [MONTH]};
var report = AdSense.Reports.generate(startDate, endDate, args).getRows();
var data = Charts.newDataTable()
.addColumn(Charts.ColumnType.STRING, "Month")
.addColumn(Charts.ColumnType.NUMBER, "Page views")
.addColumn(Charts.ColumnType.NUMBER, "Ad requests")
.addColumn(Charts.ColumnType.NUMBER, "Matched ad requests")
.addColumn(Charts.ColumnType.NUMBER, "Individual ad impressions");

// Convert the metrics to numeric values.
for (var i=0; i<report.length; i++) {
var row = report[i];
data.addRow([row[0],parseInt(row[1]),parseInt(row[2]),
parseInt(row[3]),parseInt(row[4])]);
}
data.build();

var chart = Charts.newLineChart()
.setDataTable(data)
.setTitle("Performances per Month")
.build();

var app = UiApp.createApplication().setTitle("Performances");
var panel = app.createVerticalPanel()
.setHeight(350)
.setWidth(700);
panel.add(chart);
app.add(panel);
doc.show(app);
}
A shiny line chart will be displayed in your spreadsheet, as shown in the following picture:


You can start using the service by checking out the reference documentation, that contains also some sample scripts, and this tutorial that implements the use cases mentioned above.

Happy Google Apps Scripting with the AdSense Management API!

Silvano Luciani   profile

Silvano Luciani joined Googles London office in 2011 to make the AdSense API developers happier people. Before that, he has worked in Finland, Italy, Spain and the UK, writing web based configuration management tools for ISPs, social networks, web based training materials, e-commerce apps and more. He has recently discovered that he loves charts, and has finally started to play the drums in the London’s office music room. If you can call what he does "playing the drums".

Read more »

Story Maps A Testing Tool After All

The following was recently published as a sidebar in Lisa Crispin and Janet Gregorys new book More Agile Testing. The book is full of great advice from the authors as well as other contributors. I encourage you to take a look.

So you’re an agile tester and wonder why you should care about story maps. You may already be convinced that modelling your backlog in two dimensions is useful for helping the whole team visualize the big picture. However, story maps are also a valuable testing tool, providing two additional testing avenues. In the first case, the map itself offers the ability to test the validity of a solution. In the second, a story map improves a team’s ability to identify story slices and then test them.

User Story Mapping Series

* How to Create a User Story Map
* How to Prioritize a User Story Map
* Tips for Facilitating a User Story Mapping Session
* Dont Etch your User Story Map in Stone
* User Story Mapping Tool Review – SmartViewApp
* Story Maps - A Testing Tool After All
Testing What to Build

User story maps are a representation: they provide a means to visualize a system that might be built and are useful for testing the validity of that system before investing significant time and money. A story shared at a recent Agile Winnipeg event demonstrated this principle well. The company involved used story mapping to test an idea before building any software. The team had a project idea that they thought would serve their client well. After quickly building a story map around that idea, they presented the map to their client at the next customer conference. Although it soon became clear that the idea missed the mark, the customer was able to collaborate with the team on the spot, to adjust the map until it represented what they actually wanted built. The map itself was the tool that allowed for the idea to be tested (and then adjusted) and moved the project forward.

Testing Application Slices

As Crispin and Gregory demonstrated in their first book Agile Testing, identifying thin slices and small chunks is important for testing agile projects. Story maps help identify those slices but, perhaps more importantly, they help us understand how those thinly sliced stories might fit together to form a thin slice of the whole application. When undertaking an agile project, testers are required to make a vital shift in thinking; only test small pieces at a time. Despite this fundamental change, it is also important to ensure that the first few pieces fit together, enabling end to end testing as early as possible. The story map helps to identify and prioritize that first application slice. It may be based on a user scenario or just a string of stories that represent the smallest stories that allow left to right movement on the map.

Visualizing testing slices in your map

As that the team identifies that first slice, utilizing excellent testing skills is crucial. By looking at the map, you can identify areas that will be difficult to test, areas where the test variations are still relatively unknown, or areas that represent higher risk. This activity can help identify stories that should be included in the first application slice.

When coding and testing begins, personas and user scenarios that were created can be revisited, helping to flesh out the map and application slices. Testing with a persona in mind helps ensure that the targeted customer will be satisfied with the solution. It may not be possible or wise to test if the application works well for everyone but testing should evaluate whether the targeted personas can use the application easily, and that the new functionality fits into, or adds to their current processes without getting in the way.

Story Maps—A Testing Tool After All

At first glance, the story map doesn’t appear to be an obvious asset for testing, but upon closer inspection, it proves its value in any testing toolbox. The map itself is a reliable way to test that the right system is being built before any code is written. The map also provides a visual aid for testing in horizontal application slices, allowing for early confirmation that a project is on the right track.

Subscribe to Winnipeg Agilist by Email
Read more »

Thursday, March 12, 2015

Automating business processes with Google Apps Scripts

Google Sites lets you create public or internal web sites, and today we’re enabling scripts to support multi-step workflows in sites.

For example, your company can create a site for employees to browse and register for training sessions and career development programs. On the page describing each training session or class, you could add a “Register Now” button, which would automatically add registrants to the class roster, add the details of the session to each participants Google Calendar, and email users to confirm enrollment. All of these automated actions can be driven by a script embedded in the site.



Starting today, you can create, edit, and launch Google Apps Scripts from any Google Site, which allows you to automate business processes that involve multiple applications. As in the example above, an Apps Script function can automate tasks such as sending emails, scheduling calendar events, creating and updating site pages using data from other systems, and more.

You can build a script by clicking “More actions” > “Manage site” > “Apps Scripts.” Once you’ve added a script to your site, you can add links or buttons to trigger the script from any page. For tips to get started with scripts, visit the Google Apps Script site.


Want to weigh in on this topic? Discuss on Buzz

Read more »

Announcing Version 1 9 of the NET Library for Google Data APIs

We have released version 1.9 of the .NET Library for Google Data APIs and it is available for download.

This version adds the following new features:

  • support for 3-legged OAuth
  • two new sample applications: BookThemAll (mashup of Calendar and Provisioning APIs) and UnshareProfiles (showcasing a new feature of the Google Apps Profiles API)
  • updates to the Content for Shopping API to implement 20+ new item attributes
  • support for new yt:rating system and Access Control settings to the YouTube API

This new version also removes the client library for the deprecated Google Base API and fixes 20 bugs.

For more details, please check the Release Notes and remember to file feature requests or bugs in the project issue tracker.

Claudio Cherubino profile | twitter | blog

Claudio is a Developer Programs Engineer working on Google Apps APIs and the Google Apps Marketplace. Prior to Google, he worked as software developer, technology evangelist, community manager, consultant, technical translator and has contributed to many open-source projects, including MySQL, PHP, Wordpress, Songbird and Project Voldemort.

Read more »

User stories and sandbag dikes

This year on the Canadian prairies we experienced a lot of flooding and residents banded together to support each other - building sandbag dikes to help keep the water out. During this ordeal, I had a small aha moment in comparing user stories to sandbag dikes. User stories and sandbag dikes are similar because:

1. They are both boundary objects. Well constructed dikes keep water out and contain a dry area. Well crafted user stories contain scope and keep additional scope out.

2.  There is no value to the user unless all layers are complete. To build a dike, you need to pile the sandbags on top of each other in layers and also weave in the plastic. Leave a layer out or forget the plastic and the dike is useless to the homeowner. To complete a user story, you need to build all layers or tiers of the system. A new database table doesnt provide any value to the user.

3. Size is important. If you want to protect a home from flooding, the dike only needs to surround the home, not the whole property. In fact, if you build it too big (for example, to protect the house, the shed, and the swing set), there are more potential points of failure, it takes longer to build which increases the risk of the dike not being completed on time, and you could have spent more time building dikes to protect other homes. If your stories are too big (for example, to implement logging in for a site, you build the login w/ password, forgot password, password reset, max login attempts, etc before building other stories), there are more potential points of failure, it takes longer to build which increases the risk of the story not being completed on time, and you could have spent more time completing other stories to increase the value of your project.

4. Priority is important. If you build dikes around the homes that are less likely to be affected by the flood, then when you run out of time it is likely that more homes will be flooded. If you complete lower priority user stories first, then when you run out of money you may not have accomplished the goals of your project.

Read more »

Wednesday, March 11, 2015

How to get from weekend idea to funded startup

This is cross-posted from the Google Code Blog because we think it will be of interest to Google Apps developers

Almost every developer has an idea and might want to start a company. Where do you start? Entrepreneurs Paul Buchheit, Joe Kraus, and Seth Priebatsch explained how to go from hacking on the nights and weekends to building an investor funded startup. We also discussed how to find co-founders, attract investors, and focus on the key decisions. You can watch the complete Google I/O session on YouTube. Here are some highlights.



Should I have a co-founder? Having strong co-founders join you in transforming your idea into a real company is critical to success. There is a positive correlation between the number of co-founders and successful outcomes up to about four co-founders. Beyond four co-founders there isn’t much data. But having more co-founders on your team definitely improves your chances of success.

What are important characteristics of a co-founder? It helps if you have worked together before, know each other well, have complimentary expertise, and can communicate openly and honestly. Joe Kraus said you should be able to settle arguments with great answers, not the compromise middle position. What else should you look for in a co-founder?
  1. Experience starting a company
  2. Domain experience and an understanding of the market
  3. Balance and different experience than your own
  4. Passion about the company vision
How do you get started? Paul Buchheit knew he wanted to start a company but didn’t know how. So, he decided to join a startup to get some experience. That startup was Google. Paul learned how startups grow, and worked with some great people who would later become his co-founders at FriendFeed. Having experience at a startup earns you credibility with potential co-founders, employees, and investors.

What matters most; team, traction, idea, or market segment? They all matter, but the people on the team are the number one consideration. The founding team shapes the product vision and sets the direction for the company. Potential employees and investors are attracted...or not, by the members of the founding team. The idea matters, but will probably change significantly over time, so most investors don’t fixate on the idea. The market segment is important, but only as a gauge of the range of successful outcomes. Traction from early users or customers makes it much easier to raise money.

How do you find investors? People invest in businesses they understand, or people they know. Look for investors that have started companies in your area, or have invested in similar companies in the past. Talk to everyone you know about your idea. Joe Kraus, co-founder of Excite, tells the story of how he read a book about starting companies, called the author, got introduced to other people, who introduced him to other people, and finally ended up with a $3M investment from Kleiner Perkins, one of the top VCs in the world.

Should you raise money from VCs or Angels? The first consideration is who can help you most. You want more than just money from investors. You want help, advice, introductions to other people who can help, and maybe access to press. Aside from help, it depends on how much money you need to raise. Friends and Family is the best place to start to raise small amounts of money. Angel investors can fund anywhere from $100K to $1M or more. Venture Capitalists (VCs) usually invest $1M to $3M in a first round Series A investment.

Incubators, Angels, and VCs - Seth Priebatsch, founder of SCVNGR.com did all three in starting his company. Seth entered a business plan competition at Princeton...and won. He used that to get the initial product built, and then applied to DreamIT, a startup incubator. That experience at the incubator allowed him to build and refine the product. Next he raised a small amount of money from Angels and brought on advisers to help him grow the company. That led to a small round from VCs. Seth believes the more investors you have, the more help, advice, and experience you get.

How do you arrive at a valuation for the company? Joe Kraus says it is an art, not a science. It depends on the stage of the company, the competition, and how fast the market segment is growing. Most early stage startups don’t have revenue and don’t have many users so the valuation is typically between $1M and $3M, and depends on the experience of the founding team, how much progress you have made on the product, and the relative success of competitors. The best way to determine a fair valuation is by having several competing investors give you proposals.

Do I need a business plan? No, but you do need a good slide deck that explains what you want to do, what problem it solves, why it will be successful, and how your team can execute on the vision. Here is a link to a post that explains how to pitch your company to investors. A good pitch deck and a product demo are what most investors are looking for. Business plans might be useful for helping you refine your ideas and vision, but most investors will never read it.

Are patents, IP, and trademarks important? Paul Buchheit says in most cases they don’t matter for early stage startups. Joe Kraus added, patents might be of some value to a potential acquirer, but probably just as a defense against patent infringement cases. Patents are very expensive to obtain (legal bills) and they take two to four years, sometimes longer, to actually get issued. By that time most startups are out of business, acquired, or moving on to something else. Even if you have a patent, most startups can’t afford to defend them in court against potential infringers. The legal expense of defending a patent, and time lost away from your business, make it nearly impossible for a small startup.

Want to weigh in on this topic? Discuss on Buzz



Don Dodge profile | twitter | blog | events

Don Dodge is a Developer Advocate at Google helping developers build new applications on Google platforms and technologies. Prior to joining Google Don was a startup evangelist at Microsoft. He is also a veteran of five start-ups including Forte Software, AltaVista, Napster, Bowstreet, and Groove Networks.

Read more »

Are we agile yet Applying fuzzy logic to the manifesto

Some background on logic from my brother who is a math professor:

In Greek logic (the logic of Plato and Aristotle) there are only two truth values. Any statement is either true, or false, but not both. Truth is absolute. This works nicely except for when we say things like:
"This sentence is false" 
If this statement is true, then it is also false, and if it is false, then it is also true, and if it is true, then it is also false - a fun logical circle which causes trouble for Greek logic. This liars paradox was ignored for about 2500 years. Since sentences are either true or false, then the sentence above obviously isnt a sentence. Case closed.

In the last century, mathematicians started to realize that things were not so simple. A quote from my brother:
"There are contradictions in the laws of physics – We have Einstein’s relativity that explains planetary motion, gravity, all these big things. And we have quantum mechanics that explains subatomic energy and matter, all those tiny things. Unfortunately, they contradict each other in the middle. Because the one requires physical reality to be absolutely smooth and continuous, while the other requires quantum bumps, which are profoundly non-smooth and discontinuous. Right now the laws of physics are both true and false (and by false, I mean true.)"
More common examples of statements that can be both true and false include: "I am young", "I am tall", and of course, "We are agile". Truth becomes fuzzy. The truth of those statements can lie somewhere in between absolutely false and absolutely true depending on who is saying them.
"A newborn is young" = truth value of 100%.
"A 20 year old is young" = truth value of 80%
Thus, fuzzy logic was born. Statements can have a truth value in between true and false.

Now lets apply this to the question "Are we agile yet?" by looking at the four tenants of the agile manifesto:
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan
Many of us have read articles or have been in discussion groups where these statements are discussed at length and usually someone tries to apply Greek logic by making statements such as: "Agile has no documentation" and "Agile means no planning". However, the word "over" in the middle implies that fuzzy logic is at work. The manifesto authors are saying that for agile teams truth should be closer to the left than the right. We should focus more of our time on working software and less of our time creating documentation. Planning is still important but responding to change is more important so our plans need to be more flexible. For each statement, we want the left side to be more true than the right - the truth value should be above 50%. Additionally, having a truth value of 100% for any of the statements above can be a dangerous thing. We should stay fuzzy.

So when answering the original question for your team or organization - "Are we agile yet?" - dont expect a checklist of practices to give you the answer. Instead, ask your team this question: "Given the statements above, which direction are we moving?" If you are moving to the left and have committed to staying on the left side of each equation, then youve joined the club - you are agile. Agile is a direction, and that is absolutely true.

My brother Tims bio: http://www.cmu.ca/facultystaff/trogalsky.html
Read more »

Storing Items in Drive BLOBs vs Shortcuts

The Drive SDK allows apps to store all kinds of files and file-like items in user-managed cloud storage. Files can be standard document formats like PDF, images, video & audio clips, or even your proprietary application data files. Storing files in Drive makes it easy for users to organize, search, and securely share them with their coworkers, friends, or family.

However, some applications work better with document or application data stored in a database. For example, let’s imagine a modern, web-based project management tool that provides lots of awesome features via data objects that are assembled dynamically at runtime for presentation to the user. In such cases, there is no single file to store all the data that comprises the project -- though there is of course a named “file” item that users will want to save and list in their Drive. Drive applications like this can create file-like entries called shortcuts that allow users to organize, access, and share items as if they were files stored in Drive.


Creating Shortcuts

Creating a shortcut is not much different than creating a regular file. Just set the MIME type to application/vnd.google-apps.drive-sdk, and make sure you don’t upload any actual content in the call to files.insert. Here’s an example of creating a shortcut using Python:


shortcut = {
title: My project plan,
mimetype: application/vnd.google-apps.drive-sdk,
description: Project plan for the launch of our new product!
}
file = service.files().insert(body=shortcut).execute()
key = file[id] # Key to use when re-opening shortcuts

For examples in other supported languages, see the Drive SDK documentation.

Opening shortcuts in Drive always launches the application that created them. Shortcuts can even be synchronized to the desktop. Opening a shortcut from the desktop will launch the application that created it in a new browser tab.


Sharing and Security

Shortcuts require special consideration when it comes to sharing and security. Since the actual content is not stored in Drive, applications are responsible for enforcing permissions and ensuring that only authorized users are allowed to read or update content. Follow these best practices when working with shortcuts:

  • Always call files.get with the current user’s access token to verify the user has access to the content.
  • Restrict user actions based on the userPermission property of the file and disable saves if the user only has reader or commenter roles.

Honoring permissions not only ensures the protection of user data, but also provides a consistent user experience and added value to Drive applications. Users should be able to safely share an item in Drive without worrying about the particular implementation details of the application that created it.

If you have any questions about shortcuts, don’t hesitate to ask us on our Stack Overflow tag, google-drive-sdk



Steven Bazyl   profile | twitter | events

Steve is a Developer Advocate for Google Drive, Google Apps, and the Google Apps Marketplace. He enjoys helping developers find ways to integrate their apps and bring added value to users.

Read more »

Google Apps Marketplace Developer Survey

The Google Apps Marketplace team would like to get feedback from the developer community on your experience with the Marketplace and what you think can be done to improve it.

Please fill out the survey below if you have an installable app on the Marketplace (using the Add it Now blue button), are actively building an installable app or previously had an installable app on the Marketplace.

Most questions are optional, so please provide the feedback most important to you even if you dont have time to complete the whole survey.

Wed also like to offer the opportunity to speak 1:1 with the Google team about your Marketplace app. If youre interested, please provide a proposed agenda at the end of the survey.

-Ryan, Scott, Steve and the entire Apps Marketplace team





If you do not see the survey embedded above, please visit the form directly.



Ryan Boyd profile | twitter | events

Ryan is a Developer Advocate on the Google Apps Marketplace team, helping businesses build applications integrated into Google Apps. Wearing both engineering and business development hats, youll find Ryan writing code and helping businesses get to market with integrated features.

Read more »

DrEdit for Google Drive and Learning AngularJS

Since we released version 2 of the Google Drive SDK at Google I/O, we’ve been quietly updating the DrEdit sample application to use the new API. As part of the update, the UI for DrEdit has been rewritten to use AngularJS, a modern web application toolset developed by Google and used in apps at DoubleClick. You might be wondering -- why go through the trouble of rewriting the UI for a basic sample app just to show off some new API features? Turns out it was more of a happy coincidence, but a valuable one and great learning experience!

Practice what you preach

I had the pleasure of co-presenting a session on building great apps for Google Drive, and a big focus of the talk was on all the little things that go into making an app intuitive and user-friendly. This is particularly important for Google Drive, where many users are already familiar with the built-in apps like Docs, Presentations, and Spreadsheets.

The first version of DrEdit was a good demo app, but didn’t follow all of our recommendations. I didn’t want to tell developers all the things they should be doing without having tried them myself. I decided to write a separate sample for the talk and needed a solid base to build on. It was the perfect opportunity to learn a new tool!

HTML & Javascript, only smarter

Angular doesn’t aim to abstract away HTML, Javascript & CSS. Rather, it enhances HTML to make building dynamic apps easier. One benefit, besides a nice short learning curve, is the positive interaction with other tools. To give the app some structure, I used Bootstrap. For example, the HTML for displaying the authenticated user’s info and a small dropdown to link to their profile in the navigation bar only required a few minor changes from typical Bootstrap usage (shown in bold) to wire up to a controller.


<ul class="nav pull-right" ng-controller="UserCtrl">
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
{{user.email}}
</a>
<ul class="dropdown-menu">
<li><a href="{{user.link}}" target="_blank">Profile</a></li>
</ul>
</li>
</ul>

Even models are plain javascript objects. Anything reachable through a scope (the binding between a view and controller) is considered part of the model. These can be primitives, hashes, or objects. No need to extend a base class or access properties through special properties. Rather than use change listeners that require special instrumentation, Angular uses dirty checking to detect model changes and update views.

The one catch with this approach is it requires any changes to the model to be made inside the scope of a scope.$apply(fn) call. In most cases, this is done automatically. When working with external libraries or raw XMLHttpRequests that can fire asynchronous callbacks, calling $apply yourself is necessary to make sure mutations are tracked correctly.

Speaking of asynchronous tasks…

Promises, Promises

No, I’m not talking about the hit song by 80’s band Naked Eyes, rather Angular’s $q service based on one of the proposed CommonJS Promises APIs. If you’re already familiar with JQuery’s deferred object or any of the other related implementations, this is familiar territory. If not, time to learn. Working with deferred objects can be a lot easier than the traditional callback approach. You can compose async tasks either serially or in parallel, chain callbacks, and return deferred objects from functions like normal results.

Where this mostly comes into play is Angular’s $http service. If you’ve used jQuery, you’ll find it similar to jQuery.ajax() & the jqXHR result. It is based on the deferred/promises API and also ensures callbacks are executed correctly inside $apply for safe & efficient model mutations. This combination makes it easy to work with remote services in Angular.

Room for improvement

Trying to learn some new frameworks while preparing for Google I/O and helping developers to launch apps on our updated API all within a few weeks was a lot to take on. A few corners were cut and there are a few things I’d like to revisit when time permits:

  • Tests! AngularJS boasts testability as one of its key features and leverages dependency injection throughout to help keep things simple and testable. Since this was originally intended as a live demo instead of a reference app, I cut a few corners here. Yeah, I know better than that...
  • Rethink how ACE is used. In most cases it’s easy to figure out if something should be a controller, directive, filter, or service. But trying to pigeonhole libraries like ACE into one of those is daunting. Out of expediency, I chose to hide ACE behind a service, but it feels like it belongs in a directive. It would be nice to be able to declare in HTML:
    <editor content=”myModel.text”/>
    and have that sync with the model just like any other input in Angular. I started down that route, but correctly wiring up ACE to do that was more effort than it seemed worth at the time. This resulted in some other warts with how the app’s routes & views are structured.
  • Talking to the backend servers. Not so much an issue with Angular, but rather with a late decision to replace the DrEdit UI. The original goal was a separate app. Once we decided to build on the previous sample, I didn’t want to make unnecessary changes to the server side code that was already written. This led to implementing some of the new features in less than ideal ways. For example, the editor can not independently save metadata from the document content when the file is renamed or starred but the content left untouched. A minor inefficiency, but something that could have been done better.

I know I’ve only scratched the surface and have a lot more to learn. Even so, it was incredibly fun diving head first into AngularJS, and I highly recommend considering it if you’re dissatisfied with your current framework or just want to learn something new!



Steven Bazyl   profile | twitter | events

Steve is a Developer Advocate for Google Drive, Google Apps, and the Google Apps Marketplace. He enjoys helping developers find ways to integrate their apps and bring added value to users.

Read more »

Documents List API Best Practices Batching ACL entries

ACL (Access Control List) entries control who can access Google Docs resources. This allows more specific control over resource privacy or permissions.

Many types of applications need to grant document access for several users at once. As an example: when a new user is added to a project in the Manymoon project management application, every user on the project needs to be granted access to all attached Google docs. If there are 10 users on the project and 10 shared documents, this means the app would typically need to perform 100 HTTP requests -- a lot of overhead. With batching of ACL requests, the application can reduce the number of requests to one per document, resulting in a 10x savings.

Before Batching

A typical ACL entry for a single user is created by making an HTTP POST to the ACL link provided with each resource entry. The POST body looks something like this:

<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:gAcl=http://schemas.google.com/acl/2007>
<category scheme=http://schemas.google.com/g/2005#kind
term=http://schemas.google.com/acl/2007#accessRule/>
<gAcl:role value=writer/>
<gAcl:scope type=user value=new_writer@example.com/>
</entry>

To achieve the same thing using the Python client library, use the following code:

from gdata.acl.data import AclScope, AclRole
from gdata.docs.data import AclEntry

acl = AclEntry(
scope = AclScope(value=user@example.com, type=user),
role = AclRole(value=writer)
)

With Batching

Instead of submitting the requests separately, multiple ACL operations for a resource can be combined into a single batch request. This is done by POSTing a feed of ACL entries. Each ACL entry in the feed must have a special batch:operation element, describing the type of operation to perform on the ACL entry. Valid operations are query, insert, update, and delete.

<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:gAcl=http://schemas.google.com/acl/2007
xmlns:batch=http://schemas.google.com/gdata/batch>
<category scheme=http://schemas.google.com/g/2005#kind
term=http://schemas.google.com/acl/2007#accessRule/>
<entry>
<category scheme=http://schemas.google.com/g/2005#kind
term=http://schemas.google.com/acl/2007#accessRule/>
<gAcl:role value=reader/>
<gAcl:scope type=domain value=example.com/>
<batch:operation type=insert/>
</entry>
<entry>
<category scheme=http://schemas.google.com/g/2005#kind
term=http://schemas.google.com/acl/2007#accessRule/>
<id>https://docs.google.com/feeds/default/private/full/document%3Adocument_id/acl/user%3Aold_writer%40example.com</id>
<gAcl:role value=writer/>
<gAcl:scope type=user value=new_writer@example.com/>
<batch:operation type=update/>
</entry>
</feed>

The following code represents the same operation in the Python client library:

from gdata.data import BatchOperation
from gdata.acl.data import AclScope, AclRole
from gdata.docs.data import AclEntry

acl1 = AclEntry(
scope=AclScope(value=example.com, type=domain),
role=AclRole(value=reader),
batch_operation=BatchOperation(type=insert)
)

acl2 = client.get_acl_entry_by_self_link(
(https://docs.google.com/feeds/default/private/full/
document%3Adocument_id/acl/user%3Aold_writer%40example.com))
acl2.scope = AclScope(value=new_writer@example.com, type=user)
acl2.role = AclRole(value=writer)
acl2.batch_operation = BatchOperation(type=update)

entries = [acl1, acl2]

The feed of these entries can now be submitted together to apply to a resource:

results = client.batch_process_acl_entries(resource, entries)

The return value is an AclFeed, with a list of AclEntry elements for each operation, the status of which can be checked individually:

for result in results.entry:
print entry.title.text, entry.batch_status.code

The examples shown here are using the raw protocol or the Python client library. The Java client library also supports batch operations on ACL entries.

For more information on how to use batch operations when managing ACLs, see the Google Documents List API documentation, and the Google Data APIs batch protocol reference guide. You can also find assistance in the Google Documents List API forum.


Ali Afshar profile | twitter

Ali is a Developer Programs engineer at Google, working on Google Docs and the Shopping APIs which help shopping-based applications upload and search shopping content. As an eternal open source advocate, he contributes to a number of open source applications, and is the author of the PIDA Python IDE. Once an intensive care physician, he has a special interest in all aspects of technology for healthcare.

Read more »

Tuesday, March 10, 2015

Instant voting with Apps Script

From nations choosing presidents to offices selecting which coffee to brew, we often find ourselves involved in election systems designed to choose the best option. This spring my alma maters solar vehicle team, CalSol, needed to elect new leaders. Our previous system was painfully slow, involved "raising hands" in a room, and excluded any team members who could not attend a specific meeting. I set out to solve these problems and the result was an easy method for running fair elections in a matter of minutes.

I was able to build the system completely on Google products and technologies:

  • Google Forms: Allows members to submit their votes from anywhere.
  • Google Spreadsheets: Makes it easy to audit the votes and configure the system.
  • Google Apps Script: Simple way to access the results and determine the winner.

I used a lesser known voting system called instant-runoff voting (IRV), or the alternative vote, which asks voters to rank candidates rather than cast a single vote. These votes, along with a secret voting key which I provided to each member, are recorded with a Google Form that automatically populates a spreadsheet. The code in Apps Script looks through the spreadsheet to count the votes while ensuring that each voting key is only used once. The secret keys not only prevent voters from casting multiple votes, but they also allow voters to change their vote by submitting the form again.

Below is a simplified snippet of code that shows the general process used to calculate the winner.

/* Some code omitted for clarity */

/* candidates is a list of names (strings) */
var candidates = get_all_candidates(results_range);

/* votes is an object mapping candidate names -> number of votes */
var votes = get_votes(results_range, candidates, keys_range, valid_keys);

/* winner is candidate name (string) or null */
var winner = get_winner(votes, candidates);

while (winner == null) {
/* Modify candidates to only include remaining candidates */
get_remaining_candidates(votes, candidates);
if (candidates.length == 0) {
Browser.msgBox("Tie");
return;
}
votes = get_votes(results_range, candidates, keys_range, valid_keys);
winner = get_winner(votes, candidates);
}
Browser.msgBox("Winner: " + winner);

I learned that putting a little effort into Apps Script can make people happy and save a lot of time. The team feedback was outstanding. One CalSol member said the process was an "Excellent, clean, and professional voting process. This should become a standard [for the team]." I was elated when I was able to close the polls during a meeting and announce the winners of twelve independent elections in just a matter of minutes.

If you like, you can watch a video demonstrating how to create and run your own election using this script:

Try the script yourself to make sure your coffee preferences are heard!


Chris Cartland profile | GitHub

Chris is a Developer Programs Engineer based in Mountain View on the Google+ team. He previously worked on solar vehicles at UC Berkeley and wants developers to write software that makes our lives better. In his spare time he likes to play soccer and throw the ball in after doing a front handspring.

Read more »

Google Apps Marketplace We want your suggestions

The Google Apps Marketplace launched last month with over 50 integrated business applications. In less than 2 months, more than 1 million Google Apps users now have access to integrated cloud apps that their organization’s IT administrators have installed through the Google Apps Marketplace. More businesses are adding their applications to the Marketplace every week. Google Apps are used by more than 25 million users at over 2 million businesses, and growing very fast.

The Google Apps Marketplace is growing, and we want your suggestions on how to make it bigger and better. Here is your chance to submit your big ideas and small suggestions on Google Apps Marketplace and the APIs used to create installable apps. You can also see existing ideas and what others have to say. Vote up the ideas you like the most. You tell us whats important.

We have set up two Product Ideas sites; one for improvements to the Marketplace itself, and another for applications you would like to see available for sale in the Marketplace. There are already lots of ideas and over 300 votes. Take a look at the ideas and add yours to the list.

Thank you from the Google Apps Marketplace team.
Read more »

Retiring the Google Documents List API v3

With the arrival of the new Google Drive API v2, we are deprecating the Google Documents List API v3. We are confident that the Google Drive API covers all the functionality of the Documents List API, in addition to adding many improvements, including Drive UI Integration, a finer grained security model, and a better client library experience.

What does this mean for your app?

The Documents List API v3 will remain in action for more than a year, as per our deprecation policy, so there’s no rush, but we encourage you to migrate your code to the new platform. Documentation is available with samples in multiple languages and a migration guide outlining some of the major transition points.

If you have any questions or issues, please ask them on StackOverflow.com, where our team is waiting to hear from you.

Ali Afshar profile | twitter

Tech Lead, Google Drive Developer Relations. As an eternal open source advocate, he contributes to a number of open source applications, and is the author of the PIDA Python IDE. Once an intensive care physician, he has a special interest in all aspects of technology for healthcare

Read more »

Add missing keys to resource files resx language

If you work on .net and some multi-language application, sooner or later you find the beauty of resx files. Put tke keys there and call them by the language user has chosen (or set by the browser). Cool, indeed. But as time flies, these language files become ... well, quite big, not huge. And if you have some 6 languages, the management of those files is something you are affraid of.

Why? While you code your application, youre not in the mood of entering a new key to each and every language file. So you just put them in the default language file (language.resx). And as you code and code, there are several keys you put in.

And then deployment. But you need to enter those keys into other languages. Send them to translators, copy the translations back?

OK, enough said. Borring, not worth a developer. :-) So, the solution...

1. The translation tool in the application (website): ResXManager
2. The "administrational" tool that adds all the missing keys from one file (languageNew.resx) to all the other files (language.de.resx, language.whatever.resx)
3. Small function to translate via google (but consider this to be quite unusable currently since if you send some heavy html, it will give you back all sorts of funny things), thxs to Piyush:


public string TranslateText(string input, string languagePair, Encoding encoding)
    {
        string url = String.Format("http://www.google.com/translate_t?hl=en&ie=UTF8&text={0}&langpair={1}", input, languagePair);

        string result = String.Empty;
        try
        {
            using (WebClient webClient = new WebClient())
            {
                webClient.Encoding = encoding;
                result = webClient.DownloadString(url);
            }

            Match m = Regex.Match(result, "(?<=overflow:auto">)(.*?)(?=)");

            if (m.Success)
                result = m.Value;
        }
        catch { }
        return result;
    }


The ResxManager and administration is avaliable here. Cant really explain more currently. Check the files and if you dont get it, comment here. Will be glad to explain.
Read more »

Lots of Excitement about Google Apps at I O 2011

Hard to believe it’s been only two short weeks since Google I/O 2011! There was fantastic energy at the event, and developers had their choice of over 100+ sessions on topics ranging from Google Apps to Android to App Engine to HTML5 to Cloud Robotics.

Here are the highlights from the Google Apps track:

Sessions

In the Google Apps track, we had 8 sessions on a variety of topics of interest to Google Apps Marketplace developers, systems integrators and customers alike. All of the sessions are available in HD on YouTube and we’ve also posted many of the session slides and notes.

Google Apps Marketplace:

  • Launch and Grow your Business App on the Google Apps Marketplace provided an intro to the Apps Marketplace, but most of the session was third-party developers telling the story of their businesses, demoing their integrations and providing guidance for other developers looking for success on the Marketplace. Teaser: 30% free->paid conversion rates from GQueues on the Google Apps Marketplace.
  • Apps Marketplace: Best Practices and Integrations covered a wealth of best practices for business app development and Google Apps integrations based on experience working with hundreds of developers building applications for the Google Apps Marketplace.

Google Apps Script:

  • Enterprise Workflow with Apps Script showed how Google Apps Script can be used to build complex workflows using simple server-side JavaScript code. The speakers built on several examples for document publishing approval, showing lots of code for how it’s done.
  • Developing Apps, Add-Ins and More stepped through building Add-Ins with deep integration into the Google Apps UI and full applications. The team announced the Apps Script GUI Builder to drag and drop UI components and full Apps Script APIs for Gmail and Google Docs.

Application APIs:

  • Google Tasks API announced the brand-new API to interact with a user’s Google Tasks. Several third-party developers demonstrated how they integrated tasks with their project management and CRM apps.
  • Using the Google Docs APIs to Store All your Information in the Cloud gave a very brief overview of the Documents List API followed by a deep-dive into gcategorically, an App Engine + Python sample app for uploading documents to Google Docs. Best practices for developing integrations with Google Doc were also covered. This session is very useful for Apps Marketplace developers, especially because of the new ability to upload all file types to all types of Google accounts.

Solutions and Administration:

  • Developing Innovative Custom Business Solutions with Google Apps covered how web solution providers are driving us towards the goal of 100% web. Included many real-world examples from a variety of companies who are extending Google Apps using Apps Script, Google Sites, gadgets, Data APIs, App Engine, GWT and more.
  • Compliance and Security in the Cloud talked about the suite of APIs and tools available for Google Apps customers to handle policy compliance, audit, incident response and more. Very helpful session for IT administrators, CTOs and CIOs using Google Apps, with much of the session diving into several examples using real-world use cases.

Developer Sandbox

We had 24 fantastic companies in our Developer Sandbox this year, showcasing the applications they built for the Google Apps Marketplace and the services they provide Google Apps customers as system integrators or VARs. We were excited to see many of the companies talking about new integrations they have recently built with Google Apps.

Parties and Fun

The official After Hours event celebrated technical and artistic innovation and included robots, games and transforming vehicles in addition to a live performance from Jane’s Addiction. Many Google teams and companies attending I/O also threw plenty of great parties at nearby bars and restaurants.

Thanks to all the developers who attended Google I/O and made it such an enormous success. Our team loved the chance to chat with many of you and learn more about your businesses and technical challenges.

Hope to see you all at Google I/O 2012!

Want to weigh in on this topic? Discuss on Buzz



Ryan Boyd profile | twitter | events

Ryan is a Developer Advocate on the Google Apps Marketplace team, helping businesses build applications integrated into Google Apps. Wearing both engineering and business development hats, youll find Ryan writing code and helping businesses get to market with integrated features.

Read more »

Monday, March 9, 2015

Learn about Google Apps Script in NYC

Google Apps Script lets you automate and extend Google Apps. Using Apps Script, businesses can build efficient solutions to meet their requirements such as:
  • Gmail Snooze with Apps Script
  • Content Approval Workflow
  • Vacation calendar management
  • Helpdesk Workflow
  • Time Booking
Join us on August 18th, 2011 for the Google Apps Script Hackathon. If your organization uses Google Apps and you want to explore how you can use Google Apps Script to create custom functions or automate repetitive tasks, then this hackathon is a perfect opportunity to learn. Google engineers will be available to answer your questions and help you learn Apps Script throughout the day’s agenda. We’ll provide food, refreshments, and experts to help you learn to use Apps Script and write your own scripts. Just bring your laptop, ideas, and enthusiasm to complete the mix. We hope to see you there!

What: Apps Script Hackathon
Date: Thursday, August 18th, 2011
Time: 2pm to 7pm EDT
Where: 76 9th Avenue, New York, NY
Register: Space is limited, register here.

For those who cannot attend in person, we invite you to try out a number of self-paced tutorials on the Apps Script documentation site.



Saurabh Gupta profile | twitter | blog

Saurabh is a Developer Programs Engineer at Google. He works closely with Google Apps Script developers to help them extend Google Apps. Over the last 10 years, he has worked in the financial services industry in different roles. His current mission is to bring automation and collaboration to Google Apps users.

Read more »

Deprecating Tables and Records feeds of the Spreadsheets API

At Google, we value quality, effective developer products. APIs are something we develop and release often. In support of this, we offer many APIs in our Labs program that allows our users to test APIs in an experimental setting.

After more than two years in service, we have made the decision to deprecate the Table and Record feeds of the Google Spreadsheets API. Having thoroughly tested these feeds and received lots of your feedback, we feel that the functionality provided by these feeds is something much better satisfied by the List and Cell feeds in the API.

Our deprecation plan for these APIs will keep these feeds in service for an additional year from today’s date.

If you are a current user of the Table and Record feeds, we highly recommend that you take the time to migrate over to the List and Cell feeds. Since the List feed works very similarly to the Records feed, this should be a smooth process.

As always, if you have any questions, feel free to use the Spreadsheets API forum.

Want to weigh in on this topic? Discuss on Buzz

Read more »

Agile Adoption 3 Vital Behaviours


One of the books on my reading list this year was “Influencer: The Power to Change Anything” (Patterson, Grenny, Maxfield, McMillan, Switzler). As I read it, I was struck by how the ideas in the book can be helpful for guiding an agile adoption.

The book is split into two parts. The first section outlines how any change can be made inevitable by looking for the vital behaviours that will bring about the change. The second section outlines six different types of influence strategies that you must use in order to make those vital behaviours happen. In this post, I’ll just be talking about the first section on vital behaviours.

According to the authors, any change can be made inevitable if you can find the correct set of vital behaviours. For many common problems, these vital behaviours have already been discovered by various research teams. For example, the vital behaviours for losing weight and keeping it off were identified by a U.S. government research project: a) weigh yourself every day, b) eat breakfast every day, and c) exercise with home equipment. A strong marriage can be determined by looking for the following vital behaviours during arguments:  a) statements that communicate shared respect and purpose, and b) taking timeouts when required to halt emotional escalation. The best teachers a) reward positive actions often and b) alternate frequently between teaching and testing.

So what are the vital behaviours for agile adoption? First, let me suggest that agile adoption isn’t the goal at all – rather the goal that we are looking for is to have successful projects. Agile adoption may or may not be required to meet that goal. If then our goal is to have successful projects, has anyone done the research to find the vital behaviours that are part of all successful software projects? Indeed – Alistair Cockburn did significant research into this topic and found three common behaviours amongst all successful teams. He described his findings in a 2006 Agile Toolkit podcast where he said: (starting at about 3:25) “Those that were collocating face to face, short delivery cycles, access to customers were delivering. Those that were following some process very carefully were not delivering.” In an article where he describes his research methods and results he writes that a) they improved their communication by co-locating, b) had access to their customer and c) had short delivery cycles. He also commented in his article that “I ran the seemingly odd hypothesis that if you simply put four people in a roomwith whiteboards and computers, give them access to the users, and have them deliver running software every month or two, they would have a high likelihood of success in delivering useful, working software. Surprisingly, this hypothesis has not yet been broken." Reflecting on my own project history, I find that I agree with his hypothesis. You can read more about his research here. Notice by the way, that all 3 of these behaviours are about shortening the feedback loops.

If you look at Alistair’s work and writing on Crystal Clear, you’ll notice something interesting. These three behaviours are all in included in the 7 properties of Crystal Clear. However, of the 7, only 3 are listed as mandatory and one of the above was not included in the mandatory list. “Easy Access to Expert Users” was excluded (still on the list, but not mandatory) and replaced by “Reflective Improvement” despite his findings and hypothesis. I’ve asked Alistair about this and look forward to his answer – I’ll keep you posted.
Another interesting observation about “Easy Access to Expert Users” is that for external products with external customers, it would be difficult or impossible to have access to those users. It makes sense then that the Lean Startup movement is heavily focused on tools and techniques to find and measure feedback from your external users.

While these 3 vital behaviours may be the ‘key’ behaviours that will help your team be successful, they will also spawn other behaviours to improve your results. For example, in order to have short delivery cycles, you will need to deliver small increments of value which could lead your team towards the practice of user stories. In order to have short delivery cycles and not spend an inordinate amount of time doing manual regression testing for each delivery, your team will likely move towards automated testing. In order to have short delivery cycles and not spend an inordinate amount of time creating deployment packages, your team will likely move towards a continuous deployment practice.

In conclusion, if you are a manager, executive or coach wondering how you can make your teams more successful but have struggled with or without agile techniques, try encouraging and supporting these three vital behaviours as a starting point and then examine the results. Then, use something like reflection workshops to examine the results and start adding, deleting, or modifying practices over time to improve your results. Based on what we know about organizational change management, this iterative approach to process improvement has an increased chance of being successful. If the Influencer book is correct, (and there are lots of examples in the book to indicate it is) then these three behaviours should make a significant impact on your projects.

Read part II of this post to find six possible influence strategies to make these behaviours inevitable.
Read more »

Kicking Apps and Making Names

Way back in the dawn of time, before I joined Google — OK, fine, two months ago — I was a video-game designer. Occasionally, I had to come up with names for people or places. And Im no good at naming things.

So once, instead of manually naming hundreds of towns in a (fictitious) foreign country, I weaseled my way out of creativity by writing a ridiculous set of custom spreadsheet functions. My spreadsheet analyzed a list of real placenames from a similar country, then spit out plausible fake names with the same lexical structure.

It worked — but I was pushing spreadsheet functions so far that the “code” (if you can call it that) became difficult to maintain. At the same time, the reason I used a spreadsheet in the first place was so I could lean on the analytical power of pivot tables.

That’s what made Google Apps Script perfect for revamping the project. With Apps Script, I can still use pivot tables, then do the heavy lifting in JavaScript and package everything up as a tidy web app. I call it Name Generator … because I’m terrible at naming software, too.

Now, before you say, “There’s no way I’d call my daughter Harliance,” remember that the goal wasn’t to produce real names. The goal was to produce names that were good enough for a video game. Perhaps Harliance is a cyborg woman of negotiable virtue in dystopian future-America? You should probably pick your daughter’s name the old-fashioned way.

So let’s look at a few of the techniques that NameGen uses.

1. We start out in Google Sheets, first dropping a list of real names into column A, then slicing it into overlapping three-letter segments using the formula =MID($A2,COLUMN(B2)-1,3) (that’s the version of the formula you’d use in cell B2; from there, just copy and paste the formula across the rest of the sheet and the cell references will update accordingly). Here’s a sample of one of the spreadsheets so you can see how the data is set up.

2. We then create a pivot table for each column in that first sheet, just summarizing the column by COUNTA (the number of times each segment occurs). For example, since Lakisha, Nakia, and Nakisha (from our list of real names) share “aki” as letters 2 through 4, the pivot table for Segment 2 shows “aki: 3.”

The plan is that NameGen will randomly pick one of the starting three-letter segments, then look at the last two letters of its selection so that it can find an overlapping segment from the next column. The script then uses the pivot-table statistics to weight its selections toward more common segments. It continues until a segment ends in a blank. This diagram shows how it might build the name Calina:

3. This is where Apps Script takes over. Just once per source list of names, we run the utility function below (shown slightly simplified) to convert the spreadsheet data to a more useful format and store it in ScriptDb. The script can then pull the data from ScriptDb in about 0.5s, versus about 5s to read directly from the spreadsheet. Note that we’re using Script Properties to store the spreadsheet ID rather than cluttering up the code with extra variables.


function updateDb() {
var language = americanFemale;

// Look up the spreadsheet ID in Script Properties, then grab its sheets.
var ssId = ScriptProperties.getProperty(language);
var sheets = SpreadsheetApp.openById(ssId).getSheets();
var dictSize = sheets[0].getLastRow() - 1;
var segment = {};

// Transform each sheet into the segment object we want later.
for (var i = 0; i < sheets.length; i++) {

// Retrieve the list of real names (first loop) or a pivot table.
if (i === 0) {
segment.data = sheets[0].getRange(A:A).getValues();
} else {
segment.data = sheets[i].getDataRange().getValues();
}

// Store other properties so we can retrieve the right record later.
segment.index = i;
segment.language = language;
segment.size = dictSize;

// Save the object as a ScriptDb record, then start the loop again.
ScriptDb.getMyDb().save(segment);
}
}

4. Now, every time the app runs, it jumps straight to the generateNames() function shown below (again slightly simplified). After it queries the database, it’s straight JavaScript — but one Apps Script–specific trick you’ll notice is that we assemble the data into an array using segments[current.index] = current.data rather than segments.push(current.data). Because ScriptDb returns the records in an unpredictable order, we gave our objects an index property to store the correct order.


function generateNames(language, numNames) {

// Query the database to find all results for this language.
var results = ScriptDb.getMyDb().query({language: language});
var current = {};
var segments = [];

// Assemble the DB records into an array so we can pass it around.
while (results.hasNext()) {
current = results.next();
segments[current.index] = current.data;
}

var names = [];
var segment = ;

for (var i = 0; i < numNames; i++) {
var name = ;

// For each requested name, pick one segment, making
// sure it overlaps with the previous two letters.
for (var j = 1; j < segments.length; j++) {
segment = randomSegment(segments[j], name);
name = name.slice(0, name.length - 2);
name += segment;

// If the segment wasnt full length (end of a name), done!
if (segment.length < 3) {
break;
}
}

names.push(name);
}

return names;
}

I haven’t explained the randomSegment() function, but you can probably guess at how it works based on the description above. Still, if you want to dig in further, you can view the full source code here.

5. The only remaining step is to expose the results to the world through a web app. Apps Script provides several ways of doing this; I used Html Service, but didn’t require any of the advanced features. Here’s how little HTML we need to turn NameGen into a functional app:


<html>
<body>
<script>
function sendRequest() {
var language = document.getElementById(language).value;
var numNames = document.getElementById(numNames).value;
google.script.run.withSuccessHandler(updateField).
generateNames(language, numNames);
}

function updateField(names) {
var output = "";
for (var i = 0; i < names.length; i++) {
output += (names[i] + <br/>);
}
document.getElementById(resultsBox).innerHTML = output;
}
</script>
<select id="language">
<option value="americanFemale">American Females</option>
<option value="americanMale">American Males</option>
<option value="american">American Towns</option>
<option value="british">British Towns</option>
<option value="french">French Towns</option>
<option value="irish">Irish Towns</option>
<option value="italian">Italian Towns</option>
<option value="spanish">Spanish Towns</option>
</select>
<select id="numNames">
<option value=1>1</option>
<option value=10 selected>10</option>
<option value=100>100</option>
<option value=1000>1000</option>
</select>
<input id="generateButton" type="button"
value="Generate" onclick="sendRequest()">
<div id="resultsBox">
</div>
</body>
</html>

And presto chango, you have a web app that harnesses the tremendous power of Google’s infrastructure … to produce names that could only ever exist in a parallel universe. It’s like Adriano Celentano’s "Prisencolinensinainciusol" — a convincing rendition of an American pop song, unless you actually speak English, in which case it’s total gibberish.




Dan Lazin   profile | twitter

Dan is a technical writer on the Developer Relations team for Google Apps Script. Before joining Google, he worked as video-game designer and newspaper reporter. He has bicycled through 17 countries.

Read more »

Expensify Accelerates Sign ups with the Provisioning API

Editors Note: This post was written by Zhenya Grinshteyn and Tom Jacobs of Expensify. We invited Expensify to share their experience with the Google Apps Marketplace.

Expensify does expense reports that dont suck by importing expenses and receipts from your credit cards and mobile phones, submitting expense reports through email, and reimbursing online with QuickBooks and direct deposit.

The Foundation: Single Sign-On

We were really excited when Google approached us to be a launch partner for their new Google Apps Marketplace because tons of our customers use Google Apps -- including us! We have long wanted to put an Expenses link up there next to Mail and Documents, and now we had our chance.


To do that, we installed the JanRain PHP OpenID library with the Google Apps Discovery extension. We’d already implemented Gmail OpenID and ironed out the kinks related to having multiple logins to a single account, so implementing this was a very straightforward process.

Lessons Learned

We quickly learned that while single sign-on is awesome, there was a high drop-off rate among admins installing Expensify into their domain. Digging deeper we determined it was due to the setup process being split: part of the setup was done from within Google Apps, but the final part had to be completed by signing in to our site. Not only that, a major part of the setup process was laboriously entering their employee’s emails. We decided to address each in turn by creating a setup wizard and importing the domain’s email list. We approached this change in two major ways:

First, when the Google Apps admin installs the Expensify application, we created a custom configuration step that creates what we call an expense policy. This governs everything from who is part of the company, who can approve expenses, and ultimately who exports to QuickBooks to keep the general ledger in check. Previously this step had to be done after the application was already installed, usually when the admin first signed in. By making this step part of the install process, the entire setup felt much more intuitive and resulted in a higher completion rate.

Second, we used the Zend framework to connect to the Google Apps Provisioning API to fill the new expense policy with a list of all existing employees. This saved a ton of typing and resulted in a vast reduction in the time it took to deploy Expensify to the full company. With everything else in place, the code we used to do this looked something like this:
$oauthOptions = array(
requestScheme => Zend_Oauth::REQUEST_SCHEME_HEADER,
version => 1.0,
signatureMethod => HMAC-SHA1,
consumerKey => $CONSUMER_KEY,
consumerSecret => $CONSUMER_SECRET
);
$consumer = new Zend_Oauth_Consumer($oauthOptions);
$token = new Zend_Oauth_Token_Access();
$httpClient = $token->getHttpClient($oauthOptions);
$service = new Zend_Gdata_Gapps($httpClient, $domain );
$users = $service->retrieveAllUsers();
All of the users’ names and emails are presented in a table of employees that the person installing the app can use to set roles and quickly build an approval tree for all expenses.


Once the setup is completed, we automatically create accounts for all of the selected employees and send out a brief email with tips to get started.

Results: 3.5x more users sign up

Overall it was a fast and painless process, has increased the flow of high-quality leads, and has accelerated their rate of converting into real users. Domain admins now sign up 3.5x more users right away than they have been using the previous two-part setup! Feel free to install our app to see how the setup process works, and respond to this post with questions about your implementation -- well try to help out as best we can. And of course if youre still doing your expense reports the old sucky way, please come visit our website (Expensify.com) and wed be happy to help ease your pain. Thanks for reading, let me know if theres anything I can help clarify!

Want to weigh in on this topic? Discuss on Buzz

Read more »

Google Data Authentication Choices

Editors Note: Jeff Morgan is a Senior Technical Consultant at Appirio, a cloud solution provider which creates products and delivers services . He’s worked with many Google Data APIs, so we’re excited to publish his insights on the various authentication choices.

As developers using the Google Data APIs, one of the first challenges we tackle is learning and sorting through the Google Data authentication schemes. AuthSub, OAuth, ClientLogin, OpenID+OAuth, and so on. Perhaps you may be developing a Google App Engine web application for the first time and want access to a users Google Calendar. Maybe you are building a data processing application that requires access to a Google users data. If you are familiar with the Google Data APIs you likely know that there are many authentication options available depending on the API. So how do you decide? The best place to start is the Getting Started with Account Authorization guide. Also, the Authentication in Google Data Protocol page provides detail on the various authentication methods. This post provides references to many existing resources and some additional things to consider to help you decide which authentication method to use for your application.

Does your application need end user permission to access their Google data?

When developing web applications, developers are sometimes faced with deciding between AuthSub or OAuth. However, the first question should be, "Who will be granting permission to the users Google data?" If the end users are Google Apps users then most likely it will be an administrator granting access. Frequently developers ask the same question in another way, "Should I use 3-legged or 2-legged authentication?" Ideally, from a Google Apps user experience perspective, it is better to use 2-legged OAuth. This way the application is granted access to a users Google Apps data at the administrator level. The end user can start to use the application and the trust has already been established by an administrator. If you are developing a Marketplace application then it is very likely you will not need to engage in the 3-legged authentication dance.
However, if you are writing an application that is wide open to anyone with a Google account, let the 3-legged dance begin. Both AuthSub and OAuth for Web Applications are designed for this purpose. However, the behavior and look and feel for each is slightly different. Both ultimately allow the user to grant your application access to their data, but knowing the differences helps you make the best choice. Here is an article that covers the topic and should help you choose. It has color coded highlights that compare the two.

Some general rules follow when choosing an authentication method:
End UserAuthentication
Google User (regular)AuthSub or 3-Legged OAuth (3LO)
Googe Apps User (hosted)2-Legged OAuth (2LO)
No end user2LO or ClientLogin


Gadgets

Again there are different options for choosing Google Data authentication from a Gadget container. The first option to consider is OAuth Proxy for Gadgets. OAuth proxy is a 3-legged dance asking the end user for permission to access their data. Once access has been granted then the gadget developer can use the gadgets.io.makeRequest()method to make the Google Data API calls. Most likely you will want the JSON response from the feed so remember to add the ?alt=json URL parameter. For more information and code examples on OAuth Proxy see Writing OAuth Gadgets.

For Marketplace Gadgets another authentication option is available and uses OpenID. This option is used to authenticate the user and determine identity only and it does not provide authorization for API access. After the user is authenticated, server-to-server calls are used to make the requests, authorized via 2-legged OAuth and specifying the xoauth_requestor_id based on the authenticated user from OpenID. For more information on this approach see the Marketplace Best Practices page.


Secure Storage of Credentials

Adding layers of security is a common approach to to making data more secure. Google does provide various layers by providing different authentication and authorization methods. Registering web applications, supporting digital certificates, support for industry standards, (SAML, OAuth, OpenID) all help in providing security. However, one of the most common mistakes we can make is not taking care to protect important credentials. When working with Google Data ClientLogin and 2-legged OAuth, these credentials can be keys to the kingdom (e.g. administrator credentials or domain OAuth consumer secret) and therefore should be protected at all costs. Access to these credentials can potentially open the entire Google Apps domain data for the authorized services. This could have tremendous impact especially if you are maintaining 2-legged OAuth credentials for domains that have granted your application access, e.g. a Marketplace application. Therefore it is risky practice to embed them in source code or even a configuration file. Consider using an approach that allows you to enter credentials at runtime and store in memory or use your favorite method for secure storage of these important credentials.


Google Apps Marketplace

With the March announcement of the Google Apps Marketplace, the decision making process may have become a little easier. OpenID+OAuth and 2-Legged OAuth are the schemes that are supported and likely will be used if your Marketplace application needs access to Google Apps data; which is very likely. You’ll notice that the Marketplace has embraced the open standards of OpenID and OAuth. While AuthSub and ClientLogin are proprietary to Google, they will likely not be useful in your Marketplace application.


ClientLogin

If your application needs to create or make modifications to user accounts (using the Provisioning API) then your only current option is ClientLogin. But a common oversight is to not reuse the access token. Without proper reuse of this token, eventually your application will force the account into a CAPTCHA state which can easily be avoided if the access token is used for subsequent ClientLogin authentication requests. It is best to keep this token cached in memory and renew the token in some configured frequency/timeout.

Summary

This post covered some important considerations for selecting a Google Data authentication method for your application. If you are new to Google Data authentications and want to have a better overall understanding then start with the Getting Started with Account Authorization guide. No matter which approach you choose make sure that accessing users data is done is a secure user friendly way.

References

Google Data authentication is a vast topic. For your convenience here are a list of resources.

Google Data Authentication - Start Here
Getting Started with Account Authorization
Authentication in the Google Data Protocol
OAuth
OAuth in the Google Data Protocol Client Libraries
OAuth for Web Applications
OAuth for Installed Applications
OAuth API Reference
Using OAuth with the Google Data APIs
Google Data API Tips - OAuth
OAuth Playground
OAuth-enabled http test client: oacurl
Gadgets
Authentication for Gadgets
Writing OAuth Gadgets
Fetching Remote Content
Creating a Google Data Gadget
JavaScript client library API reference
Using JSON with Google Data APIs
OAuth Enabled Gadgets on OpenSocial enabled Social Networks
Registration
Registration for Web-Based Applications
OpenID
Federated Login Service for Google Apps
OpenID+OAuth
Sharing and previewing Google Docs in Socialwok: Google Data APIs
Step2 Code Project
OpenID OAuth Extension
ClientLogin
ClientLogin in the Google Data Protocol Client Libraries
ClientLogin for Installed Applications
Google Data API Blog - ClientLogin
AuthSub
AuthSub Authentication for Web Applications
Using AuthSub in the Google Data Protocol JavaScript Client Library
Google Data API Tips - AuthSub
Google I/O
OpenID-based single sign on and OAuth data access for Google Apps

Want to weigh in on this topic? Discuss on Buzz

Read more »