I have Excel sheet with a lot of addresses (and the matching coordinates). I want to use Google Places API to create a function that gets me e. g. all restaurants surrounding a specific address. I try to output the names of all matching restaurants, the issue is that the output is just "0".
Here is my code:
Function Nearby(Lat As Long, Lng As Long) As Variant
'Variablen definieren
Dim Request As New XMLHTTP30
Dim Results As New DOMDocument30
Dim StatusNode As IXMLDOMNode
Dim NearbyNode As IXMLDOMNode
On Error GoTo errorHandler
Request.Open "GET", "https://maps.googleapis.com/maps/api/place/nearbysearch/xml?location=" & Lat & "," & Lng & "&radius=50&type=restaurant&key=AIzaSyA5nFPM_9Ss_X410c35WfoP_obP5UwppRU"""
Request.send
Results.LoadXML Request.responseText
Set StatusNode = Results.SelectSingleNode("//status")
Select Case UCase(StatusNode.Text)
Case "OK"
Set NearbyNode = Results.SelectSingleNode("//result/name[1]/name[2]/name[3]/name[4]")
Nearby = NearbyNode.Text
Case "ZERO_RESULTS"
Nearby = "The address does not exists"
Case Else
Nearby = "Error"
End Select
errorHandler:
Set StatusNode = Nothing
Set NearbyNode = Nothing
Set Results = Nothing
Set Request = Nothing
End Function
I slightly reworked your code, try the below example:
Option Explicit
Sub TestNearby()
Dim NearbyNames
Dim NearbyState As String
Nearby "-33.8670522", "151.1957362", "1000", "hospital", NearbyNames, NearbyState
If NearbyState = "OK" Then
MsgBox Join(NearbyNames, vbCrLf)
Else
MsgBox NearbyState
End If
End Sub
Sub Nearby(Lat As String, Lng As String, Dist As String, PointType As String, Names As Variant, State As String)
Dim Request As Object
Dim Results As Object
Dim Node
On Error GoTo errorHandler
Set Request = CreateObject("MSXML2.XMLHTTP")
Request.Open "GET", "https://maps.googleapis.com/maps/api/place/nearbysearch/xml?" & _
"location=" & Lat & "," & Lng & _
"&radius=" & Dist & _
"&type=" & PointType & _
"&key=AIzaSyA5nFPM_9Ss_X410c35WfoP_obP5UwppRU", False
Request.send
Set Results = Request.responseXML
Select Case UCase(Results.SelectSingleNode("//status").Text)
Case "OK"
With CreateObject("Scripting.Dictionary")
For Each Node In Results.SelectNodes("//PlaceSearchResponse/result/name")
.Add .Count, Node.nodeTypedValue
Next
Names = .Items()
End With
State = "OK"
Case "ZERO_RESULTS"
State = "No results"
Case Else
State = "Wrong request"
End Select
Exit Sub
errorHandler:
State = "Error"
End Sub
The output for me is:
I changed Lat,Lng to type double and modified the Request.Open "GET" string
Sub Nearby()
Dim Request As New XMLHTTP30
Dim Results As New DOMDocument30
Dim StatusNode As IXMLDOMNode
Dim NearbyNode As IXMLDOMNode
Dim Node As IXMLDOMNode
On Error GoTo errorHandler
Dim Lat As Double 'Chicago
Lat = 41.878114
Dim Lng As Double
Lng = -87.629798
Request.Open "GET", "https://maps.googleapis.com/maps/api/place/nearbysearch/xml?location=" & Lat & "," & Lng & "&radius=50&type=restaurant&key=AIzaSyA5nFPM_9Ss_X410c35WfoP_obP5UwppRU" & "&sensor=False"
Request.send
Results.LoadXML Request.responseText
Set StatusNode = Results.SelectSingleNode("//status")
Select Case UCase(StatusNode.Text)
Case "OK"
For Each Node In Results.SelectNodes("//PlaceSearchResponse/result/name")
Debug.Print Node.nodeTypedValue
Next
Case "ZERO_RESULTS"
Debug.Print "The address does not exists"
Case Else
Debug.Print "Error"
End Select
errorHandler:
Set StatusNode = Nothing
Set NearbyNode = Nothing
Set Results = Nothing
Set Request = Nothing
End Sub
This function returns a string of comma separated values (albeit needs more error trapping) :
Public Function NearBy(Lat As Double, Lng As Double) As Variant
Dim Request As New XMLHTTP30
Dim Results As New DOMDocument30
Dim StatusNode As IXMLDOMNode
Dim NearbyNode As IXMLDOMNode
Dim Node As IXMLDOMNode
Dim sz As String
On Error GoTo errorHandler
Request.Open "GET", "https://maps.googleapis.com/maps/api/place/nearbysearch/xml?location=" & Lat & "," & Lng & "&radius=150&type=restaurant&key=AIzaSyA5nFPM_9Ss_X410c35WfoP_obP5UwppRU" & "&sensor=False"
Request.send
Results.LoadXML Request.responseText
Set StatusNode = Results.SelectSingleNode("//status")
Select Case UCase(StatusNode.Text)
Case "OK"
For Each Node In Results.SelectNodes("//PlaceSearchResponse/result/name")
sz = sz & Node.nodeTypedValue & ", "
Next
NearBy = Left(sz, Len(sz) - 2) 'remove last ", "
Case "ZERO_RESULTS"
NearBy = "The address does not exists"
Case Else
NearBy = "Error"
End Select
errorHandler:
Set StatusNode = Nothing
Set NearbyNode = Nothing
Set Results = Nothing
Set Request = Nothing
End Function
Related
I'm trying to write code which can measure geometry coordinates in Catia active document, probably in CATProduct?! this is my code and the result is nothing. MsgBox doesn't show anything.
Sub CatMain()
Dim varFilter(1) As Variant
Dim objSel As Selection
Dim objSelLB As Object ' <--- notice declared as object
Dim strReturn As String
Dim strMsg As String
varFilter(0) = "Body" 'Body represents a solid body
varFilter(1) = "HybridBody" 'HybridBody represents a geometrical set
Set objSel = CATIA.ActiveDocument.Selection
Set objSelLB = objSel
strMsg = "Select a body or geometrical set…"
objSel.Clear
strReturn = objSelLB.SelectElement2(varFilter, strMsg, False)
If strReturn = "Normal" Then
If objSel.Count2 > 0 Then
Set bb = objSel.Item(1).Value
Set cc = bb.HybridShapes
For s = 1 To cc.Count
Set cc = cc.Item(s)
cc.GetCoordinates arrXYZ
MsgBox ((cc.Parent.Name) & Separator & (cc.Name) & Separator & _
arrXYZ(0) & Separator & _
arrXYZ(1) & Separator & _
arrXYZ(2) & vbLf)
Next s
End If
End Sub
This is my code for this task. The issue is with the invalid characters in Windows. I can replace them fine on files but on folders in doesn't seem to work.
Dim xFSO As Scripting.FileSystemObject
Sub CopyOutlookFldStructureToWinExplorer()
ExportAction "Copy"
End Sub
Sub ExportAction(xAction As String)
Dim xFolder As Outlook.Folder
Dim xFldPath As String
xFldPath = SelectAFolder()
If xFldPath = "" Then
MsgBox "You did not select a folder. Export cancelled.", vbInformation + vbOKOnly, "Kutools for Outlook"
Else
Set xFSO = New Scripting.FileSystemObject
Set xFolder = Outlook.Application.ActiveExplorer.CurrentFolder
ExportOutlookFolder xFolder, xFldPath
End If
Set xFolder = Nothing
Set xFSO = Nothing
End Sub
Sub ExportOutlookFolder(ByVal OutlookFolder As Outlook.Folder, xFldPath As String)
Dim xSubFld As Outlook.Folder
Dim xItem As Object
Dim xPath As String
Dim xFilePath As String
Dim xSubject As String
Dim xFilename As String
On Error Resume Next
xPath = xFldPath & "\" & OutlookFolder.Name
'?????????,??????
If Dir(xPath, 16) = Empty Then MkDir xPath
For Each xItem In OutlookFolder.Items
xItem = ReplaceInvalidCharacters(xItem.Item)
xSubject = ReplaceInvalidCharacters(xItem.Subject)
xSubFld = ReplaceInvalidCharacters(xItem.SubFld)
xFldPath = ReplaceInvalidCharacters(xItem.FldPath)
xPath = ReplaceInvalidCharacters(xItem.Path)
xSubject = ReplaceInvalidCharacters(xItem.Subject)
xFilename = xSubject & ".msg"
xFilename = ReplaceInvalidCharacters(xItem.FileName)
xFilePath = xPath & "\" & xFilename
xFilePath = ReplaceInvalidCharacters(xItem.FilePath)
If xFSO.FileExists(xFilePath) Then
xCounter = xCounter + 1
xFilename = xSubject & " (" & xCounter & ").msg"
xFilePath = xPath & "\" & xFilename
xFilePath = ReplaceInvalidCharacters(xItem.FilePath)
End If
xItem.SaveAs xFilePath, olMSG
Next
For Each xSubFld In OutlookFolder.Folders
ExportOutlookFolder xSubFld, xPath
Next
Set OutlookFolder = Nothing
Set xItem = Nothing
End Sub
Function SelectAFolder() As String
Dim xSelFolder As Object
Dim xShell As Object
On Error Resume Next
Set xShell = CreateObject("Shell.Application")
Set xSelFolder = xShell.BrowseForFolder(0, "Select a folder", 0, 0)
If Not TypeName(xSelFolder) = "Nothing" Then
SelectAFolder = xSelFolder.self.Path
End If
Set xSelFolder = Nothing
Set xShell = Nothing
End Function
Function ReplaceInvalidCharacters(Str As String) As String
Dim xRegEx
Set xRegEx = CreateObject("vbscript.regexp")
xRegEx.Global = True
xRegEx.IgnoreCase = False
xRegEx.Pattern = "\||\/|\<|\>|""|:|\*|\\|\?"
ReplaceInvalidCharacters = xRegEx.Replace(Str, "_")
End Function
Always use Option Explicit at the very top of every module, before any function. This will tell you if you have not Dim'med any variables. In this case there is an issue with xCount and xCounter, which should have only one name.
I think the problem may come from the function ExportOutlookFolder, this line:
xPath = xFldPath & "\" & OutlookFolder.Name
Try replacing it with:
xPath = xFldPath & "\" & ReplaceInvalidCharacters(OutlookFolder.Name)
I'm not able to union two csvs even though ADODB confirms via .Fields.Count that they both have the same number of columns.
Here's the query that's failing:
select * from csv1.csv union select * from csv2.csv
with the error message:
The number of columns in the two selected tables or queries of a union query do not match
However, when I do select * from csv1.csv and select * from csv2.csv separately, ADODB confirms that .Fields.Count = 8 for both.
Possible key to the problem:
Do I need to create two separate connections? I'm only creating one connection (to the first csv) even though there are two csvs in the query.
I was trying to figure out how to do two separate connections for the same query and it seemed like people weren't finding that necessary - I couldn't find two connections mentioned in equivalent queries people were running against csvs.
Per #Parfait's request to see more of the code:
GetDataFromCSV
Public Function GetDataFromCSV(ByVal fileReport As Scripting.File, ByVal strQuery As String, ByVal arrSourceReports As Variant) As Boolean
Dim strRevisedQuery As String
strRevisedQuery = GetRevisedQueryWithFileAliasesReplacedWithTrueFileNames(strQuery, arrSourceReports)
Dim cnn As ADODB.Connection
Set cnn = OpenConnectionToCSV(fileReport)
If cnn Is Nothing Then
GetDataFromCSV = False
Exit Function
End If
GetDataFromCSV = QueryDataFromCSV(cnn, strRevisedQuery, fileReport.Name, fileReport.Name)
End Function
OpenConnectionToCSV
Private Function OpenConnectionToCSV(ByVal fileCSV As Scripting.File, Optional boolHeadersPresent As Boolean = True) As ADODB.Connection
Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection
cnn.ConnectionTimeout = 0
Dim strfileCSVParentFolderPath As String
strfileCSVParentFolderPath = fileCSV.ParentFolder
If Right(strfileCSVParentFolderPath, 1) <> Application.PathSeparator Then strfileCSVParentFolderPath = strfileCSVParentFolderPath & Application.PathSeparator
Dim strConn As String
If boolHeadersPresent = False Then
strConn = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & strfileCSVParentFolderPath & ";Extended Properties=""text;HDR=NO;FMT=Delimited"""
Else
strConn = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & strfileCSVParentFolderPath & ";Extended Properties=""text;HDR=YES;FMT=Delimited"""
End If
If strConn <> vbNullString Then
On Error GoTo ErrorHandler
Dim lngRetryCount As Long
lngRetryCount = 0
cnn.Open strConn
On Error GoTo 0
Set OpenConnectionToCSV = cnn
End If
Exit Function
ErrorHandler:
Select Case True
Case InStr(1, Err.Description, "Connect timeout occurred", vbTextCompare) > 0
If lngRetryCount < 30 Then
Application.Wait DateAdd("s", 1, Now)
lngRetryCount = lngRetryCount + 1
Resume
Else
MsgBox "Can't connect to " & fileCSV.Path & ". Reading this file will be skipped."
Exit Function
End If
Case Else
MsgBox "Getting data from " & fileCSV.Name & " has failed with the following error message: " & Err.Number & ": " & Err.Description
On Error GoTo 0
Resume
End Select
End Function
QueryDataFromCSV
Private Function QueryDataFromCSV(ByVal cnn As ADODB.Connection, ByVal strQuery As String, ByVal strCSVName As String, ByVal strFinalReportTitle As String) As Boolean
QueryDataFromCSV = True
Dim cmd As ADODB.Command
Set cmd = PrepareQueryCommand(cnn, strQuery)
CreateQueryDebugLog cmd.CommandText
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
rst.Open cmd
Dim Loop1 As Long
With rst
For Loop1 = 1 To .Fields.Count
If .Fields(Loop1 - 1).Name = "F" & Loop1 Then
If Loop1 < 4 Then
MsgBox "Can't retrieve data from " & strCSVName & " because it is formatted improperly."
Else
MsgBox "Can't retrieve data from " & strCSVName & " because it is delimited improperly. The file is most likely delimited with a comma even though it has addresses or other fields that contain commas. Ask Encounters IT to change this report's delimiter to another character, such as | (pipe), in the Tidal batch file."
End If
QueryDataFromCSV = False
Exit Function
End If
Next Loop1
End With
CopyThisCSVRecordsetToResultSheets rst, strFinalReportTitle
cnn.Close
Set rst = Nothing
Set cmd = Nothing
Set cnn = Nothing
End Function
The error is occurring at rst.Open cmd in the above function QueryDataFromCSV
Illustrating schema.ini creation for #Comintern:
GetRevisedQueryWithFileAliasesReplacedWithTrueFileNames
Private Function GetRevisedQueryWithFileAliasesReplacedWithTrueFileNames(ByVal strQuery As String, ByVal arrSourceReports As Variant) As String
Dim FSO As Scripting.FileSystemObject
Set FSO = New Scripting.FileSystemObject
Dim lngPosition As Long
lngPosition = 0
Do Until lngPosition > Len(strQuery)
Dim lngStartPosition As Long
lngStartPosition = InStr(lngPosition + 1, strQuery, "from", vbTextCompare) + 5
If lngStartPosition > lngPosition Then
Dim lngEndPosition As Long
lngEndPosition = InStr(lngStartPosition + 1, strQuery, " ", vbTextCompare)
If lngEndPosition = 0 Then lngEndPosition = Len(strQuery) + 1
Dim strSourceReportTitle As String
strSourceReportTitle = Mid(strQuery, lngStartPosition, lngEndPosition - lngStartPosition)
Dim Loop2 As Long
For Loop2 = LBound(arrSourceReports, 1) To UBound(arrSourceReports, 1)
If arrSourceReports(Loop2, 1) = strSourceReportTitle Then Exit For
Next Loop2
Dim fileSource As Scripting.File
Set fileSource = FSO.GetFile(arrSourceReports(Loop2, 3))
If arrSourceReports(Loop2, 2) = "TAB" Then arrSourceReports(Loop2, 2) = Chr(9)
CreateSchemaIni fileSource, arrSourceReports(Loop2, 2)
Dim strRevisedQuery As String
If strRevisedQuery = vbNullString Then
strRevisedQuery = Replace(strQuery, "from " & strSourceReportTitle, "from " & fileSource.Name)
Else
strRevisedQuery = Replace(strRevisedQuery, "from " & strSourceReportTitle, "from " & fileSource.Name)
End If
lngPosition = lngEndPosition
Else
lngPosition = Len(strQuery) + 1
End If
Loop
GetRevisedQueryWithFileAliasesReplacedWithTrueFileNames = strRevisedQuery
End Function
CreateSchemaIni
Private Sub CreateSchemaIni(ByVal fileReport As Scripting.File, ByVal strDelimiter As String)
Dim intSystemFileNumber As Integer
intSystemFileNumber = FreeFile()
On Error GoTo ErrorHandler
Open fileReport.ParentFolder.Path & Application.PathSeparator & "Schema.ini" For Output As #intSystemFileNumber
Print #intSystemFileNumber, "[" & fileReport.Name & "]"
Print #intSystemFileNumber, "Format=Delimited(" & strDelimiter & ")"
Close #intSystemFileNumber
Exit Sub
ErrorHandler:
Select Case True
Case InStr(1, Err.Description, "Path/File Access Error", vbTextCompare) > 0
Dim strStandardQueryDebugLogPath As String
strStandardQueryDebugLogPath = fileReport.ParentFolder.Path & Application.PathSeparator & "strQuery.txt"
MsgBox strStandardQueryDebugLogPath & " was inaccessible. Creating log in same folder where your copy of the Mass Queryer is saved instead."
Open Left(ThisWorkbook.Path, InStrRev(ThisWorkbook.Path, Application.PathSeparator, , vbTextCompare)) & "strQuery.txt" For Output As #intSystemFileNumber
Print #intSystemFileNumber, "[" & fileReport.Name & "]"
Print #intSystemFileNumber, "Format=Delimited(" & strDelimiter & ")"
Close #intSystemFileNumber
Exit Sub
Case Else
MsgBox "Creating a query debug log has failed with the following error message: " & Err.Number & ": " & Err.Description
On Error GoTo 0
Resume
End Select
End Sub
With #Comintern's help, I was able to see that I made a silly mistake having nothing to do with the question title in actuality. You can see above that my CreateSchemaIni method was creating and then overwriting the Schema.ini file for each csv I was querying rather than creating and then appending to it. By changing that method to use Open For Append instead of Open For Output, the problem was solved.
I tried to a macro to get top 3 street addresses from a keyword and let the user choose one. However, I kept running into error 13( mismatched data type) on my "case 1" statement or in the last input box. Any help?I am relatively new to VBA.
Sub myTest2()
Dim xhrRequest As XMLHTTP60
Dim domDoc As DOMDocument60
Dim query As String
Dim myNodes As IXMLDOMNodeList
Dim myNode As IXMLDOMNode
Dim nNode As Integer
Dim re As Range
Dim result(2) As String
'allows user to select range
Set myValue = Application.InputBox(prompt:="Please select the list of addresses wether empty or not of the organizations", Type:=8)
Set myValueCol = Application.InputBox(prompt:="Please select the column with the names", Type:=8)
For Each re In myValue
If IsEmpty(re.Value) Or re.Value = vbNullString Then
query = Cells(re.Row, myValueCol.Column)
query = Replace(query, " ", "+")
query = Replace(query, ",", "%2C")
'You must acquire a google api key and enter it here
Dim googleKey As String
googleKey = "KEY_HERE" 'your api key here
'Send a "GET" request for place/textsearch
Set xhrRequest = New XMLHTTP60
xhrRequest.Open "GET", "https://maps.googleapis.com/maps/api/place/textsearch/xml?query=" & query & "&key=" & googleKey, False
xhrRequest.send
'Save the response into a document
Set domDoc = New DOMDocument60
domDoc.LoadXML xhrRequest.responseText
Set myNodes = domDoc.SelectNodes("//result/formatted_address")
For nNode = 0 To 2
Set myNode = myNodes(nNode)
If Not (myNode Is Nothing) Then
result(nNode) = myNode.Text
End If
If myNode Is Nothing Then
result(nNode) = "no additional adresses found"
End If
Next nNode
sinput = Application.InputBox(prompt:="1. " & result(0) & vbNewLine & "2. " & result(1) & vbNewLine & "3. " & result(2), Type:=1)
Select Case sinput
Case 1
re = result0
Case 2
re = result1
Case 3
re = result2
End Select
End If
Next re
End Sub
This is what finally worked for me. Thank you :)
Sub allowUserToChooseLocation()
Dim xhrRequest As XMLHTTP60
Dim domDoc As DOMDocument60
Dim query As String
Dim myNodes As IXMLDOMNodeList
Dim myNode As IXMLDOMNode
Dim nNode As Integer
Dim re As Range
Dim result(0 To 2) As String
'allows user to select range
Set myValue = Application.InputBox(prompt:="Please select the list of addresses wether empty or not of the organizations", Type:=8)
Set myValueCol = Application.InputBox(prompt:="Please select the column with the names", Type:=8)
For Each re In myValue
If IsEmpty(re.Value) Or re.Value = vbNullString Then
query = Cells(re.Row, myValueCol.Column)
query = Replace(query, " ", "+")
query = Replace(query, ",", "%2C")
'You must acquire a google api key and enter it here
Dim googleKey As String
googleKey = "Key_Here" 'your api key here
'Send a "GET" request for place/textsearch
Set xhrRequest = New XMLHTTP60
xhrRequest.Open "GET", "https://maps.googleapis.com/maps/api/place/textsearch/xml?query=" & query & "&key=AIzaSyAmkY6nbeMGS19t0jdcFQT_SxoFcm7LUdE", False
xhrRequest.send
'Save the response into a document
Set domDoc = New DOMDocument60
domDoc.LoadXML xhrRequest.responseText
Set myNodes = domDoc.SelectNodes("//result/formatted_address")
For nNode = 0 To 2
Set myNode = myNodes(nNode)
If Not (myNode Is Nothing) Then
result(nNode) = myNode.nodeTypedValue
End If
If (myNode Is Nothing) Then
result(nNode) = "No additonal addresses found"
End If
Next nNode
sinput = Application.InputBox(prompt:="1. " & result(0) & vbNewLine & "2. " & result(1) & vbNewLine & "3. " & result(2), Type:=1)
Select Case sinput
Case 1
re.Value = result(0)
Case 2
re.Value = result(1)
Case 3
re.Value = result(2)
End Select
End If
Next re
End Sub
I have found a code on which helps me export both travel time and a distance between 2 locations from Google Maps, while using Excel spreadsheet.
It works fine, but one thing I am missing is an opportunity to add an in-between point. Do you think it is doable to modify the code so I could have 3th cell with in-between point?
Please find code below:
' Usage :
' GetGoogleTravelTime (strFrom, strTo) returns a string containing journey duration : hh:mm
' GetGoogleDistance (strFrom, strTo) returns a string containing journey distance in either miles or km (as defined by strUnits)
' GetGoogleDirections (strFrom, strTo) returns a string containing the directions
'
' where strFrom/To are address search terms recognisable by Google
' i.e. Postcode, address etc.
'
' by Desmond Oshiwambo
Const strUnits = "metric" ' imperial/metric (miles/km)
Function CleanHTML(ByVal strHTML)
'Helper function to clean HTML instructions
Dim strInstrArr1() As String
Dim strInstrArr2() As String
Dim s As Integer
strInstrArr1 = Split(strHTML, "<")
For s = LBound(strInstrArr1) To UBound(strInstrArr1)
strInstrArr2 = Split(strInstrArr1(s), ">")
If UBound(strInstrArr2) > 0 Then
strInstrArr1(s) = strInstrArr2(1)
Else
strInstrArr1(s) = strInstrArr2(0)
End If
Next
CleanHTML = Join(strInstrArr1)
End Function
Public Function formatGoogleTime(ByVal lngSeconds As Double)
'Helper function. Google returns the time in seconds, so this converts it into time format hh:mm
Dim lngMinutes As Long
Dim lngHours As Long
lngMinutes = Fix(lngSeconds / 60)
lngHours = Fix(lngMinutes / 60)
lngMinutes = lngMinutes - (lngHours * 60)
formatGoogleTime = Format(lngHours, "00") & ":" & Format(lngMinutes, "00")
End Function
Function gglDirectionsResponse(ByVal strStartLocation, ByVal strEndLocation, ByRef strTravelTime, ByRef strDistance, ByRef strInstructions, Optional ByRef strError = "") As Boolean
On Error GoTo errorHandler
' Helper function to request and process XML generated by Google Maps.
Dim strURL As String
Dim objXMLHttp As Object
Dim objDOMDocument As Object
Dim nodeRoute As Object
Dim lngDistance As Long
Set objXMLHttp = CreateObject("MSXML2.XMLHTTP")
Set objDOMDocument = CreateObject("MSXML2.DOMDocument.6.0")
strStartLocation = Replace(strStartLocation, " ", "+")
strEndLocation = Replace(strEndLocation, " ", "+")
strURL = "http://maps.googleapis.com/maps/api/directions/xml" & _
"?origin=" & strStartLocation & _
"&destination=" & strEndLocation & _
"&sensor=false" & _
"&units=" & strUnits 'Sensor field is required by google and indicates whether a Geo-sensor is being used by the device making the request
'Send XML request
With objXMLHttp
.Open "GET", strURL, False
.setRequestHeader "Content-Type", "application/x-www-form-URLEncoded"
.Send
objDOMDocument.LoadXML .ResponseText
End With
With objDOMDocument
If .SelectSingleNode("//status").Text = "OK" Then
'Get Distance
lngDistance = .SelectSingleNode("/DirectionsResponse/route/leg/distance/value").Text ' Retrieves distance in meters
Select Case strUnits
Case "imperial": strDistance = Round(lngDistance * 0.00062137, 1) 'Convert meters to miles
Case "metric": strDistance = Round(lngDistance / 1000, 1) 'Convert meters to miles
End Select
'Get Travel Time
strTravelTime = .SelectSingleNode("/DirectionsResponse/route/leg/duration/value").Text 'returns in seconds from google
strTravelTime = formatGoogleTime(strTravelTime) 'converts seconds to hh:mm
'Get Directions
For Each nodeRoute In .SelectSingleNode("//route/leg").ChildNodes
If nodeRoute.BaseName = "step" Then
strInstructions = strInstructions & nodeRoute.SelectSingleNode("html_instructions").Text & " - " & nodeRoute.SelectSingleNode("distance/text").Text & vbCrLf
End If
Next
strInstructions = CleanHTML(strInstructions) 'Removes MetaTag information from HTML result to convert to plain text.
Else
strError = .SelectSingleNode("//status").Text
GoTo errorHandler
End If
End With
gglDirectionsResponse = True
GoTo CleanExit
errorHandler:
If strError = "" Then strError = Err.Description
strDistance = -1
strTravelTime = "00:00"
strInstructions = ""
gglDirectionsResponse = False
CleanExit:
Set objDOMDocument = Nothing
Set objXMLHttp = Nothing
End Function
Function getGoogleTravelTime(ByVal strFrom, ByVal strTo) As String
'Returns the journey time between strFrom and strTo
Dim strTravelTime As String
Dim strDistance As String
Dim strInstructions As String
Dim strError As String
If gglDirectionsResponse(strFrom, strTo, strTravelTime, strDistance, strInstructions, strError) Then
getGoogleTravelTime = strTravelTime
Else
getGoogleTravelTime = strError
End If
End Function
Function getGoogleDistance(ByVal strFrom, ByVal strTo) As String
'Returns the distance between strFrom and strTo
'where strFrom/To are address search terms recognisable by Google
'i.e. Postcode, address etc.
Dim strTravelTime As String
Dim strDistance As String
Dim strError As String
Dim strInstructions As String
If gglDirectionsResponse(strFrom, strTo, strTravelTime, strDistance, strInstructions, strError) Then
getGoogleDistance = strDistance
Else
getGoogleDistance = strError
End If
End Function
Function getGoogleDirections(ByVal strFrom, ByVal strTo) As String
'Returns the directions between strFrom and strTo
'where strFrom/To are address search terms recognisable by Google
'i.e. Postcode, address etc.
Dim strTravelTime As String
Dim strDistance As String
Dim strError As String
Dim strInstructions As String
If gglDirectionsResponse(strFrom, strTo, strTravelTime, strDistance, strInstructions, strError) Then
getGoogleDirections = strInstructions
Else
getGoogleDirections = strError
End If
End Function
Thank you,
Przemek