使用VBA通过API Norges银行查找特定日期的汇率

时间:2018-09-28 11:10:48

标签: excel vba excel-vba web-scraping xmlhttprequest

我想使用VBA通过特定的日期使用Norges银行的API检索汇率。

我试图修改以前使用的代码以从另一个API检索数据,但是很遗憾,我无法使其工作。我已经能够获取API本身以在浏览器中检索所需的信息,但是我想要一个VBA代码,可以在其中自动检索这些汇率。

在下面的代码中,我试图查找特定日期XXX / NOK的汇率。

Public Function FX(FXdate As String, FXcurrency As String)
    Dim firstVal As String, secondVal As String, thirdVal As String
    firstVal = "https://data.norges-bank.no/api/data/EXR/B."
    secondVal = ".NOK.SP?format=sdmx-json&startPeriod="
    thirdVal = "&endPeriod="
    Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
    URL = firstVal & secondVal & thirdVal
    objHTTP.Open "GET", URL, False
    objHTTP.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
    objHTTP.send ("")
    Set regex = CreateObject("VBScript.RegExp"): regex.Pattern = """observations""*""([0-9])""": regex.Global = False
    Set matches = regex.Execute(objHTTP.responseText)
    tmpVal = Replace(matches(0).SubMatches(0), ".", Application.International(xlListSeparator))
    GetCurrency = CDbl(tmpVal)
 End Function

例如,如果我想要在2018年1月2日的SEK / NOK,则原始数据API返回以下数据。在此示例中,我希望VBA在“观察”之后返回值,在这种情况下为“ 99.46”。

{"header":{"id":"64ffd01684ad7f51ab197c573027a05f","prepared":"2018-09-28T09:33:13","test":false,"sender":{"id":"NB"},"receiver":{"id":"ANONYMOUS"}},"dataSets":[{"action":"Information","series":{"0:0:0:0":{"attributes":[0,0,0,0],"observations":{"0":["99.46"]}}}}],"structure":{"name":"Exchange rates","description":"Norges Bank exchange rate statistics","dimensions":{"dataset":[],"series":[{"id":"FREQ","name":"Frequency","description":"The time interval at which observations occur over a given time period.","keyPosition":0,"role":null,"values":[{"id":"B","name":"Business"}]},{"id":"BASE_CUR","name":"Base Currency","description":"The first currency in a currency pair quotation. Also known as the transaction currency.","keyPosition":1,"role":null,"values":[{"id":"SEK","name":"Swedish krona"}]},{"id":"QUOTE_CUR","name":"Quote Currency","description":"The second currency in a currency quote pair. Also known as counter currency.","keyPosition":2,"role":null,"values":[{"id":"NOK","name":"Norwegian krone"}]},{"id":"TENOR","name":"Tenor","description":"The amount of time left for the repayment of a loan or until a financial contract expires.","keyPosition":3,"role":null,"values":[{"id":"SP","name":"Spot"}]}],"observation":[{"id":"TIME_PERIOD","name":"Time Period","description":"The period of time or point in time to which the measured observation refers.","keyPosition":4,"role":"time","values":[{"start":"2018-01-02T00:00:00","end":"2018-01-02T00:00:00","id":"2018-01-02","name":"2018-01-02"}]}]},"attributes":{"dataset":[],"series":[{"id":"DECIMALS","name":"Decimals","description":"The number of digits to the right of a decimal point.","role":null,"values":[{"id":"2","name":"2"}]},{"id":"CALCULATED","name":"Calculated","description":"Indicates if the value is calculated or an actual observation.","role":null,"values":[{"id":"false","name":"false"}]},{"id":"UNIT_MULT","name":"Unit Multiplier","description":"Exponent in base 10 specified so that multiplying the observation numeric values by 10^UNIT_MULT gives a value expressed in the UNIT.","role":null,"values":[{"id":"2","name":"Hundreds"}]},{"id":"COLLECTION","name":"Collection Indicator","description":"Dates or periods during which the observations have been collected.","role":null,"values":[{"id":"C","name":"ECB concertation time 14:15 CET"}]}],"observation":[]}}}

有什么解决方法吗?

2 个答案:

答案 0 :(得分:1)

进行API调用:

在这里,您可以使用函数进行API调用并使用JSON parser获得结果。我本来可以使用Split self从响应文本中提取项目,但是已经在给出的​​答案中得到了证明,因此我将向您展示JSON解析。我添加了一个附加标头,以希望减轻浏览器提供的缓存结果。

您可以将JSON解析部分移至函数中,但我希望单独进行演示。

您没有在API调用的URL字符串中显示值的串联。

Option Explicit
Public Sub TEST()
    'https://data.norges-bank.no/api/data/EXR/B.SEK.NOK.SP?format=sdmx-json&startPeriod=2018-01-02&endPeriod=2018-01-02
    Dim json As Object
    Set json = JsonConverter.ParseJson(FX_json("2018-01-02", "SEK"))
    Debug.Print json("dataSets")(1)("series")("0:0:0:0")("observations")("0")(1)
End Sub

Public Function FX_json(ByVal FXdate As String, ByVal FXcurrency As String) As String
    Dim firstVal As String, secondVal As String, thirdVal As String, url As String
    firstVal = "https://data.norges-bank.no/api/data/EXR/B."
    secondVal = ".NOK.SP?format=sdmx-json&startPeriod="
    thirdVal = "&endPeriod="
    url = firstVal & FXcurrency & secondVal & FXdate & thirdVal & FXdate
    With CreateObject("MSXML2.ServerXMLHTTP")       
        .Open "GET", url, False
        .setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
        .setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
        .send
        FX_json = .responseText
    End With
End Function

JSON树视图:

这是感兴趣的项目的JSON树路径的视觉效果


参考:

在将JSONConverter.bas下载并添加到项目中之后,转到VBE>工具>参考,然后添加对Microsoft脚本运行时的参考。

答案 1 :(得分:0)

整个问题可以翻译成如何分割字符串?。可能有20多种不同的方式来做到这一点。从序列化和循环显示正确的属性,到使用search(),find(),向左,向右和拆分。

所以,这只是其中一种方法-假设您在excel的给定范围内拥有整个输入字符串,如下所示:

enter image description here

然后,您需要获取observations":{"0":["和下一个"之间的数据。

如果通过第一定界符将字符串拆分为数组,然后获取第二部分,则会实现此目的。然后再次用"分割,并采用第一部分:

使用一些硬编码不太容易,但是应该可以:

Sub TestMe()

    Dim inputTxt As String
    inputTxt = Worksheets(1).Range("A1")
    inputTxt = Split(inputTxt, "observations"":{""0"":[""")(1)
    inputTxt = Split(inputTxt, """")(0)
    Debug.Print inputTxt

End Sub

类似的问题: