Friday, March 13, 2015

Change in Apps Scripts DocsListDialog

DocsListDialog is a widget used by only a small fraction of Apps Script projects to provide a Google Drive "file open" dialog in a UI service user interface. In almost all cases, using Google Picker in HTML service is preferable and more secure.

Before September 30, 2014, we require scripts using DocsListDialog to make a small update to improve security.

Specifically, if you use DocsListDialog, youll need to start calling a new method, setOAuthToken(oAuthToken) before you call showDocsPicker(). The new method sets an OAuth 2.0 token to use when fetching data for the dialog, on behalf of the user whose content should be shown.

So long as the app isnt a web app set to execute as "me" (the developer), you can get the necessary OAuth 2.0 token by calling ScriptApp.getOAuthToken(). The example below shows how to convert an old DocsListDialog implementation to the new model.


Old example

function showDialog() {
var app = UiApp.createApplication();

app.createDocsListDialog()
.addCloseHandler(serverHandler)
.addSelectionHandler(serverHandler)
.showDocsPicker();

SpreadsheetApp.getUi()
.showModalDialog(app, );
}

New example

function showDialog() {
var app = UiApp.createApplication();

app.createDocsListDialog()
.addCloseHandler(serverHandler)
.addSelectionHandler(serverHandler)
.setOAuthToken(ScriptApp.getOAuthToken())
.showDocsPicker();

SpreadsheetApp.getUi()
.showModalDialog(app, );
}

To ensure your script continues to work properly, be sure to make this change before September 30.

Posted by Dan Lazin, Googler

Read more »

Thursday, March 12, 2015

Iterative Development and User Story Slicing

You may have seen Jeff Pattons slides showing iterative vs. incremental development using the Mona Lisa as an example (slides are here, page 80, 81). Iterative development suggests that you build each feature from the ground up increasing the subjective quality of each feature with each user story that you implement. This method is important for allowing you and your team to narrow in on the final solution rather than designing and understanding it all up front. It also allows you to deliver a full featured application earlier and to use methods like trim the tail to optimize your available budget vs the value that the project is delivering.

Here is a quick discussion on Iterative vs Incremental development:

The diagram to the left shows how a project could be completed using Iterative or Incremental development. In both cases, iterations were used to develop the list of features, but in iterative development we build each feature up a slice at a time rather than a feature at a time. Some of the advantages of iterative development are that it:
  • Allows you to validate your architecture and solution early
  • Allows users to see and test the whole application early
  • Minimizes the affects of change to a feature
  • Ensures important stories are built first
  • Elicits improved feedback on the whole application early
  • Allows you to deliver your application early
  • Discourages "gold plating"
  • It partners nicely with user story mapping (turn the diagram upside down and you have your story map)
Some of the disadvantages are:
  • Your code and design has to be change tolerant
  • You have to be proficient at slicing your user stories
  • You wont know the final solution at the beginning of the project
User story slicing is an important technique in iterative development, but what does this look like in practice? Using Jeffs Mona Lisa pictures as a pattern, Ive created a few images that show how a feature like "Send Email" could be completed iteratively.

The first story slice is simply a form with little or no validation with text boxes To, Subject and Body with Send and Cancel buttons. When the user fills in the text boxes and clicks Send an e-mail is sent provided the e-mail addresses entered are correct. But, this e-mail has no extra features like support for HTML formats, RTF, attachments, e-mail priorities, etc. Once this story is implemented, the team will implement similar slices of each feature for Read Email, Create Appointment, View Calendar, Create Task, Edit Task, Create Contact, Edit Contact, etc in order to create a minimalist working model of the whole application.



The next slices of this particular feature would be to implement stories such as implementing Carbon Copy (CC) and taking e-mail addresses from your contact list. You can also see that the form has changed slightly - the Cancel button has been removed and the Send button has been moved to the top.



As we continue to iterate through this feature by adding story slices, the form takes additional shape, adding tool bars and tool bar items. At this point, the application may be finished enough to release to production and start earning revenue for the organization while we continue to add new features and use that revenue to help fund the remainder of the project.



A further release with more story slices implemented:



The final release:



Iterative development is an important tool in your agile toolbox to help your teams deliver early and adapt to change while keeping the projects end goals in mind. User story slicing is one of the important techniques you can use to help make this happen.

Want to receive future blog posts in your inbox? Enter your email address here.
Read more »

The Hottest Script in Hollywood

In just a few hours at the recent Apps Script hackathon in Los Angeles, we saw attendees build everything from website monitoring to room booking to financial tracking apps. For those of you who couldn’t make it, attendees were given a brief introduction to Apps Script and a few hours to let their imaginations run wild. Apps Script’s ease of use enabled them to quickly create fully functioning, useful apps. Here are a few interesting things we saw from local developers:


Website Monitor by Eduardo Arino de la Rubina

