-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGetDataModule.bas
More file actions
294 lines (233 loc) · 9.43 KB
/
GetDataModule.bas
File metadata and controls
294 lines (233 loc) · 9.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
Attribute VB_Name = "GetDataModule"
Option Explicit
'
' GetRecentDataFromYahoo v2.00
' (c) Wei Mu - https://github.com/mason1900
'
' Last update: 04/21/2019
'
' Requires the following references:
' Microsoft WinHTTP Services
' Microsoft Scripting Runtime
'
' Make sure VBA-JSON ("JsonConverter") module is included in your workbook.
'
' Tested on Microsoft Office 365 Only. It may work for other versions. such as Office 2016.
' The current version of this software does not work on Mac.
'
' Change history:
' 1. Use options API instead of the old Yahoo Finance quote API v7
' which is much more stable.
'
' 2. Major change: Use VBA-JSON to parse JSON response. VBA-JSON is published under MIT License
' which is a very permissive license. The MIT License of VBA-JSON is attached in the spreadsheet.
' Link to VBA-JSON project: https://github.com/VBA-tools/VBA-JSON
' Note: it requires Tools|References|Microsoft Scripting Runtime
'
' 3. Added assetProfile module to output Sector and Industry.
'
'
Const intMaxJsonResponseFields = 75
Const intMaxFields_assetProfile = 30
Private Sub extractJSON_old(strTicker As String, Optional rngOutput As Range)
'============================================================================
'
' This is no longer in use since ver 2.00
'
'============================================================================
'Ref:
'http://gergs.net/2018/01/near-real-time-yahoo-stock-quotes-excel/
Dim URL As String, response As String, stripped As String, inbits() As String, i As Long
Dim myRange As Range
Dim request As WinHttp.WinHttpRequest ' needs Tools|References|Microsoft WinHTTP Services
On Error GoTo Err
If rngOutput Is Nothing Then
Set rngOutput = ThisWorkbook.Sheets("GetRecentDataFromYahoo").Range("JSONstart")
End If
URL = "https://query2.finance.yahoo.com/v7/finance/quote?symbols=" & Trim(strTicker)
Set request = New WinHttp.WinHttpRequest
With request
.Open "GET", URL, False
.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"
.Send
.WaitForResponse (10)
response = .ResponseText
End With
' For debugging purpose
' To read JSON response, Notepad++ with JSTool plugin is recommended
' See https://sourceforge.net/projects/jsminnpp/
' Call exportJSON(response)
If InStr(response, """result"":[]") <> 0 Then GoTo Err ' ticker not found
'kludge parse: strip JSON delimiters and quotes
stripped = Replace(Replace(Replace(Replace(Replace(response, "[", ""), "]", ""), "{", ""), "}", ""), """", "")
'stripped = Replace(stripped, ":", ":,") ' keep colons for readability, but make them delimit
stripped = Replace(stripped, ":", ",")
inbits = Split(stripped, ",") ' split
Set myRange = rngOutput
i = LBound(inbits)
Do While i <= UBound(inbits)
myRange.Offset((i Mod 2), i \ 2).Value = Trim(inbits(i))
i = i + 1
Loop
Exit Sub
Err:
Debug.Print "extractJSON_old Failed!" + strTicker
End Sub
Private Sub RefreshRecentPrice()
Dim i As Integer
Dim myRange As Range
Dim myDestRange As Range
Dim strTicker As String
On Error Resume Next
With ThisWorkbook.Sheets("GetRecentDataFromYahoo")
i = 1
Do Until .Range("YHRecentTickerHeading").Offset(i, 0).Row = .Range("YHRecentTickerEnding").Row
Set myRange = .Range("YHRecentTickerHeading").Offset(i, 0)
If myRange.Value <> "" Then
strTicker = Trim(myRange.Value)
Set myDestRange = .Range("JSONstart").Offset(2 * i - 2, 0)
Call extractJSON(strTicker, myDestRange)
Set myDestRange = .Range("assetProfileStart").Offset(2 * i - 2, 0)
Call extractJSON(strTicker, rngOutput:=myDestRange, strModuleName:="assetProfile")
End If
i = i + 1
Loop
End With
End Sub
Private Sub extractJSON(strTicker As String, Optional rngOutput As Range, Optional strModuleName As String = "default")
'=============================================================================
' Version 2.00 update
' Change history:
'
' 1. Use options API instead of the old Yahoo Finance quote API v7
' which is much more stable.
'
' 2. Use VBA-JSON to parse JSON response. VBA-JSON is published under MIT License
' which is a very permissive license.
' Link to VBA-JSON project: https://github.com/VBA-tools/VBA-JSON
' Note: it also requires Tools|References|Microsoft Scripting Runtime
'
' 3. Added assetProfile module.
'
' Version 2.01 update
'
' 1. Added 'On Error' statement
'
'==============================================================================
Dim strURL As String
Dim strResponse As String
Dim myRange As Range
Dim request As WinHttp.WinHttpRequest ' needs Tools|References|Microsoft WinHTTP Services
Dim Parsed As Object ' needs Microsoft Scripting Runtime
Dim jsonNode As Object
Dim QuoteKey As Variant
Dim QuoteValue As Variant
Dim OutputValues As Variant
Dim i As Integer
On Error GoTo ExtractFail
If rngOutput Is Nothing Then
Set rngOutput = ThisWorkbook.Sheets("GetRecentDataFromYahoo").Range("JSONstart")
End If
If strModuleName = "default" Then
strURL = "https://query2.finance.yahoo.com/v7/finance/options/" & Trim(strTicker)
ElseIf strModuleName = "assetProfile" Then
strURL = "https://query2.finance.yahoo.com/v10/finance/quoteSummary/" & Trim(strTicker) & "?modules=assetProfile"
Else
GoTo ExtractFail
End If
Set request = New WinHttp.WinHttpRequest
With request
.Open "GET", strURL, False
.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"
.Send
.WaitForResponse (10)
strResponse = .ResponseText
End With
' Call exportJSON(strResponse)
If strModuleName = "default" Then
Set Parsed = JsonConverter.ParseJson(strResponse)
If Parsed("optionChain")("result").Count = 0 Then
GoTo ExtractFail
End If
'Debug.Print Parsed("optionChain")("result")(1)("quote").Count
Set jsonNode = Parsed("optionChain")("result")(1)("quote")
ReDim OutputValues(2, jsonNode.Count)
i = 0
For Each QuoteKey In jsonNode
On Error Resume Next
'Debug.Print QuoteKey
QuoteValue = jsonNode(QuoteKey)
'Debug.Print QuoteValue
OutputValues(0, i) = QuoteKey
OutputValues(1, i) = QuoteValue
i = i + 1
Next QuoteKey
With ThisWorkbook.Worksheets("GetRecentDataFromYahoo")
.Range(rngOutput, rngOutput.Offset(1, intMaxJsonResponseFields)).Clear
.Range(rngOutput, rngOutput.Offset(1, UBound(OutputValues, 2) - 1)) = OutputValues
End With
ElseIf strModuleName = "assetProfile" Then
Set Parsed = JsonConverter.ParseJson(strResponse)
If IsNull(Parsed("quoteSummary")("result")) Then
GoTo ExtractFail
End If
Set jsonNode = Parsed("quoteSummary")("result")(1)("assetProfile")
ReDim OutputValues(2, jsonNode.Count)
i = 0
For Each QuoteKey In jsonNode
On Error Resume Next
If TypeName(jsonNode(QuoteKey)) <> "Collection" Then
'Debug.Print QuoteKey
QuoteValue = jsonNode(QuoteKey)
'Debug.Print QuoteValue
OutputValues(0, i) = QuoteKey
OutputValues(1, i) = QuoteValue
Else
'Debug.Print QuoteKey
End If
i = i + 1
Next QuoteKey
With ThisWorkbook.Worksheets("GetRecentDataFromYahoo")
.Range(rngOutput, rngOutput.Offset(1, intMaxFields_assetProfile)).Clear
.Range(rngOutput, rngOutput.Offset(1, UBound(OutputValues, 2) - 1)) = OutputValues
End With
End If
Set request = Nothing
Exit Sub
ExtractFail:
Debug.Print "extractJSON Failed!" + strTicker
End Sub
Private Sub exportJSON(strResponse As String)
' Unit test
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim oFile As Object
Set oFile = fso.CreateTextFile("D:\vba-JSON.txt")
oFile.WriteLine strResponse
oFile.Close
Set fso = Nothing
Set oFile = Nothing
End Sub
Private Sub testJSON()
'unit test
'Call extractJSON_old("IBM")
'Call extractJSON("AAPL")
'Call extractJSON("AAPLxxxxx")
'Call extractJSON("SND")
With ThisWorkbook.Worksheets("GetRecentDataFromYahoo")
Call extractJSON("AAPL", rngOutput:=.Range("assetProfileStart"), strModuleName:="assetProfile")
End With
End Sub
Sub btnClearRecentData()
Dim response As Variant
response = MsgBox("Clear recent data?", _
vbQuestion + vbYesNoCancel + vbDefaultButton1, "Info")
If response = vbNo Or response = vbCancel Then Exit Sub
With ThisWorkbook.Sheets("GetRecentDataFromYahoo")
.Range("JSONResponseArea").Clear
.Range("JSONResponseArea_asset").Clear
End With
End Sub
Sub btnRefreshRecentPrice()
Call RefreshRecentPrice
End Sub