(不定期更新)使用VBA解決 excel web 查詢無法匯入、匯入太慢的股市資料

oliwa wrote:
如下是騰訊的收盤價 , 想要把它全部轉出來使用 , 謝謝 !!
https://stockapp.finance.qq.com/mstats/#mod=list&id=ssa&module=SS&type=ranka



就如mickmini(1030樓),說的一樣,資料來源網址是https://qt.gtimg.cn/




Sub qq()

Dim Xmlhttp As Object, Url As String, StockName As String, stock, temp, i As Integer, r As Long
Set Xmlhttp = CreateObject("msxml2.xmlhttp")

Cells.Clear
Application.ScreenUpdating = False
Range("a1:m1") = Array("代碼", "名稱", "最新價", "漲跌幅", "漲跌額", "買入", "賣出", "成交量", "成交額", "今開", "昨收", "最高", "最低")


'StockName = "sh688700" 'test
'StockName = "sh688700,sh688609" 'test
StockName = "sh688700,sh603529,sh605259,sz300134,sz300076,sz300649,sz300235,sh688579"
'股票代碼用,(逗點)區隔,不確定是否能一次查詢超過80筆,請自行測試
'如果代碼數量太多,建議改用迴圈處理

Url = "https://qt.gtimg.cn/q=" & StockName

With Xmlhttp
.Open "GET", Url, False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Cache-Control", "no-cache"
.setRequestHeader "Pragma", "no-cache"
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.send

stock = Split(.Responsetext, ";")

r = 1
For i = 0 To UBound(stock) - 1
temp = Split(stock(i), "~")
r = r + 1
Cells(r, 1) = temp(2)
Cells(r, 2) = temp(1)
Cells(r, 3) = temp(3)
Cells(r, 4) = temp(32) & "%"
Cells(r, 5) = temp(31)
Cells(r, 6) = temp(19)
Cells(r, 7) = temp(3)
Cells(r, 8) = temp(36)
Cells(r, 9) = temp(37)
Cells(r, 10) = temp(5)
Cells(r, 11) = temp(4)
Cells(r, 12) = temp(33)
Cells(r, 13) = temp(34)
Next i

End With

Cells.EntireColumn.AutoFit
Application.ScreenUpdating = True

Set Xmlhttp = Nothing

End Sub



oliwa
好 , 我試試看 , 謝謝 !!
Snare版主好,我將下載的數據分別寫入數個資料庫供取用,現在遇到難題,爬了很多文章都沒能得到解決,我希望將字串轉為代碼運行(如附件--建立資料庫連結),再煩請您不吝指導,謝謝。

[點擊下載]
Dylan67 wrote:
我將下載的數據分別寫入數個資料庫供取用,現在遇到難題,爬了很多文章都沒能得到解決,我希望將字串轉為代碼運行(如附件--建立資料庫連結)


正常情況下,您不能把整串程式碼都用字串代替
這種寫法通常用在寫bat、vbscript、匯入用的bas(模組)... 等等
例如:
Sub test()
Open "c:\test.bat" For Output As #1
Print #1, "echo off"
Print #1, "echo 一二三abc"
Print #1, "echo 四五六def"
Print #1, "pause"
Close #1
Shell "c:\test.bat", vbNormalFocus
End Sub



access資料庫,不一定要分檔案,如果規劃好,也可以合併在一起
無論如何一定要同時開啟多資料庫,可定義多物件
例如:

Sub test1()

Dim DB1 As Object, RS1 As Object, DB2 As Object, RS2 As Object
Dim TargetA As String, TargetB As String, Sql1 As String, Sql2 As String

Set DB1 = CreateObject("ADODB.Connection")
Set DB2 = CreateObject("ADODB.Connection")
Set RS1 = CreateObject("ADODB.Recordset")
Set RS2 = CreateObject("ADODB.Recordset")

TargetA = ThisWorkbook.Path & "\aaa.accdb"
TargetB = ThisWorkbook.Path & "\bbb.accdb"

Sql1 = "sql的程式碼"
Sql2 = "sql的程式碼"

DB1.Open "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & TargetA & ";"
RS1.Open Sql1, DB1, 3, 3
DB2.Open "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & TargetA & ";"
RS2.Open Sql2, DB2, 3, 3