These days, small businesses are quickly increasing their online presence; a website outage during a critical period can be devastating to a mom-and-pop shop. Eduardo realized that existing network-monitoring solutions require a significant investment in technology and infrastructure that is beyond the reach of many small-business users. Using Apps Script’s UrlFetch and Spreadsheet services, he was able to quickly create a website monitor packaged in an easy-to-use spreadsheet that, given a list of URLs, tries to fetch each one and records the latency and content length.

The code is available here.


Get A Room by Danny Favela

Get A Room allows users to book meeting rooms by taking advantage of Apps Script’s tight integration with Google Calendar and events. The app, built entirely on a Chromebook utilizing Apps Scripts cloud friendliness, displays building floorplans with buttons that users can click to book a room. In response to a booking request, the app fetches the room’s calendar and creates a new event. It also updates the UI by replacing the floor plan with a modified image to show the newly booked room. Here is a snippet of the booking code:


// Click handler for the interaction to book a room
function bookBoardroomHandler(e) {
var app = UiApp.getActiveApplication();

// Perform the calendar-booking operations
bookBoardroom();

// Swap the images as visual confirmation
app.remove(app.getElementById(imageDefaultLayout));
app.add(app.getElementById(imageBoardroom));

app.close();
return app;
}

function bookBoardroom(e) {
var calendarBoardroom = CalendarApp.getCalendarsByName("Boardroom");
calendarBoardroom[0].createEventFromDescription("Boardroom Meeting");
}


Stock Info by Matt Kaufman

Matt decided to build a web service that provides information about publicly traded stocks. The app’s backend consists of a spreadsheet with stock symbols of interest. Using Apps Script’s FinanceService, Matt loops through the spreadsheet on a timed trigger and appends the latest stock information for each symbol. He then uses HtmlService to create a web app that outputs an XML page of the stock info based on a symbol parameter in the URL. Here’s a picture of his script in action:

These are just some examples of how quickly useful apps can be created with Apps Script. Thanks to all the attendees for coming out! If you couldn’t make it to the hackathon, check out these tutorials to see how you can get started making great apps.


Kalyan Reddy profile | Stack Overflow

Kalyan is a Developer Programs Engineer on the Google Apps Script team based in NYC. He is committed to increasing developer productivity by helping them fully utilize the power of Apps Script. In his free time, he enjoys participating in the Maker community and hacking together robots.

Read more »

Analytics reporting with Google Apps Script at the UK Cabinet Office

Editor’s Note: Guest author Ashraf Chohan works at the Government Digital Service (GDS), part of the UK Cabinet Office. -- Arun Nagarajan

Recently, when we were preparing the launch of GOV.UK, my team was tasked with creating a series of high-level metrics reports which could be quickly compiled and presented to managers without technical or analytical backgrounds. These reports would be sent daily to ministers and senior civil servants of several government departments, with the data customised for each department.

We decided to use Adobe InDesign to manage the visual appearance of the reports. InDesign’s data-merge functionality, which can automatically import external data into the layout, made it easy to create custom departmental reports. The challenge was to automate the data collection using the Google Analytics API, then organize the data in an appropriate format for InDesign’s importer.

In a previous post on this blog, Nick Mihailovski introduced a tool which allows automation of Google Analytics Reporting using Google Apps Script. This seemed an ideal solution because the team only had basic developer knowledge, much of the data we needed was not accessible from the Google Analytics UI, and some of the data required specific formatting prior to being exported.

We started by building the core reports in a Google spreadsheet that pulls in all of the required raw data. Because we wanted to create daily reports, the start and end dates for our queries referenced a cell which defaulted to yesterday’s date [=(TODAY())-1].

These queries were dynamically fed into the Google Analytics API through Apps Script:


// All variables read from each of the “query” cells
var optArgs = {
dimensions: dimensions,
sort: sort
segment: segment
filters: filters,
start-index: 1,
max-results: 250
};

// Make a request to the API.
var results = Analytics.Data.Ga.get(
tableId, // Table id (format ga:xxxxxx).
startDate, // Start-date (format yyyy-MM-dd).
endDate, // End-date (format yyyy-MM-dd).
endDate, // Comma seperated list of metrics.
optArgs);

Next, we created additional worksheets that referenced the raw data so that we could apply the first stage of formatting. This is where storing the data in a spreadsheet really helps, as data formatting is not really possible in the Google Analytics UI.

For example, the final report had a 47-character limit for page titles, so we restricted the cells in the spreadsheet to 44 characters and automatically truncated long URLs by appending “...”.

Once the initial formatting was complete, we used formulas to copy the data into a summary sheet specially laid out so it could be exported as a CSV file that merges seamlessly into InDesign.

Below is an example of how a report looks on publication. Nearly everything on the page was extracted from the API tool, including the department name and the day number. Because most of the data was automated, it required minimal effort on our part to assemble these reports each morning.

We discovered that an added bonus of pulling data into a Google spreadsheet was that it also allowed us to publish the data to a Google site. This helped us display data to stakeholders without adding lots of users to our Google Analytics account.

The tools let us present Google Analytics data in deeper, more creative ways. That’s really important as we share information with more and more non-technical people, whether they’re inside GDS or beyond.


Ashraf Chohan

Guest author Ashraf Chohan works at the Government Digital Service (GDS), part of the UK Cabinet Office. GDS’s role is to deliver digital transformation of government services. Ashraf is a Product Analyst for GOV.UK, a new site for public services and information.

Read more »

Introducing the next version of the Google Calendar API!

The Google Calendar API is one of Google’s most used APIs. Today, we’re rolling out a new version of the API that will give developers even more reasons to use it. Version three of the Google Calendar API provides several improvements over previous versions of the API:

  • Lightweight resource representation in JSON
  • Consistent and comprehensive reference documentation
  • Improved support for recurring events
  • Ability to manipulate default reminders on calendars
  • Access to the new UI and event colors

Developers familiar with the Google Tasks API will feel right at home with Calendar API v3, as it uses similar syntax and conventions, as well as the same base client libraries. These Google-supported client libraries, based on discovery, are available in many languages with:

  • Straightforward development for mobile using the client libraries for Java and Objective-C
  • Native support for OAuth 2.0
  • Native partial and PATCH support

If you’re new to the Google Calendar API, getting started is easy. Check out the Getting Started Guide, which will walk you through the basic concepts of Google Calendar, the API, and authorization. Once you’re ready to start coding, the Using the API page will explain how to download and use the client libraries in several languages.

If you’d like to try out some queries before you start coding, check out the APIs Explorer and try out some example queries with the new API.

Developers already using older versions of the API can refer to our Migration Guide. This interactive guide offers side-by-side examples of the API in v2 and v3 flavors across both the protocol and multiple languages. Simply hover over the code in v2 (or v3) and see the equivalent in the other version.

With our announcement of v3 of the API, we’re also announcing the deprecation of the previous versions (v1 and v2). The older versions enter into a three year deprecation period, beginning today, and will be turned off on November 17, 2014.

We’d love to hear your feedback on the Google Calendar API v3. Please feel free to reach out to us in the Google Calendar API forum with any questions or comments you have. We’ll also be hosting live Office Hours (via Google+ Hangout) on 11/30 from 8am-8:45am EST to discuss the new API. We hope to see you then!


Dan Holevoet   profile

Dan joined the Google Developer Relations team in 2007. When not playing Starcraft, he works on Google Apps, with a focus on the Calendar and Contacts APIs. Hes previously worked on iGoogle, OpenSocial, Gmail contextual gadgets, and the Google Apps Marketplace.


Alain Vongsouvanh   profile

Alain is a Developer Programs Engineer for Google Apps with a focus on Google Calendar and Google Contacts. Before Google, he graduated with his Masters in Computer Science from EPITA, France.

Read more »

Wednesday, March 11, 2015

Agile is simple but not easy advice for agile beginners


As we prepared for yesterdays user story mapping session at Agile Winnipeg, Jon Labun and I reflected on agile stories that weve been a part of or heard about. A common theme emerged - agile is simple but not easy. We touched on this in the presentation and argued that user story mapping should be a central part of your agile practices in order to make many things easier. Many agile stories start off well with organizations and teams wanting to give agile a try, but then fail to put in the investment to understand what being agile is about. The teams assume that agile is simple but lack the knowledge of how all the pieces fit together and end up running a project that is just an agile facade - agile words on the surface, but traditional methods (or no methods) underneath. It isnt the fault of agile that the projects end up in trouble or fail. 

Some common problems:
  • Unending backlogs that are hard to visualize and prioritize
  • Definitions of done that dont include testing & deployment
  • 20 page requirements documents for one user story
  • Incorrectly assuming that agile means no planning
  • Planning at the task level vs. the story level
  • Testing after development is done rather than throughout the project.
  • Out of control scope
  • Out of control change management
  • Never ending projects
  • Significant quality issues
  • etc
If you are beginning your agile journey then welcome to the club! It can be a lot of fun and very rewarding. But please, please, dont start without gaining some knowledge first. The agile community has a good head start on you and can help you through some initial hurdles to make your simple journey a little easier. Please do read some articles and books, listen to podcasts etc, but your best learning will come from interactions and conversations with others who are further along the journey. Here are two important pieces of advice for you:

1) Find your local user group and support it with your attendance. Bring real questions and ask the group to help you find some answers. If you are in Winnipeg, visit www.agilewinnipeg.com. If you are elsewhere, consult the Agile Alliances list of local user groups.

2) Attend conferences. Many of the successful agile teams I know point to ideas and practices they learned at conferences as crucial steps in their organizations agile journey. But dont expect to only attend sessions - plan to interact with the audience and speakers during the sessions and also over lunch, dinner, drinks, or even indoor sky diving. There are several great conferences you can attend, but Ill highlight one in my region - PrairieDeveloper Conference in Calgary, Alberta from March 12-15. Regardless of your location, this is a cant miss conference with 80 sessions + full day workshops. See you there?

To paraphrase Mike Cohn, the agile community has helped me up my game - now up yours.

