【问题标题】:Parsing JSON to Excel - LOOP将 JSON 解析为 Excel - LOOP
【发布时间】:2019-06-18 00:14:10
【问题描述】:

我有一个通过解析 JSON 来获取历史股票价格的代码。我需要在特定日期获得“收盘价”。我需要代码从 Excel 单元格中读取日期并粘贴与日期对应的价格。这是一个例子:

https://cloud.iexapis.com/stable/stock/AAPL/chart/1m?token=pk_98e61bb72fd84b7d8b5f19c579fd0d9d

以下是我的代码,但我需要对其进行修改,以便它可以循环查找所需的日期:

Sub getHistoricalData()
'Application.DisplayAlerts = False
Application.ScreenUpdating = False

Dim wb As Workbook
Dim ws As Worksheet
Dim rng As Range
Dim symbol As Variant
Dim n As Integer
Dim lastrow As Long
Dim myrequest As Variant
Dim i As Variant

Set wb = ActiveWorkbook
Set ws = Sheets("Sheet1")
ws.Activate

'Last row find
lastrow = ws.Cells(Rows.Count, "A").End(xlUp).Row

Set rng = ws.Range("A3:A" & lastrow)

'Clear Prior Prices
ws.Range("k3:k" & lastrow).ClearContents

n = 3

'Get Symbols list
For Each symbol In rng
    Set myrequest = CreateObject("WinHttp.WinHttpRequest.5.1")
    myrequest.Open "Get", "https://cloud.iexapis.com/stable/stock/" & symbol & "/chart/1m?token=pk_98e61bb72fd84b7d8b5f19c579fd0d9d" 'updated 06/15/2019
    'Debug.Print myrequest.ResponseText

    Dim Json As Object
    Set Json = JsonConverter.ParseJson(myrequest.ResponseText)

    'MsgBox (myrequest.ResponseText)
    i = Json("Close")
    ws.Range(Cells(n, 2), Cells(n, 2)) = i
    n = n + 1
Next symbol

ws.Columns("k").AutoFit
'MsgBox ("Data is downloaded.")

ws.Range("k3:k" & lastrow).HorizontalAlignment = xlGeneral
ws.Range("k3:k" & lastrow).NumberFormat = "$#,##0.00"

Application.DisplayAlerts = True
Application.ScreenUpdating = False

End Sub

例如,我需要提取每个股票代码在 06/06/2019 的收盘价。

【问题讨论】:

    标签: json excel vba


    【解决方案1】:

    Json 解析器将是一个理想的选择。但是,您也可以从响应中正则表达式并处理 http 错误的情况,即未成功连接到所需页面以及未找到日期的情况。我从单元格 A1 中读取日期。日期的格式明确为 yyyy-mm-dd。代码被读入一个循环的数组 - 这更快。结果存储在一个数组中并一次写入工作表 - 也更快。

    Option Explicit
    Public Sub GetClosePrices()
        Dim lastRow As Long, url As String, ws As Worksheet, tickers(), dateString As String
    
        Set ws = ThisWorkbook.Worksheets("Sheet1")
        With ws
            dateString = Format$(.Range("A1").Value, "yyyy-mm-dd")
            lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
            If lastRow >= 3 Then
               .Range("K3:K" & lastRow).ClearContents
                tickers = Application.Transpose(.Range("A3:A" & lastRow).Value)
            Else
               Exit Sub
            End If
        End With
    
        Dim s As String, re As Object, p As String, r As String, prices(), i As Long
        ReDim prices(1 To UBound(tickers))
    
        p = """DATE_HERE"",""open"":[0-9.]+,""close"":(.*?),"   'Format must be YYYY-MM-DD
        p = Replace$(p, "DATE_HERE", dateString)
        url = "https://cloud.iexapis.com/stable/stock/TICKER_HERE/chart/1m?token=pk_98e61bb72fd84b7d8b5f19c579fd0d9d"
        Set re = CreateObject("VBScript.RegExp")
    
        With CreateObject("MSXML2.XMLHTTP")
            For i = LBound(tickers) To UBound(tickers)
                .Open "GET", Replace$(url, "TICKER_HERE", tickers(i)), False
                .setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
                .send
                If .Status = 200 Then
                    s = .responseText
                    r = GetValue(re, s, p)
                Else
                    r = "Failed connection"
                End If
                prices(i) = r
            s = vbNullString
            Next
        End With
        ws.Cells(3, "K").Resize(UBound(prices), 1) = Application.Transpose(prices)
    End Sub
    
    Public Function GetValue(ByVal re As Object, ByVal inputString As String, ByVal pattern As String) As String
        With re
            .Global = True
            .pattern = pattern
            If .test(inputString) Then  ' returns True if the regex pattern can be matched agaist the provided string
                GetValue = .Execute(inputString)(0).submatches(0)
            Else
                GetValue = "Not found"
            End If
        End With
    End Function
    

    示例日期的正则表达式解释 (try it):

    【讨论】:

    【解决方案2】:

    JSON 响应是一组对象(由 VBA-JSON 库作为字典集合公开),因此您需要遍历它们并根据日期找到感兴趣的对象:

    Dim closePrice
    Set Json = JsonConverter.ParseJson(myrequest.ResponseText)
    For Each o in Json
        if o("date") = "2019-06-06" Then
            closePrice = o("close")
            exit for
        end if
    Next o
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多