Sheets("工作表1").Cells.Clear
Sheets("工作表1").Cells(1, 1).CopyFromRecordset RS1
Sheets("工作表2").Cells.Clear
Sheets("工作表2").Cells(1, 1).CopyFromRecordset RS2

RS1.Close
RS2.Close
DB1.Close
DB2.Close

Set RS1 = Nothing
Set RS2 = Nothing
Set DB1 = Nothing
Set DB2 = Nothing


End Sub



輪流開啟,可用call副程式處理
例如:
Sub test2()

Call test3(ThisWorkbook.Path & "\aaa.accdb", "sql的程式碼", "工作表1")
Call test3(ThisWorkbook.Path & "\bbb.accdb", "sql的指令碼", "工作表2")

End Sub


Sub test3(TargetDb As String, SqlStr As String, Sheet_Name As String)

Dim DB As Object, RS As Object
Set DB = CreateObject("ADODB.Connection")
Set RS = CreateObject("ADODB.Recordset")

DB.Open "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & TargetDb & ";"
RS.Open SqlStr, DB, 3, 3

Sheets(Sheet_Name).Cells.Clear
Sheets(Sheet_Name).Cells(1, 1).CopyFromRecordset RS

RS.Close
DB.Close

Set RS = Nothing
Set DB = Nothing


End Sub


以上DB.Open ... + RS.Open... 都是讀取,寫入要改用DB.Execute="sql的程式碼"
詳細sql語法,請自行google
Dylan67
謝謝Snare版主的回覆,我原本就是按您的說法做的,就是想到了[字串轉為代碼運行]的方式,自己上網查資料又試不出來,所以特來請教。
版大提供的範例 , 修改測試如下 , 可以抓出 100 筆以上資料 , 非常感謝 !!
不過目前抓資料較費時 , 100筆至少要 10 min ........


Sub qq2()

On Error Resume Next
Sheets("temp").Activate
If Err Then
'新增temp工作表
Sheets.Add(after:=Sheets(Sheets.Count)).Name = "temp"
Else
Sheets("temp").Select
Sheets("temp").Cells.Clear
End If
On Error GoTo 0


Dim Xmlhttp As Object, Url As String, StockName As String, stock, temp, i As Integer, r As Long
Set Xmlhttp = CreateObject("msxml2.xmlhttp")

Cells.Clear
Application.ScreenUpdating = False
'Range("a1:m1") = Array("代碼", "名稱", "最新價", "漲跌幅", "漲跌額", "買入", "賣出", "成交量", "成交額", "今開", "昨收", "最高", "最低")
Range("a1:m1") = Array("代碼", "名稱", "最新價", "漲跌額")


'StockName = "sh688700" 'test
'StockName = "sh688700,sh688609" 'test
'StockName = "sh688700,sh603529,sh605259,sz300134,sz300076,sz300649,sz300235,sh688579,sz000001"
'股票代碼用,(逗點)區隔,不確定是否能一次查詢超過80筆,請自行測試
'如果代碼數量太多,建議改用迴圈處理

StockName = "sz300001,sz000001"
For i = 3 To 500
'MsgBox Format(i, "000000")
StockName = StockName & "," & "sz" & CStr(Format(i, "000000"))
'MsgBox StockName
Next


Url = "https://qt.gtimg.cn/q=" & StockName

With Xmlhttp
.Open "GET", Url, False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Cache-Control", "no-cache"
.setRequestHeader "Pragma", "no-cache"
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.send

stock = Split(.Responsetext, ";")

r = 1
Sheets("temp").Select
Range(Cells(1, 1), Cells(10000, 1)).NumberFormatLocal = "@"

For i = 0 To UBound(stock) - 1
temp = Split(stock(i), "~")
r = r + 1
Cells(r, 1) = temp(2)
Cells(r, 2) = temp(1)
Cells(r, 3) = temp(3)
'Cells(r, 4) = temp(32) & "%"
Cells(r, 4) = temp(31)
'Cells(r, 6) = temp(19)
'Cells(r, 7) = temp(3)
'Cells(r, 8) = temp(36)
'Cells(r, 9) = temp(37)
'Cells(r, 10) = temp(5)
'Cells(r, 11) = temp(4)
'Cells(r, 12) = temp(33)
'Cells(r, 13) = temp(34)
Next i

