在外部资源的帮助下,我获得了此代码,该代码可以获取经度和纬度并提取邮政编码。这是代码:
Public Function ReverseGeoCode(myInput1 As String, myInput2 As String) As String
'You will need to reference Microsoft XML, v6.0 object library
Dim XMLDoc As New DOMDocument60
Dim XMLNODE As IXMLDOMNode
Dim I As Long
Dim lat, lng, myAddress, myZipcode, reportZipcode As String
Dim splitAddress, splitZipcode As Variant
lat = myInput1
lng = myInput2
XMLDoc.Load "http://maps.googleapis.com/maps/api/geocode/xml?latlng=" & lat & "," & lng & " &sensor=false"
Do Until XMLDoc.readyState = 4
DoEvents
Loop
If Len(XMLDoc.Text) = 0 Then
Call MsgBox("No Data!")
Exit Function
End If
Set XMLNode = XMLDoc.SelectSingleNode("/GeocodeResponse/result/formatted_address")
For i= 0 To XMLNode.ChildNodes.Length - 1
myAddress = XMLNode.ChildNodes(i).Text
Next i
splitAddress = Split(myAddress, ",")
myZipcode = splitAddress(2)
myZipcode = Trim(myZipcode)
splitZipcode = Split(myZipcode, " ")
reportZipcode = splitZipcode(1)
reportZipcode = Trim(reportZipcode)
ReverseGeoCode = reportZipcode
End Function
因此该代码有效,而且我知道它可能不是最干净的。但是问题是当我在Excel工作表中使用“ = ReverseGeoCode(Cell1,Cell2)”调用它时。有时它可以正常工作,而其他时候它会产生返回“ #VALUE!”。我不确定为什么。我在下面附上一张图片,向您显示该错误的示例。有谁知道为什么会产生此错误?
答案 0 :(得分:1)
一般观察
:因此,请按照我在评论中所写的内容进行概述。
您不想使用用户定义函数。这样可以继续进行重复通话。您肯定会冒险在没有API密钥的情况下(可能有)达到API的调用限制;它效率低下,没有必要。而是编写一个您调用一次的子程序,该子程序将循环工作表中的所有必需单元格,并发出API调用并返回邮政编码。 API密钥是一种用于许多API调用的身份验证方法。您不应该顺便分享一下。
这些重复调用,可能会达到极限,而经常计算UDF的事实可能是您麻烦的根源。
出于效率考虑,首先从工作表中删除重复项,以避免不必要的呼叫。切换屏幕更新和其他任何方式,例如在执行时将CalculationMode设置为手动。
据我所读,一旦达到每日限额,您就需要一个API密钥。不确定免费版本或没有API密钥的API限制是什么。
Option Explicit
Public Sub ListZipCodes()
Dim lat As Double, longitude As Double
Const APIKEY As String = "yourAPIkey"
Application.ScreenUpdating = False '<==Speed up code when actually working with sheet
'Code to remove duplicates
'Code to loop sheet and call function on each input set of values
'Example call. These would be picked up from cells
lat = 40.714224
longitude = -73.961452
Debug.Print GetZipCode(lat, longitude, APIKEY)
Application.ScreenUpdating = True
End Sub
Public Function GetZipCode(ByVal lat As Double, ByVal longitude As Double, ByVal APIKEY As String) As String
Dim sResponse As String
With CreateObject("MSXML2.XMLHTTP")
Dim URL As String
URL = "https://maps.googleapis.com/maps/api/geocode/xml?latlng=" & lat & "," & longitude & "&key=" & APIKEY
.Open "GET", URL, False
.send
If .Status <> 200 Then
GetZipCode = "API call failed"
Exit Function
End If
Dim XMLDoc As New DOMDocument60, XMLNODE As IXMLDOMNode
XMLDoc.Load .responseBody
If Len(XMLDoc.Text) = 0 Then GetZipCode = "No data"
Set XMLNODE = XMLDoc.SelectSingleNode("/GeocodeResponse/result/formatted_address")
GetZipCode = Split(Trim$(Split(XMLNODE.Text, Chr$(44))(2)), Chr$(32))(1)
End With
End Function
调用JSON失败的原因是响应需要解码。这是重写为处理JSON响应的函数。
这需要下载JSONConverter,然后通过VBE>工具>引用导入并添加对Microsoft脚本运行时的引用。
下面的示例使用
运行latitude: 42.9865913391113,
longitude: -100.137954711914
VBA:
Public Function GetZipCode(ByVal lat As Double, ByVal longitude As Double, ByVal APIKEY As String) As String
Dim sResponse As String, json As Object
With CreateObject("MSXML2.XMLHTTP")
Dim URL As String, formattedAddress As String
URL = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" & lat & "," & longitude & "&key=" & APIKEY
.Open "GET", URL, False
.send
If .Status <> 200 Then
GetZipCode = "API call failed"
Exit Function
End If
Set json = JsonConverter.ParseJson(StrConv(.responseBody, vbUnicode))
formattedAddress = json("results").item(1)("formatted_address")
GetZipCode = Split(Trim$(Split(formattedAddress, Chr$(44))(2)), Chr$(32))(1)
End With
End Function
对于JSON请求,您返回的初始对象是字典,如解码响应中的开头"{"
所示:
即Set json = JsonConverter.ParseJson(StrConv(.responseBody, vbUnicode))
返回字典对象
从上面您可能会发现,字典中的感兴趣数据具有键"results"
。
可以使用json("results")
来访问它,它返回词典的集合。这由以下"["
表示,以供收集,随后由集合中第一个词典的开头表示,再次由"{"
表示。
我可以使用以下索引按索引获取集合中的第一本字典:
json("results").item(1)
对该词典中的键进行检查后发现,其中一个键就是我们所追求的"formatted_address"
。
它的关联值是原始数据类型;在这种情况下为字符串。这意味着我们可以使用键直接访问它(不返回另一个对象)。
formattedAddress = json("results").item(1)("formatted_address")
现在我们有了地址字符串,我们可以像以前一样解析它:
GetZipCode = Split(Trim$(Split(formattedAddress, Chr$(44))(2)), Chr$(32))(1)
尾注:
您可以使用Postman等工具来测试API调用,在这种情况下,请检查JSON响应。确实,要看看您将获得什么样的回应。
帮助:
建立项目,生成API密钥并开始使用非常快捷,容易。可能需要10分钟才能通读并执行。