Google Maps distance function for Excel

I’ve been writing a few bits of code lately which have required using Google tools. I thought I’d write up some notes here for my information than anything else but may come in handy for others too. This post is a nifty tool for tracking the distance travelled by building materials from source to site. Used in conjunction with the carbon factors per tonne km from Defra, this allows a decent estimate for the transport stage of a lifecycle carbon footprint assessment.
The custom function for Excel works by entering two place names – or postcodes – and finding the shortest route between them using Gmaps route planner. I’ve called the UDF G_DISTANCE and the syntax for using it is =G_DISTANCE(Origin, Destination). It returns a value of the distance between the two locations in miles kilometres. If any kind of error occurs then the function returns 0.

This table shows the various ways you can use the function. You can also mix and match the types of input parameter you use. For example you may the site location precisely – either by latitude and longitude or postcode, but only know the city or even the country of origin of the materials. That’s fine – the function should still give you the right answer, or at worst return zero.

Two note of warning:
1) The Gmaps terms of service state that you are only allowed to use the API when displaying a map, so using this without doing so is at your own risk (hence the map above…).
2) Gmaps will generally give you a road-based route which may not be the most appropriate. For example cork from Portugal would probably be shipped rather than delivered all the way by HGV. If anyone has a better function for these cases please get in touch.

Function G_DISTANCE(Origin As String, Destination As String) As Double
' Requires a reference to Microsoft XML, v6.0
' Draws on the stackoverflow answer at bit.ly/parseXML
Dim myRequest As XMLHTTP60
Dim myDomDoc As DOMDocument60
Dim distanceNode As IXMLDOMNode
    G_DISTANCE = 0
    ' Check and clean inputs
    On Error GoTo exitRoute
    Origin = Replace(Origin, " ", "%20")
    Destination = Replace(Destination, " ", "%20")
    ' Read the XML data from the Google Maps API
    Set myRequest = New XMLHTTP60
    myRequest.Open "GET", "http://maps.googleapis.com/maps/api/directions/xml?origin=" _
        & Origin & "&destination=" & Destination & "&sensor=false", False
    myRequest.send
    ' Make the XML readable usign XPath
    Set myDomDoc = New DOMDocument60
    myDomDoc.LoadXML myRequest.responseText
    ' Get the distance node value
    Set distanceNode = myDomDoc.SelectSingleNode("//leg/distance/value")
    If Not distanceNode Is Nothing Then G_DISTANCE = distanceNode.Text / 1000
exitRoute:
    ' Tidy up
    Set distanceNode = Nothing
    Set myDomDoc = Nothing
    Set myRequest = Nothing
End Function

As ever, you need to install this as a code module in the workbook you want to use it in. It also requires that you set a reference to Microsoft XML, v6.0 (Tools > References > Microsoft XML, v6.0 ).