End With

Cells.EntireColumn.AutoFit
Application.ScreenUpdating = True

Set Xmlhttp = Nothing

End Sub
oliwa wrote:
不過目前抓資料較費時 , 100筆至少要 10 min ........


這個下載時間很奇怪,我測試250筆(10個迴圈),總時間還不到1秒




用您的程式碼,只有加上計時,其它一字未改,也是不到1秒

版大 , 我找到原因了 ,
因我主程式檔案中有 7 百多的 sheets , 所以執行超慢的 ;
我另開一個新檔 , 僅執行這個部分 , 幾乎是秒完成 ;
後續我應該要分拆程式到不同檔案中 , 這樣執行才會快也正常 , 想想看.... ;
謝謝版大 !!
版大 , 又要來請益了 ,
那個騰訊收盤價 , 套入全部資料去下載時 , 它一次只能下載 500 筆資料 ,
利用廻圈設定資料範圍時 , 因為代碼中有跳號 , 無法直接設定一,二個廻圈下載 , 再加上 500 筆限制 ,
這個抓資料的廻圈變多且不好維護 ,
另外找到二個網址 , 直接由交易所去抓收盤價 ,
http://www.szse.cn/market/trend/index.html
http://www.tfzq.com/www.sse.com.cn/market/price/report/
分別是深圳及上海交易所的 , 可以協助找下載資料的URL + request嘛 ? 謝謝 !!
oliwa wrote:
利用廻圈設定資料範圍時 , 因為代碼中有跳號 , 無法直接設定一,二個廻圈下載 , 再加上 500 筆限制 ,
這個抓資料的廻圈變多且不好維護


建立一個新工作表,在a欄放入全部有效股票代碼

不要用程式產生股票代碼,就可以避免跳號的問題
您1034樓的程式碼可修改如下
(那個"sz",也可以直接放在股票代碼工作表中)

'寫法大約如下
for i=1 to n ' 請自行算出n值,要跑幾個500
StockName = ""
For j = 1 To 500
r=r+1
If StockName = "" Then StockName = sheets("股票代碼的工作表").cells(r,1) Else StockName = StockName & "," & sheets("股票代碼的工作表").cells(r,1)
Next j
cell 下載資料(stockname)
next i

sub 下載資料(stockname as string )
Url = "https://qt.gtimg.cn/q=" & StockName
………
end sub


oliwa wrote:
http://www.tfzq.com/www.sse.com.cn/market/price/report/


這個跟騰訊一樣,要有股票代碼

(20210621修正,看錯來源,以上錯誤,www.tfzq.com不需股票代碼)
回傳資料的網址是 http://yunhq.sse.com.cn:32041//v1……… ,格式是json



但是一次一頁,全部下載要79次
去騰訊(幾個迴圈) 或 http://www.szse.cn(一次下載),反而比較方便


oliwa wrote:
http://www.szse.cn/market/trend/index.html


下載方式,請參考200樓範例
檔案為標準xlsx,開啟方式,請參考此樓其它範例、或google

#If VBA7 Then
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" _
Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, _
ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
#Else
Private Declare Function URLDownloadToFile Lib "urlmon" _
Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, _
ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
#End If



Sub TEST()
'日期暫訂2021-06-18
Dim Url As String, Target As String

Target = "d:\excel\" '暫存目錄
If Dir(Target, vbDirectory) = "" Then MkDir Target
'注意,暫存目錄下的檔案,會在無任何提示下刪除
If Dir(Target & "*.*") <> "" Then Kill Target & "*.*"
Url = "http://www.szse.cn/api/report/ShowReport?SHOWTYPE=xlsx&CATALOGID=1815_stock&TABKEY=tab1&txtBeginDate=2021-06-18&txtEndDate=2021-06-18&radioClass=00,20,30&txtSite=all"

URLDownloadToFile 0, Url, Target & "股票行情.xlsx", 0, 0


End Sub


