该问题与Get Google Maps XML data, parse it and input to Excel cells部分相关。在上一个问题中,解决方案是遍历每个链接和输入值。我发现,可以调用多个起点和目的地,并从Google Maps获取XML文件中的所有内容。现在,这是一种用于获取数据的巨大XML。我需要获得1 hour 30 mins
之类的持续时间,以及103 km
之类的距离。这怎么可能?
当我只有5个不同的变体时,为什么还有25个XML响应?
这是我的VBA:
Sub GetMyValuesGoogleAPI()
Dim URL As String
Dim originsParam As String
Dim destinationsParam As String
Dim APIkey As Range, TravelMode As Range
Dim xmlDoc As DOMDocument30
Dim origins(0 To 4) As String
Dim destinations(0 To 4) As String
Dim n As Integer
n = FreeFile()
Open Environ$("USERPROFILE") & "\Desktop\" & "test.txt" For Output As #n
origins(0) = "London, UK"
origins(1) = "Manchester, UK"
origins(2) = "Liverpool, UK"
origins(3) = "Bristol, UK"
origins(4) = "Bath, UK"
destinations(0) = "Cambridge, UK"
destinations(1) = "Leeds, UK"
destinations(2) = "Cambridge, UK"
destinations(3) = "Norwich, UK"
destinations(4) = "Brighton, UK"
Set APIkey = ThisWorkbook.Worksheets("Other Data").Range("CE1")
Set TravelMode = ThisWorkbook.Worksheets("Other Data").Range("BY3")
Set xmlDoc = New DOMDocument30
originsParam = Join(origins, "|")
destinationsParam = Join(destinations, "|")
URL = "https://maps.googleapis.com/maps/api/distancematrix/xml?origins=" & Escape(originsParam) & "&destinations=" _
& Escape(destinationsParam) & "&mode=" & TravelMode & "&key=" & APIkey
With xmlDoc
.async = False
.Load URL
Debug.Print .XML
Print #n, .XML
End With
End Sub
功能:
Public Function Escape(ByVal param As String) As String
Dim i As Integer, BadChars As String
BadChars = "%<>=&!@#$^()+{[}]|\;:'"",/?"
For i = 1 To Len(BadChars)
param = Replace(param, Mid(BadChars, i, 1), "%" & Hex(Asc(Mid(BadChars, i, 1))))
Next
param = Replace(param, " ", "+")
Escape = param
End Function
这是XML输出:
<?xml version="1.0"?>
<DistanceMatrixResponse>
<status>OK</status>
<origin_address>London, UK</origin_address>
<origin_address>Manchester, UK</origin_address>
<origin_address>Liverpool, UK</origin_address>
<origin_address>Bristol, UK</origin_address>
<origin_address>Bath, UK</origin_address>
<destination_address>Cambridge, UK</destination_address>
<destination_address>Leeds, UK</destination_address>
<destination_address>Cambridge, UK</destination_address>
<destination_address>Norwich, UK</destination_address>
<destination_address>Brighton, UK</destination_address>
<row>
<element>
<status>OK</status>
<duration>
<value>5420</value>
<text>1 hour 30 mins</text>
</duration>
<distance>
<value>103024</value>
<text>103 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>13268</value>
<text>3 hours 41 mins</text>
</duration>
<distance>
<value>313516</value>
<text>314 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>5420</value>
<text>1 hour 30 mins</text>
</duration>
<distance>
<value>103024</value>
<text>103 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>8674</value>
<text>2 hours 25 mins</text>
</duration>
<distance>
<value>189805</value>
<text>190 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>6696</value>
<text>1 hour 52 mins</text>
</duration>
<distance>
<value>103629</value>
<text>104 km</text>
</distance>
</element>
</row>
<row>
<element>
<status>OK</status>
<duration>
<value>12617</value>
<text>3 hours 30 mins</text>
</duration>
<distance>
<value>301588</value>
<text>302 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>3723</value>
<text>1 hour 2 mins</text>
</duration>
<distance>
<value>71765</value>
<text>71.8 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>12617</value>
<text>3 hours 30 mins</text>
</duration>
<distance>
<value>301588</value>
<text>302 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>15640</value>
<text>4 hours 21 mins</text>
</duration>
<distance>
<value>336098</value>
<text>336 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>16712</value>
<text>4 hours 39 mins</text>
</duration>
<distance>
<value>417143</value>
<text>417 km</text>
</distance>
</element>
</row>
<row>
<element>
<status>OK</status>
<duration>
<value>13457</value>
<text>3 hours 44 mins</text>
</duration>
<distance>
<value>312942</value>
<text>313 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>5458</value>
<text>1 hour 31 mins</text>
</duration>
<distance>
<value>117472</value>
<text>117 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>13457</value>
<text>3 hours 44 mins</text>
</duration>
<distance>
<value>312942</value>
<text>313 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>17245</value>
<text>4 hours 47 mins</text>
</duration>
<distance>
<value>409544</value>
<text>410 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>17253</value>
<text>4 hours 48 mins</text>
</duration>
<distance>
<value>437125</value>
<text>437 km</text>
</distance>
</element>
</row>
<row>
<element>
<status>OK</status>
<duration>
<value>11371</value>
<text>3 hours 10 mins</text>
</duration>
<distance>
<value>269123</value>
<text>269 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>12344</value>
<text>3 hours 26 mins</text>
</duration>
<distance>
<value>333320</value>
<text>333 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>11344</value>
<text>3 hours 9 mins</text>
</duration>
<distance>
<value>272045</value>
<text>272 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>14866</value>
<text>4 hours 8 mins</text>
</duration>
<distance>
<value>386263</value>
<text>386 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>10533</value>
<text>2 hours 56 mins</text>
</duration>
<distance>
<value>254730</value>
<text>255 km</text>
</distance>
</element>
</row>
<row>
<element>
<status>OK</status>
<duration>
<value>11688</value>
<text>3 hours 15 mins</text>
</duration>
<distance>
<value>264172</value>
<text>264 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>13467</value>
<text>3 hours 44 mins</text>
</duration>
<distance>
<value>352919</value>
<text>353 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>11662</value>
<text>3 hours 14 mins</text>
</duration>
<distance>
<value>267094</value>
<text>267 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>15183</value>
<text>4 hours 13 mins</text>
</duration>
<distance>
<value>381312</value>
<text>381 km</text>
</distance>
</element>
<element>
<status>OK</status>
<duration>
<value>10850</value>
<text>3 hours 1 min</text>
</duration>
<distance>
<value>249779</value>
<text>250 km</text>
</distance>
</element>
</row>
</DistanceMatrixResponse>
答案 0 :(得分:1)
请考虑XSLT,这是一种专用语言,旨在将XML文件转换为最终使用格式,包括其他XML文件,HTML文件甚至文本文件。在这里,XSLT可以将您的 DistanceMatrixResult 结构转换为CSV格式,并带有需要的标题和数据行,以将其导入Excel电子表格。 Office库MSXML(您已经使用过)可以运行XSLT 1.0脚本。
您收到25个 请求的原因是每个5个原始站点和5个目标站点(5*5
)的成对匹配。每个行是一对配对(即英国伦敦到所有五个目的地)。在XSLT中相应地映射这些配对。顺便说一句,忘记解析文本,而使用值代替,其中 duration 以秒为单位,距离以米为单位。甚至XSLT都将数学转换转换为十进制小时和十进制公里!
XSLT (另存为.xsl文件,特殊的.xml文件,以便在VBA中读取)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="DistanceMatrixResponse">
<xsl:text>origin_address,destination_address,duration,distance
</xsl:text>
<xsl:apply-templates select="row"/>
</xsl:template>
<xsl:template match="row">
<xsl:variable name="row_pos"><xsl:value-of select="position()"/></xsl:variable>
<xsl:for-each select="element">
<xsl:variable name="elem_pos"><xsl:value-of select="position()"/></xsl:variable>
<xsl:variable name="quot">"</xsl:variable>
<xsl:value-of select="concat($quot, ancestor::DistanceMatrixResponse/origin_address[position() = $row_pos], $quot, ',',
$quot, ancestor::DistanceMatrixResponse/destination_address[position() = $elem_pos], $quot, ',',
format-number(duration/value div 3600, '##.####'), ',',
format-number(distance/value div 100, '##.####'))"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
VBA
Public Sub RunXSLTtoCSV()
Dim xmlDoc As New MSXML2.DOMDocument30, xslDoc As New MSXML2.DOMDocument30
Dim txtOutput As String, csvfile As String
' LOAD XML AND XSL
xmlDoc.Load "C:\Path\To\Google\Maps\API\Response.xml"
xmlDoc.async = False
xslDoc.Load "C:\Path\To\XSLT\Script.xsl"
xslDoc.async = False
' TRANSFORM TO TEXT
txtOutput = xmlDoc.transformNode(xslDoc)
' SAVE TO CSV (TO IMPORT INTO EXCEL)
csvfile = "C:\Path\To\CSV\File.csv"
Open csvfile For Output As #1
Print #1, txtOutput
Close #1
Set xslDoc = Nothing
Set xmlDoc = Nothing
End Sub
输出