* P.S. Prairie Developer Conference is more than just agile of course, bring your whole team, your IT pros, your managers, etc.

Read more »

Managing Projects with Gantt Charts using Google Apps Script

Editor’s Note: Guest author Ronald Dahrs runs Forscale, an IT and project management company based in the Netherlands. -- Arun Nagarajan

Google Apps is well-suited for project management because it’s a cloud-based productivity suite that helps you and your team connect and get work done from anywhere on any device. Using Google Apps Script, we can push the capabilities even further to create advanced scheduling and management tools. A common tool in project management circles is the Gantt chart: a schedule of the tasks in the project and how they relate to each other over time.

The spreadsheet that generated that Gantt chart is available in the template gallery today. In this post, we’ll explore the basics of how the template works and explain a few of the Apps Script techniques that transform Google Sheets into such a powerful project management tool.

When you open the template, you’ll see stubs for each type of task, but the screenshot above shows an example of a slightly larger project plan — in fact, the same data used to generate the Gantt chart below.

The template’s sophisticated formulas rely on the structure of the table to enable schedule awareness and task dependencies. However, we still ensure that the user can rename, rearrange, or add columns by using a hidden header to identify each column. This diagram demonstrates the spreadsheet’s structure:

In Apps Script, we use the spreadsheet’s onEdit() event to monitor user interaction with the schedule portion of the spreadsheet and update the Gantt chart accordingly. The powerful JavaScript language does all the required summary calculations based on the provided dates and completion percentages.

We have also used Apps Script’s addMenu() method to build a custom menu that calls row-oriented functions like indenting tasks to get a so-called Work Breakdown Structure with summary tasks. If you just want to see an overview, the custom menu allows you to collapse tasks, which we accomplished through the hideRows() method.

For changes that do not trigger an onEdit() event (for example, clearing a row), the user can use the menu’s Refresh command to recalculate the schedule.

The template stores user preferences as Script Properties and offers an interactive user interface built in UiApp to change those settings:

Finally, to render the Gantt chart, we use cell background colors to visually group and highlight the appropriate cells. This creates the effect of a continuous calendar with clearly visible start and finish dates for each task.

var ganttColors = ganttRange.getBackgroundColors();
var ganttValues = ganttRange.getValues();

// update Gantt colors and values
ganttRange.setBackgroundColors(ganttColors).setValues(ganttValues);

Ronald Dahrs

Ronald combines his knowledge of project management and software solutions at his company, Forscale. He believes Google Apps is an excellent platform for online project management. He uses Google Apps Script to integrate the services to manage a wide range of projects.

Read more »

Google Spreadsheets and Forms send new records via email

Classic scenario:

1. You create a form to collect data (event sign-in form).
2. To make it simple for everyone, you create it in Google docs (so you can set who has access - from anywhere; simple download,... hey its just collecting data, right?)
3. Theres a person in the team that uses Excel and Excel only. And email.
4. So this person wants to get on email each new record that is added to that spreadheet.
5. You send link. But he doesnt want that. He wants each new record on email. Data, not link.

So what do you do? Google for solutions. But wait, almost every solution is about "set notification rules" on document. Thats cool. But you get only link via email.

Well, I did some further research and came quite close to solution:

http://www.labnol.org/software/mail-merge-with-gmail/13289/

So, if I can send email to everyone, why not send it just to 1 person? Well, as it turns out, it works. Ive just modified the script a little bit. :-)

First, go to Script Editor on your spreadsheet.





Then, copy and modify bellow script in.


function onFormSubmit (){
sendEmail();
}


function sendEmail() {


var mySheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var LastRow = mySheet.getLastRow();
var emailYourName = "My name";
var emailReplyTo = "my.email@OurDomain.com";
var emailTo = "thePerson@theDomain.org";
var emailSubject = "Your data. Pointless. But here you have it.";


//variables: sure, you can have your own, logic is obvious. :-)


var CasPrijave = mySheet.getDataRange().getCell(LastRow, 1).getValue();
var ImeInPriimek = mySheet.getDataRange().getCell(LastRow, 2).getValue();
var Organizacija = mySheet.getDataRange().getCell(LastRow, 3).getValue();
var Ulica = mySheet.getDataRange().getCell(LastRow, 4).getValue();
var Postna = mySheet.getDataRange().getCell(LastRow, 5).getValue();
var Kraj = mySheet.getDataRange().getCell(LastRow, 6).getValue();
var Telefon = mySheet.getDataRange().getCell(LastRow, 7).getValue();
var Email = mySheet.getDataRange().getCell(LastRow, 8).getValue();
var Soglasje = mySheet.getDataRange().getCell(LastRow, 9).getValue();
var Jezik = mySheet.getDataRange().getCell(LastRow, 10).getValue();


//Email: bla, bla and variables.


var emailBody = "Bla, bla... Data:


";
emailBody += "ÄŚas prijave: " + CasPrijave + "
";
emailBody += "Ime in priimek: " + ImeInPriimek + "
";
emailBody += "Organizacija: " + Organizacija + "
";
emailBody += "Ulica: " + Ulica + "
";
emailBody += "Poštna številka: " + Postna + "
";
emailBody += "Kraj: " + Kraj + "
";
emailBody += "Telefon: " + Telefon + "
";
emailBody += "Email: " + Email + "
";
emailBody += "Soglasje: " + Soglasje + "
";
emailBody += "Jezik: " + Jezik + "
";


//SendEmail


var advancedArgs = {htmlBody:emailBody, name:emailYourName, replyTo:emailReplyTo};
MailApp.sendEmail(emailTo, emailSubject, emailBody, advancedArgs);


//Interesting, it needs to flush. Sure, pointless work that had to be done.


SpreadsheetApp.flush();
}​


