Google OpenOffice Calc 中的地图地理编码 API VBA
Google Maps geocoding API in OpenOffice Calc VBA
对于我的项目,我需要对一组我想知道其 GPS 坐标的位置进行地理编码。
位置的数量对于手动来说太大了,但也不会太多,这样我就不会遇到 Google 使用地理编码 API 的限制问题。
对我来说最方便的方法是使用 OpenOffice Calc。
我发现 VBA code 可以满足我的需要:
Function GetGeoData(sSearch as String) as String
If Len(sSearch) = 0 Then Exit Function 'we dont need empty cells <img draggable="false" class="emoji" alt="" src="http://s.w.org/images/core/emoji/72x72/1f609.png">
URL = "http://maps.googleapis.com/maps/api/geocode/xml?sensor=true&address=" 'we will use the google maps api
URL = URL & sSearch 'create the searchstring
oSimpleFileAccess = createUnoService( "com.sun.star.ucb.SimpleFileAccess" ) 'this is the Sefvice in getting the data from the web
On Error GoTo ErrorResponse
oInputStream = oSimpleFileAccess.openFileRead(URL) 'use the URL
oTextStream = createUnoService("com.sun.star.io.TextInputStream") 'get the data from the web
oTextStream.InputStream = oInputStream 'this is the data
aDelimiters = Array(ASC(">"),ASC("<")) 'as the stream is segmented with ">" and "<"
sLastString = ""
Do While NOT oTextStream.isEOF 'go through the google output
sThisString = oTextStream.readString(aDelimiters,True)
Select Case sLastString 'now search for the entries
Case "lat": 'latitudes
sLat = sThisString
Case "lng": 'longitude
sLon = sThisString
End Select
sLastString = sThisString
Loop
GetGeoData = " Longitude: " & sLon & " Latitude: " &sLat 'this is our output in the new cell
oInputStream.closeInput()
Exit Function
ErrorResponse:
GetGeoData = "no values found!!!"
End Function
然而,虽然精确地址很好,但当涉及 Google 称为多边形的定居点时,就会出现问题。在这种情况下,代码只保留它在 xml 信息中找到的最后一组坐标,但这对应于多边形的东北角。我很乐意拥有多边形的中心,它对应于 Google 地图生成的 xml 文档中的第一组坐标。
- 任何人都可以向我解释如何 select xml 中的特定节点
基于此代码的文件?
- 另一个解决方案是只保留第一组坐标。
听起来您正在寻找比仅仅在标签中匹配“<”和“>”更强大的东西。在使用 XML 时经常会发生这种情况,并且有许多专门的库可以完成此任务。
解析 XML 可以在 OpenOffice Basic 中使用 com.sun.star.xml.sax.Parser 界面完成。有关详细信息,请参阅 https://wiki.openoffice.org/wiki/XML_and_Filter。
或者,许多语言都有 XML 解析库。 Java 和 Python 有 XML 解析库,也可以与 OpenOffice 一起使用。我个人在 OpenOffice 中使用最多的库是 xml.dom.minidom.
首先:永远不要只把XML
当作文本字符串。 XML
具有需要解析的有意义的数据结构。幸运的是,Openoffice API 已经提供了一个 XML
解析器。 com.sun.star.xml.dom.DocumentBuilder
https://www.openoffice.org/api/docs/common/ref/com/sun/star/xml/dom/DocumentBuilder.html
关于你的问题:每个 result
都有一个 geometry
和一个 location
。 location
中的lat
、lng
将是近似的lat
、lng
或几何中心。其他 lat
、lng
是视口或边界。
例如德国柏林:
<geometry>
<location>
<lat>52.5200066</lat>
<lng>13.4049540</lng>
</location>
<location_type>APPROXIMATE</location_type>
<viewport>
<southwest>
<lat>52.3396296</lat>
<lng>13.0891553</lng>
</southwest>
<northeast>
<lat>52.6754542</lat>
<lng>13.7611176</lng>
</northeast>
</viewport>
<bounds>
<southwest>
<lat>52.3396296</lat>
<lng>13.0891553</lng>
</southwest>
<northeast>
<lat>52.6754542</lat>
<lng>13.7611176</lng>
</northeast>
</bounds>
</geometry>
因此只需要 location
中的 lat
、lng
。
但是还有其他问题。如果有多个结果怎么办?比如柏林,不仅仅是德国的首都。
所以我的示例函数 returns 所有结果:
Function GetGeoData(sSearch as String) as String
sResult = ""
if len(sSearch) > 0 and sSearch <> "0" then
sURI = "http://maps.googleapis.com/maps/api/geocode/xml?sensor=true&address="
sURI = sURI & sSearch
oDocumentBuilder = createUnoService("com.sun.star.xml.dom.DocumentBuilder")
oDOMDocument = oDocumentBuilder.parseURI(sURI)
oResults = oDOMDocument.getElementsByTagName("result")
for i = 0 to oResults.length -1
oResult = oResults.item(i)
oformattedAddress = oResult.getElementsByTagName("formatted_address").item(0)
sformattedAddress = oformattedAddress.getFirstChild().nodeValue
oGeometry = oResult.getElementsByTagName("geometry").item(0)
oLocation = oGeometry.getElementsByTagName("location").item(0)
oLat = oLocation.getElementsByTagName("lat").item(0)
sLat = oLat.getFirstChild().nodeValue
oLng = oLocation.getElementsByTagName("lng").item(0)
sLng = oLng.getFirstChild().nodeValue
if i = 0 then
sResult = sResult & sformattedAddress & ": Lat:" & sLat & " Lng:" & sLng
else
sResult = sResult & "; " & sformattedAddress & ": Lat:" & sLat & " Lng:" & sLng
end if
next
end if
GetGeoData = sResult
End Function
对于我的项目,我需要对一组我想知道其 GPS 坐标的位置进行地理编码。
位置的数量对于手动来说太大了,但也不会太多,这样我就不会遇到 Google 使用地理编码 API 的限制问题。
对我来说最方便的方法是使用 OpenOffice Calc。
我发现 VBA code 可以满足我的需要:
Function GetGeoData(sSearch as String) as String
If Len(sSearch) = 0 Then Exit Function 'we dont need empty cells <img draggable="false" class="emoji" alt="" src="http://s.w.org/images/core/emoji/72x72/1f609.png">
URL = "http://maps.googleapis.com/maps/api/geocode/xml?sensor=true&address=" 'we will use the google maps api
URL = URL & sSearch 'create the searchstring
oSimpleFileAccess = createUnoService( "com.sun.star.ucb.SimpleFileAccess" ) 'this is the Sefvice in getting the data from the web
On Error GoTo ErrorResponse
oInputStream = oSimpleFileAccess.openFileRead(URL) 'use the URL
oTextStream = createUnoService("com.sun.star.io.TextInputStream") 'get the data from the web
oTextStream.InputStream = oInputStream 'this is the data
aDelimiters = Array(ASC(">"),ASC("<")) 'as the stream is segmented with ">" and "<"
sLastString = ""
Do While NOT oTextStream.isEOF 'go through the google output
sThisString = oTextStream.readString(aDelimiters,True)
Select Case sLastString 'now search for the entries
Case "lat": 'latitudes
sLat = sThisString
Case "lng": 'longitude
sLon = sThisString
End Select
sLastString = sThisString
Loop
GetGeoData = " Longitude: " & sLon & " Latitude: " &sLat 'this is our output in the new cell
oInputStream.closeInput()
Exit Function
ErrorResponse:
GetGeoData = "no values found!!!"
End Function
然而,虽然精确地址很好,但当涉及 Google 称为多边形的定居点时,就会出现问题。在这种情况下,代码只保留它在 xml 信息中找到的最后一组坐标,但这对应于多边形的东北角。我很乐意拥有多边形的中心,它对应于 Google 地图生成的 xml 文档中的第一组坐标。
- 任何人都可以向我解释如何 select xml 中的特定节点 基于此代码的文件?
- 另一个解决方案是只保留第一组坐标。
听起来您正在寻找比仅仅在标签中匹配“<”和“>”更强大的东西。在使用 XML 时经常会发生这种情况,并且有许多专门的库可以完成此任务。
解析 XML 可以在 OpenOffice Basic 中使用 com.sun.star.xml.sax.Parser 界面完成。有关详细信息,请参阅 https://wiki.openoffice.org/wiki/XML_and_Filter。
或者,许多语言都有 XML 解析库。 Java 和 Python 有 XML 解析库,也可以与 OpenOffice 一起使用。我个人在 OpenOffice 中使用最多的库是 xml.dom.minidom.
首先:永远不要只把XML
当作文本字符串。 XML
具有需要解析的有意义的数据结构。幸运的是,Openoffice API 已经提供了一个 XML
解析器。 com.sun.star.xml.dom.DocumentBuilder
https://www.openoffice.org/api/docs/common/ref/com/sun/star/xml/dom/DocumentBuilder.html
关于你的问题:每个 result
都有一个 geometry
和一个 location
。 location
中的lat
、lng
将是近似的lat
、lng
或几何中心。其他 lat
、lng
是视口或边界。
例如德国柏林:
<geometry>
<location>
<lat>52.5200066</lat>
<lng>13.4049540</lng>
</location>
<location_type>APPROXIMATE</location_type>
<viewport>
<southwest>
<lat>52.3396296</lat>
<lng>13.0891553</lng>
</southwest>
<northeast>
<lat>52.6754542</lat>
<lng>13.7611176</lng>
</northeast>
</viewport>
<bounds>
<southwest>
<lat>52.3396296</lat>
<lng>13.0891553</lng>
</southwest>
<northeast>
<lat>52.6754542</lat>
<lng>13.7611176</lng>
</northeast>
</bounds>
</geometry>
因此只需要 location
中的 lat
、lng
。
但是还有其他问题。如果有多个结果怎么办?比如柏林,不仅仅是德国的首都。
所以我的示例函数 returns 所有结果:
Function GetGeoData(sSearch as String) as String
sResult = ""
if len(sSearch) > 0 and sSearch <> "0" then
sURI = "http://maps.googleapis.com/maps/api/geocode/xml?sensor=true&address="
sURI = sURI & sSearch
oDocumentBuilder = createUnoService("com.sun.star.xml.dom.DocumentBuilder")
oDOMDocument = oDocumentBuilder.parseURI(sURI)
oResults = oDOMDocument.getElementsByTagName("result")
for i = 0 to oResults.length -1
oResult = oResults.item(i)
oformattedAddress = oResult.getElementsByTagName("formatted_address").item(0)
sformattedAddress = oformattedAddress.getFirstChild().nodeValue
oGeometry = oResult.getElementsByTagName("geometry").item(0)
oLocation = oGeometry.getElementsByTagName("location").item(0)
oLat = oLocation.getElementsByTagName("lat").item(0)
sLat = oLat.getFirstChild().nodeValue
oLng = oLocation.getElementsByTagName("lng").item(0)
sLng = oLng.getFirstChild().nodeValue
if i = 0 then
sResult = sResult & sformattedAddress & ": Lat:" & sLat & " Lng:" & sLng
else
sResult = sResult & "; " & sformattedAddress & ": Lat:" & sLat & " Lng:" & sLng
end if
next
end if
GetGeoData = sResult
End Function