Calculating distance between adresses using Google API in Excel (VBA) - excel

I'm working on my master's thesis and really need your help with some distance calculations.
I am really struggling with some code I found online in order to calculate the distance between several addresses (~10k pairs). I tried two different codes from two websites, and they both give me an error.
I already created my own Google API, and activated billing (using the URL test actually works for me) and tried some suggestions from other forums.
1. Approach
Found on: https://analystcave.com/excel-calculate-distances-between-addresses/
Code
'Calculate Google Maps distance between two addresses
Public Function GetDistance(start As String, dest As String)
Dim firstVal As String, secondVal As String, lastVal As String
firstVal = "http://maps.googleapis.com/maps/api/distancematrix/json?origins="
secondVal = "&destinations="
lastVal = "&mode=car&language=pl&sensor=false&key=YOUR_KEY"
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
URL = firstVal & Replace(start, " ", "+") & secondVal & Replace(dest, " ", "+") & lastVal
objHTTP.Open "GET", URL, False
objHTTP.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
objHTTP.send ("")
If InStr(objHTTP.responseText, """distance"" : {") = 0 Then GoTo ErrorHandl
Set regex = CreateObject("VBScript.RegExp"): regex.Pattern = """value"".*?([0-9]+)": regex.Global = False
Set matches = regex.Execute(objHTTP.responseText)
tmpVal = Replace(matches(0).SubMatches(0), ".", Application.International(xlListSeparator))
GetDistance = CDbl(tmpVal)
Exit Function
ErrorHandl:
GetDistance = -1
End Function
Every time I'm applying the formula, I get a "-1" i.e. error message.
2. Approach
Found on: https://syntaxbytetutorials.com/excel-function-to-calculate-distance-using-google-maps-api-with-vba/
Here I also added VBA-JSON and activated references as suggested by the author.
Code
' Returns the number of seconds it would take to get from one place to another
Function TRAVELDISTANCE(origin, destination, apikey)
Dim strUrl As String
strUrl = "https://maps.googleapis.com/maps/api/directions/json?origin=" & origin & "&destination=" & destination & "&key=" & apikey
Set httpReq = CreateObject("MSXML2.XMLHTTP")
With httpReq
.Open "GET", strUrl, False
.Send
End With
Dim response As String
response = httpReq.ResponseText
Dim parsed As Dictionary
Set parsed = JsonConverter.ParseJson(response)
Dim meters As Integer
Dim leg As Dictionary
For Each leg In parsed("routes")(1)("legs")
meters = meters + leg("distance")("value")
Next leg
TRAVELDISTANCE = meters
End Function
Here, the functions actually do not compile due to an error in the line
strUrl = "https://maps.googleapis.com/maps/api/directions/json?origin=" & origin & "&destination=" & destination & "&key=" & apikey
It returns the "Expected: end of statement" error.
I am completely lost and would be so grateful if anyone of you could provide some help.
Best,
Felix

As far as the second approach is concerned, according to this, the URL should look like the following example:
https://maps.googleapis.com/maps/api/directions/json?origin=Disneyland&destination=Universal+Studios+Hollywood&key=YOUR_API_KEY
So in your case, if you have a variable named origin, another one named destination and a third one named apikey, the URL should be built like so:
strUrl ="https://maps.googleapis.com/maps/api/directions/json?origin=" & origin & "&destination=" & destination & "&key=" & apikey
The function would have to be called like so, for example:
call TRAVELDISTANCE("Disneyland", "Universal+Studios+Hollywood", "xxxxx")
I suppose what happened is that in the website where you found the original code, the & character was resolved in its HTML version which is: &. This however will give an error in VBA.
So before copying and pasting something you need to understand how it works.
To combine strings the following applies in general:
finalString= String1 & String2 & "String3" & "String4" & ..... 'depending on whether your strings are stored in variables or not.

Related

Subscript out of range error where debug button is not displayed in error pop-up box

I am getting the error:
"Run-time error '9': Subscript out of range"
Excel is not telling me which line is triggering this error. It only gives me the "OK" and "Help" command buttons in the error pop-up box. My Excel VBA normally gives me the Debug option, but not in this case.
I have found three related topics. I understand that this is likely due to an incorrect array configuration.
Here is the code:
Sub ServiceNowRestAPIQuery()
' Replace with your Service Now Inctance URL
InstanceURL = "https://dev#####.service-now.com"
' Replace with your Authorization code
AuthorizationCode = "Basic ########################"
' Add more tables as comma seperated with no spaces
TableNames = ("incident,problem")
Dim ws As Worksheet
Dim objHTTP As New WinHttp.WinHttpRequest
Dim columns As String
Dim Header As Boolean
Dim jsonString As String
Dim Resp As New MSXML2.DOMDocument60
Dim Result As IXMLDOMNode
Dim ColumnsArray As Variant
TablesArray = Split(TableNames, ",")
For x = 0 To UBound(TablesArray)
'Table Choices
Select Case TablesArray(x)
Case "incident"
Set ws = Sheets("incidents")
columns = "number,company,close_notes,impact,closed_at,assignment_group"
ColumnsArray = Split(columns, ",")
OtherSysParam = "&sysparm_limit=100000"
SysQuery = "&sysparm_query=active%3Dtrue"
Case "problem"
'Sheet name
Set ws = Sheets("problem")
'Columns to Query
columns = "number,short_description,state"
ColumnsArray = Split(columns, ",")
'Query filter Parameters
OtherSysParam = "&sysparm_query=state=1"
'Other Query Parameters
SysQuery = ""
End Select
Url = InstanceURL & "/api/now/table/"
Table = TablesArray(x) & "?"
sysParam = "sysparm_display_value=true&sysparm_exclude_reference_link=true" & OtherSysParam & SysQuery & "&sysparm_fields=" & columns
Url = Url & Table & sysParam
objHTTP.Open "get", Url, False
objHTTP.SetRequestHeader "Accept", "application/xml"
objHTTP.SetRequestHeader "Content-Type", "application/xml"
' Authorization Code
objHTTP.SetRequestHeader "Authorization", AuthorizationCode
objHTTP.Send '("{" & Chr(34) & "short_description" & Chr(34) & ":" & Chr(34) & "Test API2" & Chr(34) & "}")
Debug.Print objHTTP.Status
Debug.Print objHTTP.ResponseText
ws.Select
Header = False
i = 1
ThisWorkbook.Sheets("API").Range("A1").Select
Cells.Clear
Resp.LoadXML objHTTP.ResponseText
For Each Result In Resp.getElementsByTagName("result")
For n = 0 To UBound(ColumnsArray)
If Header = False Then
ActiveCell.Offset(0, n).Value = ColumnsArray(n)
End If
ActiveCell.Offset(i, n).Value = Result.SelectSingleNode(ColumnsArray(n)).Text
Next n
i = i + 1
Header = True
Next Result
'MsgBox Time
Next x
End Sub
This code is for integrating an Excel workbook with a ServiceNow instance via the REST web services. More information and the source of the code can be found on ServiceNowElite's ServiceNow to Microsoft Excel Integration webpage.
Instead of running the code fully, debug within the VBA environment. Go into the code and start it by pressing F8, then keeping pressing F8. It will go line by line and you can then see which line will cause the error.
EDIT:
If your workbook does not contain a sheet named "incidents" (or one named "API"),
you'll get a "Subscript out of Range error." Create those sheets.

VBA httpWebRequest with Credentials

I need to get some data from a cloud service.
This is my code so far:
Option Explicit
Sub Test()
Call GetHTTPResult("https://venice.unit4.com/WebConnect/api/ZZKlesserRob/2017/Balance/GetBalance?AccountNumber=604&BeginMonth=1&EndMonth=1", "username", "password")
End Sub
Function GetHTTPResult(sURL As String, Optional username As String, Optional password As String) As String
Dim XMLHTTP As Object, sResult As String
Set XMLHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
username = "dummy"
password = "dummypass"
XMLHTTP.Open "GET", sURL, False
XMLHTTP.setRequestHeader "Authorization", "Basic" & Base64Encode("username" & ":" & "password")
XMLHTTP.Send
Debug.Print "Status: " & XMLHTTP.Status & " - " & XMLHTTP.StatusText
sResult = XMLHTTP.ResponseText
GetHTTPResult = sResult
Set XMLHTTP = Nothing
End Function
Without the credentials it gives me the "401 - Unauthorized" -response, which is good, I suppose.
However I do have the necessary credentials at my disposal but I can't seem to fix the problem posed by the Base64 encoding.
What should I do?
Thanks in advance!
From inspecting the docs I believe your are missing a space in your Authorization header:
var request = new XMLHttpRequest();
...
request.setRequestHeader("Accept","application/xml");
request.setRequestHeader("Authorization","Basic " + Base64.encode ("User:Password"));
So your should read:
XMLHTTP.setRequestHeader "Authorization", "Basic " & Base64Encode(username & ":" & password)
Also, you should add an Accept header to the request with application/xml or application/json to specify the format of the requested data.

How to Automate QR Codes in Excel 2016

I need to generate a whole sheet of QR codes, (eventually about 1000), i am trying to automate the generation in Excel 2016, i currently have a sheet set up and have a URL to the generater using Google Apis, I just change the ID number in the url for it to take me to make the next code and take me to the correct place. I dont want to have to manually go and get the code and copy it into my document for each one.
Does anyone have any ideas that may help me out, i have set up the first 10 and this can be seen on the screenshot attached.
enter image description here
Thanks
You can use this VBA code to your Excel file,then you have to make a selection for the cells that you want to create QR Codes for them, then run the code "InsertQR" by (Alt+F8)
The VBA code will create QR codes for each selected cell as PNG file.
Note: You must be connected to the Internet
Sub InsertQR()
Dim xHttp: Set xHttp = CreateObject("Microsoft.XMLHTTP")
Dim bStrm: Set bStrm = CreateObject("Adodb.Stream")
Dim size: size = 500 'dalam Pixels
Dim QR, Name, val
Dim Invalid: Invalid = "\/:*?" & """" & "<>|"
For Each val In Selection
Name = val.Value
For intChar = 1 To Len(Name)
If InStr(Invalid, LCase(Mid(Name, intChar, 1))) > 0 Then
MsgBox "The file: " & vbCrLf & """" & Name & """" & vbCrLf & vbCrLf & " is invalid!"
Exit Sub
End If
Next
QR = "http://chart.googleapis.com/chart?chs=" & size & "x" & size & "&cht=qr&chl=" & Name
xHttp.Open "GET", QR, False
xHttp.Send
With bStrm
.Type = 1 '//binary
.Open
.write xHttp.responseBody
.savetofile ThisWorkbook.Path & "\" & Name & ".png", 2 '//overwrite
.Close
End With
Next
End Sub
This is the closest thing I could find with what you are trying to do.
https://sites.google.com/site/e90e50fx/home/generate-qrcode-with-excel
It's generate a QR code image but I can't get it to do it for multiple cell values.

Using "setClientCertificate" when there are multiple certificates installed

I wrote a WinHttp POST request in VBA. It works good as long as there is only one certificate installed on the computer. However, some users have multiple certs with similar certificate names and therefore it returns an error:
a certificate is required to complete client authentication
Any suggestions on how I can select the correct certificate when multiple certificates share similar names? I've tried using both the "friendly name" and the "CN" name of the cert.
Below is my code:
Sub dapull()
Dim URL As String: URL = "https://ce.midwest.org/dart/xml/query"
Dim mfile As String
pulldate = Format(Worksheets("Sheet2").Range("date").Value, "yyyy-mm-dd")
mfile = "<?xml version=" & """" & "1.0" & """" & "?><Envelope xmlns=" & """" & "http://schemas.xmlsoap.org/soap/envelope/" & """" & "><Header/><Body><QueryRequest xmlns=" & """" & "http://markets.midwest.org/dart/xml" & """" & "><QueryResults day=" & """" & pulldate & """" & "><Location>BART</Location></QueryResults></QueryRequest></Body></Envelope>"
Set Req = New WinHttp.WinHttpRequest
With Req
.Open "POST", URL, False
.SetClientCertificate "CURRENT_USER\MY\name" '*this is the issue line
.SetRequestHeader "content-type", "text/xml"
.Send (mfile)
.ResponseText
End With
End Sub
I have the same issue, did you manage to solve it?
VBA just picks the first one :( no way to list or to identify which is which (or at least sort by date or something else before picking up the certificate).
If you did it, please let me know how
For now I "solved" it by asking people to copy their own right certificate into Trusted People section and put into my XLSM an option to switch the store so that it is picked up from CURRENT_USER\TrustedPeople\ instead of MY store.
It works but it is not elegant as it needs the certificate to be manually re-copied every 6 or 12 months (but better than not working at all :) )

Checking for broken hyperlinks in Excel

I have a large list of hyperlinks (plus a few cells of nonsense) that I need to check. I need to know which links are still active and which no longer exist or return a 404 (or other) Error. I have been using the advice in this entry: Sort dead hyperlinks in Excel with VBA? and it worked great in a small selection of links, some of which I deliberately broke myself. However, now that I try to use the same macro on my actual list of hyperlinks it won't work at all! I've manually checked a few and have found links with 404 errors. Again, when I deliberately mistype one of the addresses it will pick that up but it won't pick up any in the list that were broken already.
I'm totally new to macros and am really stumbling about in the dark here. Any help/advice would be very much appreciated!
I've been using this for a while and it has been working for me.
Sub Audit_WorkSheet_For_Broken_Links()
If MsgBox("Is the Active Sheet a Sheet with Hyperlinks You Would Like to Check?", vbOKCancel) = vbCancel Then
Exit Sub
End If
On Error Resume Next
For Each alink In Cells.Hyperlinks
strURL = alink.Address
If Left(strURL, 4) <> "http" Then
strURL = ThisWorkbook.BuiltinDocumentProperties("Hyperlink Base") & strURL
End If
Application.StatusBar = "Testing Link: " & strURL
Set objhttp = CreateObject("MSXML2.XMLHTTP")
objhttp.Open "HEAD", strURL, False
objhttp.Send
If objhttp.statustext <> "OK" Then
alink.Parent.Interior.Color = 255
End If
Next alink
Application.StatusBar = False
On Error GoTo 0
MsgBox ("Checking Complete!" & vbCrLf & vbCrLf & "Cells With Broken or Suspect Links are Highlighted in RED.")
End Sub
Specify an actual address in place of alink or define alink as a variable which contains a web address.
variable definitions missing, URL to working code below
Dim alink As Hyperlink
Dim strURL As String
Dim objhttp As Object
Bulk Url checker macro excel
I have been using the suggested code above. I had to adapt it further so that it can differentiate between a URL and a File as I have both in my excel spreadsheet. It works well for my particular spreadsheet with about 50 links to files and URLs.
Sub Audit_WorkSheet_For_Broken_Links()
If MsgBox("Is the Active Sheet a Sheet with Hyperlinks You Would Like to Check?", vbOKCancel) = vbCancel Then
Exit Sub
End If
Dim alink As Hyperlink
Dim strURL As String
Dim objhttp As Object
Dim count As Integer
On Error Resume Next
count = 0 'used to track the number of non-working links
For Each alink In Cells.Hyperlinks
strURL = alink.Address
If Left(strURL, 4) <> "http" Then
strURL = ThisWorkbook.BuiltinDocumentProperties("Hyperlink Base") & strURL
End If
Application.StatusBar = "Testing Link: " & strURL
Set objhttp = CreateObject("MSXML2.XMLHTTP")
objhttp.Open "HEAD", strURL, False
objhttp.Send
If objhttp.statustext = "OK" Then 'if url does exist
alink.Parent.Interior.ColorIndex = 0 'clear cell color formatting
ElseIf objhttp.statustext <> "OK" Then 'if url doesn't exist
If Dir(strURL) = "" Then 'check if the file exists
alink.Parent.Interior.Color = 255 'set cell background to red its not a valid file or URL
count = count + 1 'update the count of bad cell links
Else
alink.Parent.Interior.ColorIndex = 0 'clear cell color formatting
End If
End If
Next alink
Application.StatusBar = False
'Release objects to prevent memory issues
Set alink = Nothing
Set objhttp = Nothing
On Error GoTo 0
MsgBox ("Checking Complete!" & vbCrLf & vbCrLf & count & " Cell(s) With Broken or Suspect Links. Errors are Highlighted in RED.")
End Sub
I hope this helps someone else as much as it has helped me... A little better everyday!

Resources