In the end, dont forget to set triggers (onFormSubmit)









Read more »

Create a custom CRM dashboard using Google Apps Script

Editors note: This is a guest post by Alex Steshenko. Alex is a core software engineer for Solve360, a highly-rated CRM in the Google Apps Marketplace which was recently chosen as a Staff Pick. Solve360 offers many points of useful integration with Google Apps. Today, in contrast to the conventional Data API integrations, Alex will showcase how he extended Solve360 using Google Apps Script. --- Ryan Boyd

Choosing Google Apps Script

Solve360 CRM integrates with Google services to provide a two-way contact & calendar sync, email sync and a comprehensive Gmail contextual gadget. We use the standard Google Data APIs. However, some of our use cases required us to use Google documents and spreadsheets. Enter Apps Script!. What brought our attention to Google Apps Script was that it allows you to run your application code right within the Google Apps platform itself, where documents can be manipulated using a wide range of native Google Apps Script functions, changing the perspective.

Our first experience with Google Apps Script was writing a "Contact Us" form. We decided to use the power and flexibility of Apps Script again to generate different kinds of reports.

Generating Solve360 Reports using Apps Script

Google Spreadsheets can produce rich reports leveraging features such as filters, pivot tables, built-in functions and charts. But where’s the data to report on? Using Google Apps Script, users can integrate Google Spreadsheets with a valuable source of data - the Solve360 CRM - completing the solution.

Solve360 Google Apps Reporting script lets users configure the reporting criteria while pulling reports into a Google Spreadsheet.

Heres a video demonstrating a real use case for Solve360 Reporting:

Designing Solve360 Reporting using Apps Script

User meet “Script”

For this script, we realized, simply providing spreadsheet functions would not be good enough. We needed a user interface to let users configure their account details and define what kind of data to fetch from the Solve360 CRM. Google Apps Script’s Ui Services came in handy. For instance, here is the function responsible for showing the “Solve360 account info” dialog:

/*
* Creates new UI application and opens setting window
*/
function settingsUi() {
var app = UiApp.createApplication();
app.setTitle(Solve360 account info)
.setWidth(260)
.setHeight(205);

var absolutePanel = app.createAbsolutePanel();

absolutePanel.add(authenticationPanel_(app));

app.add(absolutePanel);
SpreadsheetApp.getActiveSpreadsheet().show(app);
}

Working with Solve360’s API

Solve360 CRM has an external API available so the system can be integrated with custom business applications and processes. Reporting script use case is a good example of what it can be used for.

One of the first tricks learned was creating our own Google Apps-like “service” to encapsulate all those functions responsible for interacting with Solve360 CRM’s API. What is the most interesting is that this service’s code isn’t a part of the distributed Google Apps script. Instead the library is loaded from within the script itself directly from our servers. Why? Let’s say we found a bug or added new functions - if we had many copies of the service we would need to update them all, somehow notifying our clients, and so on. With one source, there’s no such problem. You may think of it as a way to distribute a Google Apps Script solution, or, in our case, a part of the solution. The service is called Solve360Service and its usage looks like this:

var contact = Solve360Service.addContact(contactData);

There were two problems with getting such an external service to work: Google Apps Script permissions restrictions and actually including it in the script.

The issue with permissions is that the Google Apps Script environment can’t see which Google Apps Script services are used inside the external service - that’s why it doesn’t ask you to grant special permissions for them. To force the authorization request for those permissions we added this to the onInstall function (called once when script is added to the spreadsheet):

function onInstall() {
// to get parseJS permissions
Xml.parseJS([solve360, 1]);

// to get base64Encode permissions
Utilities.base64Encode(solve360);
// ...
}

Here is the solution we used to load our centralized code into the script:

eval(UrlFetchApp.fetch("https://secure.solve360.com/gadgets/resources/js/Solve360Service.js").getContentText());

The Solve360Service is loaded from a single source - no copy-paste. All the functions for accessing the Solve360 API aka “the plumbing” are abstracted and hidden in inside this service, while the essentials of the reports script itself can be modified and tweaked to a particular client’s case. Inside of Solve360Service we use UrlFetchApp:

/**
* Request to the Solve360 API server
* data should be an Array in Short Hand notation
*/
request : function(uri, restVerb, data) {
if (this._credentials == null) {
throw new Error(Solve360 credentials are not set);
}

if (typeof(data) != undefined) {
if (restVerb.toLowerCase() == get) {
var parameters = [];
for each(var parameter in data) {
parameters.push(encodeURIComponent(parameter[0]) + = + encodeURIComponent(parameter[1]));
}
uri += ? + parameters.join(&);
data = ;
} else {
data.unshift(request);
data = Xml.parseJS(data).toXmlString();
}
} else {
data = ;
}

var options = {
"contentType" : "application/xml",
"method" : restVerb.toLowerCase(),
"payload" : data,
"headers" : {"Authorization" : "Basic " + this._credentials}
};
return Xml.parse(UrlFetchApp.fetch(this._url + uri, options).getContentText()).getElement();
}

As the result is always XML, in order to remove any extra work we call Xml.parse() right inside the request function and always return a XmlElement so you can iterate through it, access nodes and attributes. Here is a simplified version of how we load some items when building a report:

/*
* Builds a search config from user preferences and loads a slice of data from Solve360
* To configure how many items should be loaded at a time, change ITEMS_LOAD_REQUEST_LIMIT constant
*/
function retrieveItems_(parameter, offset) {
initSolve360Service_();
// ...
var searchParameters = [
[layout, 1],
[sortdir, ASC],
[sortfield, name],
[start, + offset],
[limit, + ITEMS_LOAD_REQUEST_LIMIT],
[filtermode, filtermode],
[filtervalue, filtervalue],
[searchmode, searchmode],
[searchvalue, searchvalue],
[special, special],
[categories, 1]
];
if (parameter.showAllFieldsCheckbox != true && fields.length > 0) {
searchParameters.push([fieldslist, fields.join(,)]);
}
// ...
var items = Solve360Service.searchProjectBlogs(searchParameters);
// ...
return items;
}

To simplify the usage of the service we added another function which initializes the service object, named Solve360Service:

/*
* Loads external Solve360Service
* For the service functions available refer to the source code here:
* https://secure.solve360.com/gadgets/resources/js/Solve360Service.js
*/
var Solve360Service = null;
function initSolve360Service_() {
if (Solve360Service == null) {
eval(UrlFetchApp.fetch("https://secure.solve360.com/gadgets/resources/js/Solve360Service.js").getContentText());
var user = UserProperties.getProperty(USERPROPERTY_USER);
var token = UserProperties.getProperty(USERPROPERTY_TOKEN);
if (user == null || user.length == 0 || token == null || token.length == 0) {
throw new Error(Use Solve360 spreadsheet menu to set email and token first);
}
Solve360Service.setCredentials(user, token);
}
}

As you can see, it uses the email/token pair previously saved in the “Solve360 Account Info” dialog or signals an error if the credentials were not yet saved.

Conclusion

There are many use cases where you can apply the Google Apps Script. The fact that you can work and implement solutions right from “inside” one of the greatest and most universal web applications available is amazing.

You can integrate your own software with Google Docs or even learn from us and build a reporting script for any other system accessible online. Try to look at solving business tasks from a different perspective, from the Google Apps point of view. We encourage it!

The code of the new script is available for use and study here:
https://secure.solve360.com/docs/google-apps-reports.js.

Alex Steshenko profile | twitter | blog

Alex Steshenko is a core software engineer for Solve360, a CRM application on the Google Apps Marketplace.

Read more »

Tuesday, March 10, 2015

Allowing the user to select Google Drive files from your application

If your application needs a way to let users easily choose a file from their Drive, this is for you.

Users can browse and select files from their Drive file list using the Google Picker API. The Google Picker API provides a user interface containing a list of all the users files in Google Drive.

Since the user interface is generated by the Picker API, there is very little effort in adding the Picker to an existing site. This article will show how to use the picker for your application, and discuss some of the configuration options.

First create a view on the data describing the type of Picker that we will be using. In this case, we’ll use google.picker.ViewId.DOCS. For more types of Picker, see the documentation.


 
var view = new google.picker.View(google.picker.ViewId.DOCS);
 

You can set the MIME types to filter the list of files. This allows you to specify your application’s specific file types to display to the user.


 
view.setMimeTypes("text/plain,text/html");
 

Use a PickerBuilder to set the required configuration parameters for your Picker.


 
var picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.setAppId("your app id")
.addView(view)
.setTitle("Select a Text File")
.setCallback(pickerCallback).build();
 

Once configured, the picker can be popped up to the user as often as you like, using


 
picker.setVisible(true)
 

When a user selects a file with the Picker, the callback set in setCallback is called with the data from the dialog. Pass this callback as the action to perform when a user selects a file in the Picker.


 
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
alert(The user selected: + fileId);
}
}
 

Check the data’s action, in this case google.picker.action.PICKED, and if it is appropriate, access the file ID as the the first element of the docs attribute.