65 Responses to Google Maps distance function for Excel

  1. Nickos Dimoglou says:

    Hi Jamie,
    thanks for sharing.
    any chance you could send me an excel with this macro working :) )
    Thx in advance

  2. Nickos Dimoglou says:

    Thx for hepling first of all
    The link however doesn’t seem to work . I get “Internet Explorer cannot display the webpage” or “The address was not found…”

  3. Nickos Dimoglou says:

    not the link you have just sent but the link in page
    http://oco-carbon.com/2012/03/29/google-maps-and-excel-download/

    thx

  4. Nickos Dimoglou says:

    Hi again,
    It works fine now. Really cool :)
    Have you got any similar excel for distance calculation which is what I am basically looking for?
    I am trying using the code you have provided above… but seems my programming is really limited…
    Thx

  5. Gabriel says:

    Good Afternoon!
    Your code is helping me a lot!
    I’m sorry for the english using google translator

    Would like to know how to check the distances Rapidas fastest route

    Thank you and congratulations

    [Edited to improve on Google's translation.]

    • Jamie Bull says:

      This post has a Gmaps journey duration function for Excel written in answer to this comment.

      • Liam says:

        Hi that function looks great!

        However i am unable to get it working on my machine. Excel comes up with error “Compile Error: user defined type not defined”….is this something to do with
        the 2nd line of your code ‘ Requires a reference to Microsoft XML, v6.0….I’m not sure i have done this?

        I am looking for something that will enable me to write origin postcode in column A and destination postcodes in column B. Then have the distance or travel time in column C

        Many thanks

        Liam

  6. Adam says:

    Great function! How would I adjust this function to display distance in miles, rather than kilometers?

    • Jamie Bull says:

      Thanks for that question. It made me notice a mistake in the post where I said it returns the result in miles where I should have said it returns in kilometres.

      To make it give you a result in miles you need to divide the result by 1.61, either in the cell where you’re doing the calculation or in the VBA code itself. To do it in the code, change the last line before the exitRoute section from “If Not distanceNode Is Nothing Then G_DISTANCE = distanceNode.Text / 1000″ to “If Not distanceNode Is Nothing Then G_DISTANCE = distanceNode.Text / 1000 / 1.61″

      Hope that helps.

      • Kirill says:

        There is an original Google parameter for unit system

        units=metric (default) returns distances in kilometers and meters.
        units=imperial returns distances in miles and feet.

        I tried to add it to your code, but it didn’t work. I am not an expert in VB, so I think it was my mistake:

        myRequest.Open “GET”, “http://maps.googleapis.com/maps/api/directions/xml?origin=” _
        & Origin & “&destination=” & Destination & “&units=imperial&sensor=false”, False

        It works fine in a browser, but in Excel it still brings kilometers only. For now I’ll use your simple remedy by dividing to 1.61, but it doesn’t seem right.

        Anyway, thanks a lot for sharing your wisdom – it is very helpful!

  7. Gabriel Lawrence says:

    Hi Jamie,

    Thanks for this tutorial, great feature.

    I have filled out a long list of from and to addresses, it works fine and pops up with the KM distance. However, if I save the list and go back into it, the distance cells do not update to the correct amount, it just stays 0. Is there a way to have the whole sheet refresh? Currently, I have to press F2 and enter repeatedly throughout all the distance cells to get them to update.

    Thanks,

    Gabe

  8. JY says:

    Hi, i have been using this method to get the distance between location from Google as well. My target is to have a matrix that display the distance between 11 cities. This will give excel 121 distance to extract from google in total.

    everything goes well except that whenever i refresh the data, i always have cells that appear as 0 instead of the distance. i have to press F2 individually on these cells before the correct distance appear. Do you know why? Thanks!

    • Jamie Bull says:

      It could be a few things. The function returns 0 if any error occurs, which could be if the location doesn’t exist, Google can’t find a route, you’re over the limit of queries for the day, etc. But the most likely reason is that you’re querying too fast. There are two ways to fix this. The easy way is to put a delay in between calls using something like this Sleep() function. Put the line Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) at the top of your module, add in the line Sleep(200) somewhere in the G_DISTANCE function and the code will pause for 0.2 seconds between queries, enough to stop Google thinking you’re a robot.

      The alternative is to cache the results somewhere as a temp file but that’s a bit more involved.

  9. JY says:

    I think that solves the problem! Thank you!

    • JY says:

      Hi, I got another query. Should i want excel to only extract and display the data from google maps only after I press a button, How should I do it? I do not want it to automatically refresh itself everytime. It is taking too much time.

      • Jamie Bull says:

        Either set Excel’s calculation mode to manual then use f9 when you want to recalculate, or alternatively wrap the G_DISTANCE() function up in a macro that writes to your output cells rather than using it as an in-cell function. You could also take a look at caching the results. It’s much faster than querying Google after the first time.

  10. Bart says:

    Wonderfull!

    I guess I can use the same code for the time to travel (in stead of the kilometers).
    How can I get this info ?

  11. Chris says:

    Hey, Ive been using this script successfully – however – is it possible to get it to return the shortest distance from point A to B rather than the quickest?

    • Jamie Bull says:

      You are limited to what Google provides so there’s no way to specifically request shortest distance. You just get the response from Google “best” route algorithm. It’s a bit of a hack but you could ask for the walking directions rather than driving which is generally shorter but may not actually be a driveable route.

  12. Thomas says:

    Hey !

    I came up with pretty much the same code, though I like yours better. However… It worked fine yesterday but I did not save the data it returned. I queried above a thousand distances (postal code to postal code).

    When I started it again this morning, it will only send back 0′s. Which I assume is because I reached the limit of queries for a day. Hopefully, it’s a limit per 24h and I’ll be able to run it again tomorrow or later today. And I already included a pause of 1 sec between each request, so… It’s pretty frustrating. Just wanted to let everybody know it might happen if you query too many distances at once…

    • Jamie Bull says:

      One suggestion that I’ve used in a pinch is to hide behind a VPN. In my case it was as easy as logging on to a client’s VPN but you could use something like Hotspot Shield – or even a friendly neighbour’s WiFi. The important thing is to present a different IP.

      For a better solution I’d recommend caching results. Have a look at some of the other posts on this site for instructions on doing that.

      • Thomas says:

        Not too sure what you mean by caching the results ? I assume it will only help getting the results faster ?…

        • Jamie Bull says:

          I mean saving the XML file to your temporary files as something like Environ("temp") & "\" & Origin & "_" & Destination & "_dist.xml". Then before you query Google, check if you already have that file in the cache. In part it helps with speed of results, but it also means that you aren’t adding to your total number of queries by making the same request over and over.

  13. Thomas says:

    FYI, it’s working again. I guess there must be a limit per 24h.

  14. Jorge says:

    Hi Jamie, I’m trying to measure between 2 waypoints

    S25 04 42.9 W57 16 17.0
    S25 05 12.6 W57 17 20.4

    the excel aplication returns 2,387 meters, but in google maps gives an exact 2 Kms

    Please help me solve this issue…

    Thanks in advance.

    • Jamie Bull says:

      I’m not entirely sure. It seems to be some sort of rounding error. Are you sure your starting points are exactly on the road? All I can think of is that the two methods may use a slightly different algorithm in deciding where to start the journey from if the start or end point is not exactly on a road. One thing I noticed while looking in to this is that the Google location parameters only got to 5 places after the decimal point. Perhaps that’s introducing the rounding error. Your best bet is probably to ask Google though. I just provide a link to their API and don’t have any insight into what goes on at their end.

      A few figures to check on:

      Your start point
      S25 04 42.9, W57 16 17.0
      Start point when entered in Google Maps
      S25 04 43.1, W57 16 16.7
      Start point via G_DISTANCE
      S25 04 37.7, W57 16 5.7

      Your end point
      S25 05 12.6, W57 17 20.4
      End point when entered in Google Maps
      S25 05 12.8, W57 17 20.2
      End point via G_DISTANCE
      S25 05 13.4, W57 17 21.3

  15. Jorge says:

    Jamie, thanks for your prompt answer. I already open a issue in

    https://developers.google.com/maps/documentation/webservices/forum?hl=es.

    But they say they will check it before open it for discussions.

    Regarding the waypoints. Yes, they starts and ends on the road.

    I don’t quite understand the “A few figures to check on”. Are you refering at the rounding issue???.

    I’ve try them all and they all gave the same result… 2.387…

    Jorge.

    • Jamie Bull says:

      Those figures are what your waypoint addresses come back as (after converting from the rounded decimal latitude/longitude) from either entering directly onto Google Maps, or when it’s entered into the Google Directions API. The fact that the Directions figure is not the same as the other two makes me think that Google is rounding off the precision when you use the API. I’ll be interested to see the response to your issue.

  16. Jorge says:

    Jamie, once again, thanks for your prompt answer!. I think I know what is going on, and I hope you help me correct it.

    If you put these values in the G_LATLNG,

    WP1 S25 07 25.9 W57 20 22.1
    WP2 S25 07 02.4 W57 19 15.1

    returns this:

    WP1 -25.1238745,-57.3396070
    WP2 -25.1162286,-57.3175897

    If you put this in maps.google.com, it returns the same distance as the Excel_Gmaps .

    • Jamie Bull says:

      This is a link to the raw XML and you can see the latitude and longitude are rounded in there. It’s definitely a problem at Google’s end to do with the level of precision of their results via the API.

  17. Jorge says:

    Jamie, I’ll wait for the forum response!.

    Thanks

    Jorge

  18. Jorge says:

    as I told you before… when y open the issue i got a this message:

    ” they will check it before open it for discussions”.

    I just opened another one in the geocoding api forum… With the following text

    Hi, when I try to calculate distance between 2 GPS waipoints the geodecoding api translates this coordinates

    WP1: S25 07 25.9 W57 20 22.1 to -25.1238745,-57.3396070
    WP2: S25 07 02.4 W57 19 15.1 to -25.1162286,-57.3175897

    using this coordinates in the distance api brings a distance of 2374 mts.

    the right result should be

    WP1: S25 07 25.9 W57 20 22.1 to -25.123861, 57.339472
    WP2: S25 07 02.4 W57 19 15.1 to -25.117333, 57.320861

    • Jamie Bull says:

      I see. Well it might be worth asking on Stack Overflow too if no luck on those Google forums. There’s as good a chance of a response on there as anywhere.

  19. Jorge says:

    and the distance is 2010 mts.

  20. Jorge says:

    Ok… I will open it there too…

    Thanks!

  21. Jas says:

    This is a great help! I only have one issue. When I am attempting to use the G_Distance formula, it does not work to find the distance from the address I input to a list of ZIP codes that begin with the number “0″. Is there a way to make it work? All other ZIP distances are located from the address I input if they do not begin with a “0″. Help?

    • Jamie Bull says:

      From a little bit of testing it seems to work if you force the ZIP code to be read as text. To do that in Excel you just enter a single quote before the number. For example if you enter 01002 (Amhurst, MA) in a cell then normally Excel will see that as a number and convert it to just 1002. If you enter it as ’01002 then Excel displays it as 01002 and G_DISTANCE reads it just fine.

  22. Fernando Soares says:

    Hey! Congratulations for your job, it is amazing! How can I see the map with the route instead of just the city map when I’m working with Excel_GMaps?

    Best Regards,

    Fernando

  23. Vic says:

    Hello Jamie!

    I need to create a simple formula in Excel that returns the distance between 2 Zip Codes:

    Column 1 Zip Code 1
    Column 2 Zip Code 2
    Column 3 Distance (Km or miles)

    I think this coul be possible but I dont know how, I dont have Long and Lat data and I dont have an Addresses… only Zip Codes!

    Can you help me with this?

    • Jamie Bull says:

      Hi Vic. The G_DISTANCE() function should work with zip codes. If it doesn’t you could try making sure it gets read as a location by appending “USA”, so instead of passing in say “90210″, have “90210, USA”.

  24. JL says:

    Great to share this! Thanks!

  25. Hamish Brown says:

    Modified your code with a quick hack that made it find the distance between two postcodes in Australia (just switch “UK” with “Australia” to make it work in the UK). Thanks for providing the code as, with the modifications below, it has saved me a lot of time at work!

    Function G_DISTANCE(Origin As Long, Destination As Long) As Double
    ‘ Requires a reference to Microsoft XML, v6.0
    ‘ Draws on the stackoverflow answer at bit.ly/parseXML
    Dim myRequest As XMLHTTP60
    Dim myDomDoc As DOMDocument60
    Dim distanceNode As IXMLDOMNode
    G_DISTANCE = 0
    On Error GoTo exitRoute
    ‘ Read the XML data from the Google Maps API
    Set myRequest = New XMLHTTP60
    myRequest.Open “GET”, “http://maps.googleapis.com/maps/api/directions/xml?origin=VIC,%20″ _
    & Origin & “%20Australia&destination=VIC,%20″ & Destination & “%20Australia&sensor=false”, False
    myRequest.send
    ‘ Make the XML readable usign XPath
    Set myDomDoc = New DOMDocument60
    myDomDoc.LoadXML myRequest.responseText
    ‘ Get the distance node value
    Set distanceNode = myDomDoc.SelectSingleNode(“//leg/distance/value”)
    If Not distanceNode Is Nothing Then G_DISTANCE = distanceNode.Text / 1000
    exitRoute:
    ‘ Tidy up
    Set distanceNode = Nothing
    Set myDomDoc = Nothing
    Set myRequest = Nothing
    End Function

    • Jamie Bull says:

      Great to see that this is coming in so handy for people. I’m surprised it doesn’t work for Australian postcodes anyway though. It should do, and if not you can pass in the extra argument in your formula if you use "=G_DISTANCE(A1&", Australia",B1&", Australia") – assuming your origin and destination are in A1 and B1 respectively.

      By the way, if you’re using this a lot it might be worth checking out the updated download in this thread which has improved code including caching of results to avoid going over Google’s daily limit.

  26. Brandon M. says:

    Jamie – your tools have been more than helpful with some of the projects I work on to make operations more efficient. I am curious though – when using this particular tool how do I display the route map that you have shown above?

  27. Ethan says:

    Hello Jamie,

    Just wanted to say what a great tool this is and to ask a few questions.

    I downloaded the Excel Workbook that contains the Sheets G_LATLNG, G_DISTANCE etc.

    I am interested specifically in the G_DISTANCE Sheet, I had wondered if in some way
    it was possible to export this somehow into Microsoft Access, in a way that if I entered
    one postcode into one cell and another postcode into another cell it would return the distance
    between them (as it does in the Spreadsheet).

    Or if this isn’t possible, whether you know of such a code module for Access that will allow me to do this.

    Thanks a lot.

    • Jamie Bull says:

      Hi Ethan,

      I’m not much of an Access person but you may still be in luck. A post came up on my RSS feeds a month or so ago and sounds like it might be exactly what you need for distance in Access – and a different implementation for Excel too. It’s not actual road distances though, just Great Circle so perhaps not quite what you need. If you’re looking for actual road distances you can link to an Excel workbook from Access but that’s not something I’ve done before.

      Hope this helps a bit at least,

      Jamie

  28. Владислав says:

    Good day, I am infinitely grateful to you for an indispensable tool.

    I have studied all the restrictions with regards to the number of Google queries, namely 2,500 requests per day for one client, and 100 000 000 for organizations.
    Distance matrix, which I process consists of more than one million hits, and I understand that the solution to my problem need to use multiple options or use a dynamic IP, or connecting to another service in which there is no restriction.
    Maybe you have to adapt their tools for such services?

    I produce only a measurement of the distance between the geographical coordinates of points, but I have them, as you know, very much.

    Thanks in advance for your help.

    P.S in Russia prefer to use all yandex me, many said that it is free, or Visicom, without limitation requests.

    http://api.yandex.ru/maps/doc/jsapi/1.x/dg/concepts/router.xml
    http://api.visicom.ua/docs/tools/console

  29. Rowel says:

    Hi Jamie, this is a wonderful tool.

  30. Paul Corbett says:

    I need to get the road distance from postcode to postcode for a ton of date (50,000+)

    I have used your G_Distance function, which is great, but with only being able to get 2500 in a 24 hour period, it will take ages.

    My company doesn’t mind paying, is there a corporate licence I could get that would open it up?

    Many thanks

    • Jamie Bull says:

      You can get business licences for about £7,000 from memory but contact them to check. I’ve sent you an email with your options but for anyone else looking here the options are just slogging away at 2,500 per day, getting a business licence, using the distance matrix API which is also rate limited, or spreading the job out over a network, with each IP address doing 2,500 queries.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>