版大 , 依您的範例 , 完成如下 ,
執行 Update_test 即可 ,
sz資料用檔案轉出 , 而sh資料則用每500筆讀取後寫在前sz的資料後累加上 , 今日測試可以運作 , 感謝 !!

另外 http://www.tfzq.com/www.sse.com.cn/market/price/report/ , 原本回覆是單頁下載要 79 頁 ,
這部分程式可以分享嘛 ? 我想要試試 ,
在前面整合後下載資料中 , stocklist 資料要不定時維護新增或刪除的 , 若能由此網站中直接轉出來就可以不用去維護 stocklist ,

這個 sh 網站中沒有整筆轉檔資料 , 我會提意見是否可以增加 , 因為 sz 網頁中有這功能 !!

再次感謝版本協助 !!








'Option Explicit
'#If VBA7 Then
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" _
Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, _
ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
'#Else
'Private Declare Function URLDownloadToFile Lib "urlmon" _
Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, _
ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
'#End If



Sub TEST()
'日期暫訂2021-06-18
Dim Url As String, Target As String, StockName As String, S_date, E_date As String
Dim i, j, LastRow As Integer

S_date = Year(Date) & "-" & Month(Date) & "-" & Day(DateAdd("d", -2, Date))
E_date = Year(Date) & "-" & Month(Date) & "-" & Day(Date)

Target = "c:\excel\" '暫存目錄
If Dir(Target, vbDirectory) = "" Then MkDir Target
'注意,暫存目錄下的檔案,會在無任何提示下刪除
'If Dir(Target & "*.*") <> "" Then Kill Target & "*.*"

'"http://www.szse.cn/api/report/ShowReport?SHOWTYPE=xlsx&CATALOGID=1815_stock&TABKEY=tab1&txtBeginDate=2021-06-18&txtEndDate=2021-06-18&radioClass=00,20,30&txtSite=all

'Url = "http://www.szse.cn/api/report/ShowReport?SHOWTYPE=xlsx&CATALOGID=1815_stock&TABKEY=tab1&txtBeginDate=2021-06-22&txtEndDate=2021-06-22&radioClass=00,20,30&txtSite=all"

Url = "http://www.szse.cn/api/report/ShowReport?SHOWTYPE=xlsx&CATALOGID=1815_stock&TABKEY=tab1&txtBeginDate=" & S_date & "&txtEndDate=" & E_date & "&radioClass=00,20,30&txtSite=all"


URLDownloadToFile 0, Url, Target & "股票行情.xlsx", 0, 0


End Sub

Sub Update_test()

Dim Xmlhttp As Object, Url As String, StockName As String, stock, temp, i As Double, r As Long
Set Xmlhttp = CreateObject("msxml2.xmlhttp")

Application.ScreenUpdating = False

Call TEST


On Error Resume Next
Sheets("temp").Activate
If Err Then
'新增temp工作表
Sheets.Add(after:=Sheets(Sheets.Count)).Name = "temp"
Else
Sheets("temp").Select
Sheets("temp").Cells.Clear
End If
On Error GoTo 0


Workbooks.Open ("c:\excel\股票行情.xlsx")
Sheets("股票行情").Activate

Cells.Select
Selection.Copy
Windows("SZ_SH收盤價").Activate
Sheets("temp").Select
Cells.Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False

'關閉及刪除 股票行情.xlsx
Application.DisplayAlerts = False
Workbooks("股票行情.xlsx").Close
On Error Resume Next '有錯誤時不理會它, 繼續下一行程式碼
Kill ("c:\excel\股票行情.xlsx") '找不到檔案時會有錯誤
Application.DisplayAlerts = True

LastRow = Sheets("stocklist").Cells(1, "A").End(xlDown).Row

For i = 0 To Int(LastRow / 500)

SotckName = ""
For j = 1 + i * 500 To 500 + i * 500
StockName = StockName & "," & "sh" & Sheets("stocklist").Cells(j, 1)
Next j

Url = "https://qt.gtimg.cn/q=" & StockName

With Xmlhttp
.Open "GET", Url, False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Cache-Control", "no-cache"
.setRequestHeader "Pragma", "no-cache"
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.send

stock = Split(.Responsetext, ";")


