What is Google Apps Script?

  • Javascript-based language for running code on Google's servers that interacts with the Google services you already use
  • Web-based development means you have access to your code anywhere you can access Google Docs
  • Don't need to download or install anything or run your own servers
  • Store web data in spreadsheets, send messages with Gmail, create calendar events,build maps and geocode addresses, import your site's Analytics data, crowdsource with Google forms, save files on Google Sites...
  • And you can share code and data with anyone with a Google account, with the permissions you want

Example: Weather Forecasts Over Time

Example: Weather Forecasts Over Time

Available free from Weather Underground as JSON

{"date":{
    "epoch":"1361242800",
    "pretty":"10:00 PM EST on February 18, 2013",
    ...
},
        "period":2,
        "high": {
        "fahrenheit":"57",
        "celsius":"14"
        },
        "low": {
        "fahrenheit":"37",
        "celsius":"3"
        },
        "conditions":"Rain Showers",

        ...
        

Example: Weather Forecasts Over Time

We want to automatically grab that data every morning and stick it in the spreadsheet here

Example: Weather Forecasts Over Time

Example: Weather Forecasts Over Time

function getTemp() {
  var url = 'http://api.wunderground.com/api/' + apikey + 
     '/forecast/q/KY/Louisville.json';
  var sheet = SpreadsheetApp.getActiveSheet();
  var rows = sheet.getDataRange();
  var numRows = rows.getNumRows();
  var response = UrlFetchApp.fetch(url);
  
  var contentText = response.getContentText();
  var forecast = Utilities.jsonParse(contentText);
  ...
  }
    
    

Example: Weather Forecasts Over Time

  var forecast = Utilities.jsonParse(contentText);
  var todaysForecast = forecast.forecast.simpleforecast.forecastday[0];
  var high = todaysForecast.high.fahrenheit;
  var low = todaysForecast.low.fahrenheit;
  var conditions = todaysForecast.conditions;  
  
    {... "forecast": {
        ... "simpleforecast": {
         "forecastday": [ {...
            "high": {
            "fahrenheit":"39",
            "celsius":"4"
            },
            "low": {
            "fahrenheit":"30",
            "celsius":"-1"
            },
            "conditions":"Partly Cloudy",
            "icon":"partlycloudy",
            ...
      }
    }
  

Example: Weather Forecasts Over Time

      // cDay = 0, cHigh = 1, cLow = 2, cConditions = 3,
      // cSparkline=4,nCols=5
      sheet.insertRowAfter(1);
      var range = sheet.getRange(2,1,1, nCols);
      var row = range.getValues()[0];
      row[cDay] = new Date ();
      row[cHigh] = high; row[cLow] = low;
      row[cConditions] = conditions;
      var nRows = numRows >= 10 ? 10 : numRows;
      row[cSparkline] = "=SPARKLINE(R[0]C[-3]:R[" + (nRows-1) + "]C[-3])";
      range.setValues([row]); 
    }
      
    

Example: Weather Forecasts Over Time

Example: Weather Forecasts Over Time

Example: Tracking Websites Over Time

Example: Tracking Websites Over Time

Example: Tracking Websites Over Time

        function processRow(rowValues) {  
  var url = rowValues[cURL];
  var name = rowValues[cName];
  var rowID = rowValues[cID];
  if (!url)
  {
    // Not much we can do here
    return rowValues;
  }
  var response = UrlFetchApp.fetch(url);
  var oldChecksum = rowValues[cChecksum];
  var contentText = response.getContentText(), content = response.getContent();
  var newChecksum = String(Utilities.computeDigest(
                     Utilities.DigestAlgorithm.MD5, contentText));


  

Example: Tracking Websites Over Time

    if (newChecksum != oldChecksum) {
    // File has changed
    var mirrorPageUrl = rowValues[cMirrorPage];
    var page;
    var contacts = rowValues[cContact];
    var baseSiteUrl = 'https://sites.google.com/site/smelendeznicarmirror/'; 
    // site to store mirrored content
    var site = SitesApp.getSiteByUrl(baseSiteUrl);
    if (!mirrorPageUrl) {
      // Need to make a mirror page
       page = site.createFileCabinetPage(name, rowID, "");
       rowValues[cMirrorPage] = mirrorPageUrl = page.getUrl();
    }
    else page = SitesApp.getPageByUrl(mirrorPageUrl);
    page.addHostedAttachment(Utilities.newBlob
        (content, "application/octet-stream", url + ' ' + today),  today); 
    // Add it to the site as an attachment
    rowValues[cChanged] = today;
    rowValues[cChecksum] = newChecksum;
    

    

Example: Tracking Websites Over Time

    if (contacts)
    {
      // Email the appropriate people
      GmailApp.sendEmail(contacts, "Change notification " + url, 
        "See the latest version at " + mirrorPageUrl);
    }
    

Example: Flickr API

Example: Flickr API

Manually maintained spreadsheet of images -- time-consuming

Example: Flickr API

A faster way -- use Flickr to store and resize the images and extract the geotag data

Example: Flickr API

Forward email submissions to Flickr, adding desired tags

Example: Flickr API

One sheet to configure, one to store output in spreadsheet here

Example: Flickr API

function load_config() {
  var config = {};
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Config");
  var rows = sheet.getDataRange();
  
  var numRows = rows.getNumRows();
  var values = rows.getValues();
  
  for (var i = 0; i<= numRows -1; i++) {
    config[values[i][0]] = values[i][1];
    
  }
 
  return config; 
}
        

Example: Flickr API

One sheet to configure, one to store output

Example: Flickr API

function onOpen() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Load New Images",
    functionName : "load_new_images"
  },
  {
    name : "Load All Images",
    functionName: "load_all_images",
    
  },
  {
    name : "Geocode Selected Addresses",
    functionName: "geocodeSelectedAddresses"
  }];
  sheet.addMenu("Image Menu", entries);
};
        
        

Example: Flickr API

 var config = load_config();
  
 var fetchurl = 
   'http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=' 
   + config.api_key +
 '&per_page=500&format=json&extras=description,geo,owner_name,date_taken,'
   + 'date_upload,url_t,url_s,url_m,url_l&tags=' 
   + config.tags + 
  '&user_id=' + config.account_id;
 
 var lastdate = ScriptProperties.getProperty("lastdate");
 if (lastdate)
 {
   fetchurl += '&min_upload_date=' +  (lastdate + 1);
 }
 var response = UrlFetchApp.fetch(fetchurl);     
        

Example: Flickr API

function geocodeSelectedAddresses(e) {
  var cAddress = 8, selected = SpreadsheetApp.getActiveRange();
  if (selected.getNumColumns() != 1 || selected.getColumn() != cAddress + 1)
  {
    // Only works if you select addresses 
    SpreadsheetApp.getActiveSpreadsheet().toast("Please select addresses to geocode.")
    return;
  }
  var rows = selected.getValues(); 
  var nrows = rows.length, outrows = [];
  var outrange = selected.offset(0, -2, nrows, 2);
  for (var row = 0; row < nrows; row++)
  {
    var address = rows[row][0];
    var result = geocodeAddress(address);
    outrows.push([result.lat, result.lng]); 
  }
  outrange.setValues(outrows);
}
        

Getting the Data Back Out

Set the sharing settings the way you want

Getting the Data Back Out

Getting the Data Back Out