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 文档中的第一组坐标。

听起来您正在寻找比仅仅在标签中匹配“<”和“>”更强大的东西。在使用 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.DocumentBuilderhttps://www.openoffice.org/api/docs/common/ref/com/sun/star/xml/dom/DocumentBuilder.html

关于你的问题:每个 result 都有一个 geometry 和一个 locationlocation中的latlng将是近似的latlng或几何中心。其他 latlng 是视口或边界。

例如德国柏林:

  <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 中的 latlng

但是还有其他问题。如果有多个结果怎么办?比如柏林,不仅仅是德国的首都。

所以我的示例函数 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