Spyridon Pikoulas

Reverse geocoding in Google Sheets™: latitude and longitude to address

Coordinates from a GPS log, a form or a phone are no use to someone reading a sheet. Google Sheets™ has no function that turns them into an address. Its Apps Script, though, includes Google’s geocoder, the service Google Maps™ uses. You can call it for free, without an API key, within a daily allowance: 1,000 lookups a day on a personal Google account, 10,000 on Google Workspace™. Below are two ways to use it, and an add-on.

Enter real numeric coordinates: latitude from -90 to 90 and longitude from -180 to 180, including the boundaries; 0 is valid. Use ordinary decimal text or numeric cells, rather than dates, TRUE/FALSE, hexadecimal text or decimal-comma text. Numeric cells displayed with a decimal comma in your spreadsheet’s locale are fine.

1. A formula: =ADDRESSPARTS(A2, B2)

Go to Extensions > Apps Script, replace everything in Code.gs with the code below, and save:

/** =ADDRESSPARTS(A2, B2): the address, postcode, city, region and country at a latitude and longitude. */
function ADDRESSPARTS(lat, lng) {
  if (lat === '' || lng === '') return [['', '', '', '', '']];
  var cache = CacheService.getScriptCache(), key = lat + ',' + lng;
  var hit = cache.get(key);
  if (hit) return JSON.parse(hit);
  var r = Maps.newGeocoder().reverseGeocode(lat, lng).results[0];
  var out = [r ? parts(r) : ['not found', '', '', '', '']];
  cache.put(key, JSON.stringify(out), 21600);
  return out;
}

/** A geocoder result as [address, postcode, city, region, country]. */
function parts(r) {
  function find(type) {
    var c = r.address_components.filter(function (c) { return c.types.indexOf(type) >= 0; })[0];
    return c ? c.long_name : '';
  }
  return [r.formatted_address, find('postal_code'), find('locality') || find('postal_town'),
    find('administrative_area_level_1'), find('country')];
}

With the latitude in A and the longitude in B, type =ADDRESSPARTS(A2, B2) in C2 and fill it down. It fills five cells to the right, so keep columns C to G empty. For example:

Latitude Longitude Address Postcode City Region Country
42.3601 -71.0942 77 Massachusetts Ave, Cambridge, MA 02139, USA 02139 Cambridge Massachusetts United States
48.8584 2.2945 Tour Eiffel, 5 Av. Anatole France, 75007 Paris, France 75007 Paris Île-de-France France
0 0 not found        

It needs no authorization. The cache keeps each answer for six hours, so the recalculations Sheets™ does now and then, for example when the file is opened, don’t spend the allowance again. For only the address, =INDEX(ADDRESSPARTS(A2, B2), 1, 1) gives one cell.

2. Fill the columns once, as plain values

For a long list, or addresses you want to keep, fill them once from a menu. Put the latitudes in column A and the longitudes in B under a header row, add this to the script (next to the code above, which it uses), and save:

function onOpen() {
  SpreadsheetApp.getUi().createMenu('Geocode')
    .addItem('Fill addresses', 'fillAddresses')
    .addToUi();
}

/** Latitude in A, longitude in B from row 2: fills C to G where C is empty. */
function fillAddresses() {
  var sheet = SpreadsheetApp.getActiveSheet();
  if (sheet.getLastRow() < 2) return;
  sheet.getRange('D:D').setNumberFormat('@');  // postcodes stay text, leading zeros and all
  var range = sheet.getRange(2, 1, sheet.getLastRow() - 1, 7);
  var rows = range.getValues();
  var geocoder = Maps.newGeocoder(), started = Date.now();
  try {
    rows.forEach(function (row) {
      if (row[0] === '' || row[1] === '' || row[2] !== '' || Date.now() - started > 5 * 60 * 1000) return;
      var r = geocoder.reverseGeocode(row[0], row[1]).results[0];
      var p = r ? parts(r) : ['not found', '', '', '', ''];
      for (var i = 0; i < 5; i++) row[2 + i] = p[i];
    });
  } finally {
    range.setValues(rows);  // what was done is kept, even if the daily quota runs out midway
  }
}

Reload the spreadsheet, choose Geocode > Fill addresses, and authorize the script the first time. It fills Address, Postcode, City, Region and Country in C to G.

Getting good results

3. GeoFill (free for 100 a day)

GeoFill is the add-on I make for this, if you’d rather not keep a script. Go to Extensions > GeoFill > Geocode addresses, choose “Coordinates to addresses”, pick the Latitude and Longitude columns, tick what you want, and click Geocode.

Watch the 90-second walkthrough: coordinates to addresses. It shows two public-place coordinate pairs and how to review the returned addresses and Match.

It has access only to the spreadsheet you open it in, not your other files.

For the other direction, addresses to coordinates, see Convert addresses to latitude and longitude in Google Sheets™.