With Sheets("temp")
.Select
LastRow = .Cells(1, "B").End(xlDown).Row


Range(Cells(LastRow, 2), Cells(LastRow + 500, 2)).NumberFormatLocal = "@"

r = LastRow
For k = 0 To UBound(stock) - 1
temp = Split(stock(k), "~")
r = r + 1
Cells(r, 2) = temp(2)
Cells(r, 3) = temp(1)
Cells(r, 5) = temp(3)
Cells(r, 6) = temp(31)
Next k

End With

End With




Cells.EntireColumn.AutoFit
Application.ScreenUpdating = True

Set Xmlhttp = Nothing

Next i

End Sub
oliwa wrote:
另外 http://www.tfzq.com/www.sse.com.cn/market/price/report/ , 原本回覆是單頁下載要 79 頁 ,
這部分程式可以分享嘛 ?


網頁上資料量每頁限制 0~25、25~50、50~75……到最後一頁
http://yunhq.sse.com.cn... ... .... ... begin=0&end=25... ...

但經測試在yunhq.sse.com.cn查詢時,限制有放寬
0~500=>oK
0~1000=>不行
接近2000筆的資料,最多只要4次下載,詳細上限請自行測試

http://yunhq.sse.com.cn... ... .... ... begin=0&end=500... ...





' 0~500 筆,簡易範例,500~最後一筆,請自行改寫

Sub tfzq()

Dim Xmlhttp As Object, JsonData As Object, temp, Url As String, i As Integer, r As Long

Set Xmlhttp = CreateObject("msxml2.xmlhttp")
Set JsonData = CreateObject("HtmlFile")
' JsonData.write …… 這行因語法關係無法正常顯示,請到1024樓copy


Cells.Clear
Application.ScreenUpdating = False
Range("a1:m1") = Array("序號", "證券代碼", "證券簡稱", "類型", "最新", "漲跌幅", "漲跌", "成交量(手)", "成交額(萬元)", "前收", "開盤", "最高", "最低")


Url = "http://yunhq.sse.com.cn:32041//v1/sh1/list/exchange/equity?select=code,name,open,high,low,last,prev_close,chg_rate,volume,amount,tradephase,change,amp_rate,cpxxsubtype,cpxxprodusta&order=&begin=0&end=500&_="

With Xmlhttp

.Open "GET", Url & ((Now() - #1/1/1970 8:00:00 AM#) * 86400), False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Cache-Control", "no-cache"
.setRequestHeader "Pragma", "no-cache"
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.send


Set decodejson = JsonData.JsonParse(.responsetext)

'debug
MsgBox "資料合計:" & CallByName(decodejson, "total", VbGet) & "筆" & vbNewLine & _
"日 期:" & CallByName(decodejson, "date", VbGet) & vbNewLine & _
"時 間:" & CallByName(decodejson, "time", VbGet), vbOKOnly, "debug"


For i = 0 To CallByName(CallByName(decodejson, "list", VbGet), "length", VbGet) - 1
temp = Split(CallByName(CallByName(decodejson, "list", VbGet), i, VbGet), ",")

Cells(i + 2, 1) = i + 1
Cells(i + 2, 2) = temp(0)
Cells(i + 2, 3) = temp(1)
'cells(i+2,4)="i don't know"
Cells(i + 2, 5) = temp(5)
Cells(i + 2, 6) = temp(7) & "%"
Cells(i + 2, 7) = temp(11)
Cells(i + 2, 8) = temp(8)
Cells(i + 2, 9) = temp(9)
Cells(i + 2, 10) = temp(6)
Cells(i + 2, 11) = temp(2)
Cells(i + 2, 12) = temp(3)
Cells(i + 2, 13) = temp(4)

Next i


End With

Cells.EntireColumn.AutoFit
Application.ScreenUpdating = True

Set Xmlhttp = Nothing
Set JsonData = Nothing

End Sub

oliwa
版大 , 這行出現 Set decodejson = JsonData.JsonParse(.responsetext) , 物件不支援此屬件或方法 !!
文章分享
評分
評分
複製連結
請輸入您要前往的頁數(1 ~ 157)

今日熱門文章 網友點擊推薦!