這次yahoo改版,真是多災多難…這幾個月來,網頁一直變來變去的
目前是改成2021-06-08 1:30 1024樓,yahoo 範例的格式,猜測現在接近最終版
原理可去1024樓看,這裡不多做說明
(1024樓,因yahoo改版,range("b1")字串要重新整理)
(會的請自行修改,直接不要b1也行,其它下載功能都正常,有空我再改)
有人知道舊版的“張數”是對應新版網頁中的那一格嗎?
(經nijawang指導,張數問題已解決)
https://tw.stock.yahoo.com/q/q?s=2330


範例中的排版方式,維持舊版
避免有人用這個格式寫程式、公式,排版一變,那全部要重寫,很麻煩的
'程式碼放到模組裡
'暫時用on error resume next 做個簡單除錯,因為不知道網頁會不會再改
'各筆之間的下載時間延遲(Delaytick),好像可以不用,有需要請自行啟用
'fake_Multiplex() 副程式,也可改用1098樓寫法替換,不影響功能有興趣自行替換
Global DownloadError As Integer
Sub fake_Multiplex()
Dim i As Integer, j As Integer, LastRow As Integer, Firstdata As Integer, Lastdata As Integer, t As Double, ErrorStock As Integer
t = Timer
DownloadError = 0
LastRow = Sheets("stock").Range("a1").CurrentRegion.Rows.Count
Sheets("stock").Range("b2:l" & LastRow).Clear: Sheets("stock").Range("n1:n3") = ""
If LastRow Mod 5 > 0 Then j = Int(LastRow / 5) + 1 Else j = Int(LastRow / 5)
For i = 1 To j
DoEvents
If i = 1 Then Firstdata = 2 Else Firstdata = (i - 1) * 5 + 1
If i = j Then
Lastdata = LastRow
Else
Lastdata = (i - 1) * 5 + 5
End If
'修正nijawang 1097樓,發現的一個小bug,請自行修改附件中的程式碼
Sheets("stock").Range("n1") = "Loading " & Round((i / j) * 100) & "%"
Call getstock(Firstdata, Lastdata)
Next i
With Sheets("stock")
If DownloadError > 0 Then Call Redownload
If DownloadError > 0 Then .Range("n2") = DownloadError & " 下載失敗"
.Range("n1") = LastRow - 1 - DownloadError & " stock loading ok"
.Cells.EntireColumn.AutoFit
End With
Debug.Print Timer - t
End Sub
Sub Redownload()
If DownloadError = 0 Then Exit Sub
Dim i As Integer, LastRow As Integer
LastRow = Sheets("stock").Range("a1").CurrentRegion.Rows.Count
For i = 5 To 0 Step -1
Delaytick (1)
Sheets("stock").Range("n3") = DownloadError & "筆失敗=>" & i & "秒後,重新下載"
Next i
DownloadError = 0
Sheets("stock").Range("n3") = ""
For i = 2 To LastRow
If Sheets("stock").Cells(i, 2) = "下載失敗" Then
Sheets("stock").Cells(i, 2) = ""
Call getstock(i, i)
End If
Next i
End Sub
Sub getstock(Firstdata As Integer, Lastdata As Integer)
Dim URL As String, GetXml As Object, Jsondata As Object, DecodeJson, temp As String, DataTime As String, i As Integer, j As Integer, k As Integer
On Error Resume Next
For k = Firstdata To Lastdata
DoEvents
URL = "https://tw.stock.yahoo.com/q/q?s=" & Sheets("stock").Cells(k, 1)
Set GetXml = CreateObject("WinHttp.WinHttpRequest.5.1")
Set Jsondata = CreateObject("HtmlFile")

With GetXml
.Open "GET", URL, False
.setRequestHeader "Cache-Control", "no-cache"
.setRequestHeader "Pragma", "no-cache"
.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
.send
DataTime = Split(Split(.responsetext, "datatime=""")(1), """>")(0)
'(20210917,縮短split判斷用字串,避免部份格式不同的代碼無法下載)
temp = "{""quote"":{""data"":" & Split(Split(.responsetext, """quote"":{""data"":")(1), ",""orderbook"":")(0) & "}}}"
Set DecodeJson = CallByName(CallByName(Jsondata.JsonParse(temp), "quote", VbGet), "data", VbGet)
With Sheets("stock")
.Cells(k, 2) = CallByName(DecodeJson, "symbolName", VbGet)
.Cells(k, 3) = DataTime 'CallByName(DecodeJson, "regularMarketTime", VbGet)
.Cells(k, 4) = CallByName(DecodeJson, "price", VbGet)
.Cells(k, 5) = CallByName(DecodeJson, "bid", VbGet)
.Cells(k, 6) = CallByName(DecodeJson, "ask", VbGet)
.Cells(k, 7) = CallByName(DecodeJson, "changePercent", VbGet)
If .Cells(k, 7).Value > 0 Then .Cells(k, 7).Font.Color = -16776961 _
Else If .Cells(k, 7).Value < 0 Then .Cells(k, 7).Font.Color = -11489280
'.Cells(k, 8) ' i don't know
'(經nijawang指導,這行修正如下)
.Cells(k, 8) = CallByName(DecodeJson, "volume", VbGet)/1000
.Cells(k, 9) = CallByName(DecodeJson, "regularMarketPreviousClose", VbGet)
.Cells(k, 10) = CallByName(DecodeJson, "regularMarketOpen", VbGet)
.Cells(k, 11) = CallByName(DecodeJson, "regularMarketDayHigh", VbGet)
.Cells(k, 12) = CallByName(DecodeJson, "regularMarketDayLow", VbGet)
If .Cells(k, 2) = "" Then
.Cells(k, 2) = "下載失敗"
DownloadError = DownloadError + 1
End If
End With
End With
Set GetXml = Nothing
Set Jsondata = Nothing
Set DecodeJson = Nothing
'Delaytick (0.3)
Next k
End Sub
Sub Delaytick(setdelay As Single)
Dim StartTime As Double, NowTime As Double
StartTime = Timer * 100
setdelay = setdelay * 100
Do
NowTime = Timer * 100
DoEvents
Loop Until NowTime - StartTime > setdelay
End Sub
(經nijawang指導,張數問題已解決)
請自行修改附件中的程式碼
'.Cells(k, 8) ' i don't know
改成
.Cells(k, 8) = CallByName(DecodeJson, "volume", VbGet)/1000
如果有人想要用舊版的▲漲、▼跌,代替正負號

把這行
If .Cells(k, 7).Value > 0 Then .Cells(k, 7).Font.Color = -16776961 _
Else If .Cells(k, 7).Value < 0 Then .Cells(k, 7).Font.Color = -11489280
換成下面這幾行
'debug.print vartype(CallByName(DecodeJson, "changePercent", VbGet)) ' 8 = string
Dim changePercent As Double
changePercent = .Cells(k, 7)
If changePercent > 0 Then
.Cells(k, 7).Value = "▲" & changePercent * 100 & "%"
.Cells(k, 7).Font.Color = -16776961
ElseIf changePercent < 0 Then
.Cells(k, 7).Value = Replace(changePercent * 100, "-", "▼") & "%"
.Cells(k, 7).Font.Color = -11489280
End If
(20231215 網頁改版,請參考1364樓nijawang提出的修改方式,自行更新程式碼)
[點擊下載]