Here are some additional tips on customizing your Picker.

  • You can allow the user to select multiple files. There will be more than one element in the data’s docs array, each representing a selected file.

     
    var picker = new google.picker.PickerBuilder()
    .enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
     
  • You can hide the navigation bar.

     
    var picker = new google.picker.PickerBuilder()
    .enableFeature(google.picker.Feature.NAV_HIDDEN)
     

For a complete example, including how to load the Picker library, please visit our the Drive SDK documentation. Also, see the Picker API documentation for more information.



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 »

Agility in Winnipeg

Yesterday I presented at sdec09 (http://www.sdec09.com/) in Winnipeg. My two presentations were at the opposite ends of the Overview/Detail spectrum. The first presentation was an introduction to Agile and Lean using a Lego project to demonstrate the usefulness of the various agile practices as compared to waterfall. The second presentation was a hands-on Planning Poker exercise (one of many agile practices). The day was fantastic and we (as a team) received a lot of questions ranging from specific questions on agile practices to how do I start using agile at my company.

In this blog, I will try to capture discussions about agile that are happening in Winnipeg and elsewhere. I hope you find it useful.
Read more »

From a need to a startup thanks to a Google hackathon

Editor’s Note: Guest author Arnaud Breton is a co-founder of UniShared — Nicolas Garnier

A few weeks ago, Clément and I started to take online courses (based on videos), mainly on Coursera, edX (the MIT-Harvard venture), and Udacity, the biggest online course providers.

Right from the start, we found that it was really painful to take digital notes while watching the video lectures: we had to switch between multiple windows, struggling to interact with them (no shortcuts to play/pause, etc) and no ways of matching the notes to videos... Finally we ended up taking notes with the old fashioned and archaic pens & papers.

After giving it a thought, we were convinced that we could make this much better. We both live in Mountain View, fifteen minutes away from the Google HQ, where a Google Drive hackathon was taking place so we decided to take this opportunity to find and build a solution to our problem. And we came up with the idea of a simple Google Drive app, which would embed both the video lectures and the notes, in the same window, letting us leverage all the shortcuts. Additionally, it would enable us to synchronize the notes with the videos, to be able to smoothly go to the related part of the videos while studying our notes. During the two days - and two nights - we developed that missing app, helped by the amazing Googlers from the Drive team and meeting other amazing people who came to also give birth to their ideas or to help us.

As a tech guy, it was a new exciting challenge to build this app, especially in such a short time. Fortunately, leveraging Google robust and powerful infrastructure and frameworks made it possible. It seemed obvious for us to leverage the Google Drive and Youtube APIs, to host our app on Google App Engine and to build it with the amazing AngularJS.

At the end of the hackathon, we managed to get a viable app, enabling students to create, save and synchronize their notes and videos. We were even rewarded by the Drive team who gave us a prize for our efforts!

VideoNot.es was born!


A few hours later, we started to spread the word about our new app and were convinced that it could be as useful for other students as it was for us. Immediately, hundreds of students started to use it, giving us useful feedback on what mattered the most to them. Based on their feedback, we continued to improve our app, with the number of users increasing. Today, one month after the hackathon, more than 300 VideoNotes are created daily all around the world, and the number continues to grow day after day!

We also got featured on The Next Web describing VideoNot.es as “a really useful tool to make, store and share notes about online videos as you watch them”

So, what’s next for us?
Obviously, continuing to improve the app based on feedback is our top priority.

Also, we have discovered new use-cases where VideoNot.es can be useful. For example journalists contacted us to tell us that they use it to write articles based on interview records. But also people in charge of the transcription of videos are also very excited about VideoNot.es.


It got us more convinced than ever that note-taking can be drastically improved, especially by adapting it to its learning context. We want to go even further. Bringing back social interactions in online classrooms, letting students easily share their notes, again leveraging Google Drive was the first step. Adding real-time collaboration and Q&A features is the second step and we will definitely take advantage of the Google Drive Realtime API for this.

Thanks a lot to the Drive team who organized this hackathon to give our idea a try through their amazing tools! And this is just the beginning of the adventure, that started from a problem we faced, whose solution has been found at the Google hackathon, and which is just starting to reach its potential.

Arnaud Breton profile

Arnaud Breton is passionate about the impact that technologies have on the world.  He is the co-founder and CTO of UniShared / VideoNot.es.

Read more »

Integrating with Google Apps using Gmail contextual gadgets

At this week’s Campfire One event, we launched the new Google Apps Marketplace, making it easier for you to create applications that integrate deeply with Google Apps and sell them to the more than 2 million businesses and 25 million people who use Google Apps.

In addition to the many integration points currently available for Google Apps, like the Google Data APIs, we announced that we will soon open Gmail contextual gadgets as a new extension point for developers. These gadgets can smartly draw information from the web and let users perform relevant actions based on the content of an email message, all without leaving the Gmail inbox. For instance, contextual gadgets currently available in Gmail can detect links in emails to show previews of documents, videos, photos, and more, right inside the messages.

For businesses, Gmail contextual gadgets can boost employee productivity by complementing email in a context-specific and actionable way. Appirio, a cloud solution provider, provided a demonstration of the potential of Gmail contextual gadgets and other experimental features with their new product PS Connect:



Appirio PS Connect shows how Gmail contextual gadgets can draw data from different web applications into relevant email messages, enabling users to make faster and more informed business decisions as they go through their inbox.

Soon we’ll be opening Gmail contextual gadgets as an extension for trusted testing by developers. If you have a good idea for this type of gadget today, please fill out this form. And for those of you who will be attending Google I/O in May, be sure to check out our session on building Gmail contextual gadgets.

Read more »

Finding Success on the Google Apps Marketplace

Editor’s note: This is a guest post by Cameron Henneke. Cameron is the founder and principal engineer of GQueues, a task management app on the Google Apps Marketplace. Cameron tells the story of his application and provides some tips for developers considering integrating with Google Apps and launching on the Marketplace -- Ryan Boyd

Google recently announced that over 4 million businesses now run on Google Apps, continuing its growth as enterprise software that focuses on collaboration. This of course is great news for Google Apps developers, since this means there are 4 million potential customers on the Google Apps Marketplace looking for complimentary tools to enhance their productivity. As you know, listing an app requires just a few quick steps, and the Marketplace targets a growing audience of customers ready to purchase additional solutions.

So what kind of success might you see on the Marketplace and how can you maximize revenue? As the founder of GQueues, an online task manager, I have listed the app on the Marketplace since its launch in March 2010. Over the past year and half, I have found the Marketplace to be my most successful channel, and have discovered a few tips along the way that proved key to this success.

Solve a Real Problem

Though this seems obvious, this first point is critical: make sure your app solves a real problem. This means you’ve identified actual people and businesses that have this problem and are actively looking for a solution. Perhaps they have already tried other tools or cobbled something together on their own. For example, I’ve verified Google Apps users are looking for an intuitive way to organize their work and manage tasks with others. GQueues fills this need as a full-featured task manager that allows users to assign tasks, share lists, set reminders, create tasks from email and tag work for easy filtering. Google Apps users come to the Marketplace with a variety of needs, make sure your app addresses at least one of them.

Create Several Points of Integration

As you solve a customer’s problem, make sure you integrate with their existing tools. For Marketplace customers, this means adding as many integration points with Google products as possible. This is important for several reasons.

First, it’s great for the user and facilitates adoption. If your service works seamlessly with other products they are already familiar with, they don’t have to spend time learning something new. For instance, GQueues has two-way syncing with Google Calendar. Since users already know how to drag events to new dates in Calendar, dragging GQueues tasks around the calendar is quite intuitive.

Secondly, more integration directly helps your app’s listing in the Marketplace. Each listing has a set of icons representing product integrations. GQueues integrates with Calendar, Mail, Contacts and Google Talk, which indicates to a customer that using this tool will allow their users to work more efficiently. Plus, customers can search based on integration points, so the more you have, the broader your presence in the Marketplace.

Lastly, integrating with existing products speeds development. Utilizing Google APIs allows you to innovate faster and respond to your customers growing needs. GQueues uses the XMPP service of Google App Engine, which eliminated the need to build a separate chat backend and makes it easy for users to add tasks by chatting a message from anywhere.

Engage Your Customers

Once you’ve listed your deeply integrated app that solves a real problem on the Marketplace, be sure to engage with your customers. The Marketplace allows users to rate your app and leave verified reviews, which not only impact the app’s listing position, but greatly influence potential customers’ willingness to test it out. I manage the GQueues Marketplace listing with a two-fold approach:

  1. Encourage happy customers to leave a review after a successful support interaction
  2. Reach out to users leaving negative reviews to address their specific issue and understand better how the app can be improved.

These actions are quite simple, but immensely effect your app’s presence in the Marketplace.

Marketplace Impact

Though each app is unique, I’ve found that following the tips mentioned above have helped the Google Apps Marketplace become GQueues’ top revenue channel.

GQueues is based on a freemium model, and the average conversion rate for a typical freemium product is 3-5%. Looking at all the regular channels, GQueues has a 6% average conversion rate from free users to paid subscribers - slightly higher than expected. However, the GQueues users from the Marketplace convert at an astonishing rate of 30%.

The Marketplace claims to target an audience ready to buy, and the data really backs this up.

Not only does the Marketplace have a substantially higher conversion rate, but it also drives a considerable amount of traffic. Looking at the data over the same period, 27% of all new GQueues users were acquired via the Marketplace.

Combining the acquisition rate with the conversion rate shows that the Marketplace is actually responsible for 63% of all paid GQueues users.

As Google Apps continues to grow worldwide, the need for deeply integrated, complimentary business tools will also expand. Based on my experience with GQueues, I strongly recommend the Google Apps Marketplace as a rewarding channel for apps that integrate with Google Apps.





Cameron Henneke  profile

Cameron Henneke is the Founder and Principal Engineer of GQueues. He is based in Chicago and loves Python and JavaScript equally. While not coding or answering support emails, he enjoys playing the piano, backpacking, and cheering on the Bulls.

Read more »