• 156

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

菜鳥提問目前都是用很簡單的巨集但是很雷因此請益
Q1:每小時固定下載資料複製彙整到檔案A.xls 。檔名:自動彙整_(固定名稱)2022080820:00.Xls(變數)。 是否可只尋找前面固定字串動作。
Q2:動作完成刪除 自動彙整_2020080820:00.xls。
Q3:A.xls儲存格變動時執行outlook.application
snare
snare 樓主

您發了2篇一樣的,有高手在另一篇回答您了

2022-08-18 20:44
又來打擾S大,請問S大一個小小問題:
在GOOGLE試算表中Apps Scrip的程式編輯器.可以寫出類似S大曾PO文(下圖)


簡言之,可以GOOGLE試算表寫出類似EXCEL VBA抓一個網頁功能?
謝謝S大,感恩你無私.
snare
snare 樓主

google 有內建函數 IMPORTXML、IMPORTHTML、IMPORTDATA、IMPORTFEED、GOOGLEFINANCE,可以抓沒保護的網頁,使用方式請google,有很多範例

2022-09-29 19:41
g80860

謝謝S大

2022-09-30 8:40
好久沒碰VBA,這東西太久沒碰真的就不行了..
師傅救命...
這是我之前的小程式,抓日期列表供其他程式取用的
---------------------
Sub get_ccdate()
Dim sca_date
RETRY:
Set ccxml = CreateObject("msxml2.xmlhttp")
On Error GoTo RETRY
With ccxml
.Open "POST", "https://www.tdcc.com.tw/smWeb/QryStockAjax.do", False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "Referer", "https://www.tdcc.com.tw/smWeb/QryStock.jsp"
.send "REQ_OPR=qrySelScaDates"

sca_date = Split(Replace(Replace(.responsetext, "[", ""), "]", ""), ",")

ReDim ccdate(UBound(sca_date))
For i = 0 To UBound(sca_date)
ccdate(i) = Replace(sca_date(i), """", "")
Next i
Erase sca_date
End With
End Sub
---------------------
但上周好像改版了
從舊文挖到
---------------------
.Open "GET", "https://www.tdcc.com.tw/portal/zh/smWeb/qryStock", False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0"
.send

Html.body.innerhtml = .responsetext
SYNCHRONIZER_TOKEN = Html.getElementbyid("SYNCHRONIZER_TOKEN").Value
firDate = Html.getElementbyid("scaDate").innertext
---------------------
firdate可以抓出日期,但是是未分割的
因為之前也是看不懂要怎麼分割,對這邊是真的沒轍...
希望師傅可以指點一下~~
bioleon69 wrote:
但上周好像改版了


集保戶股權分散表,早在7月就改版了
只是舊版網頁還保留一段時間

bioleon69 wrote:
firdate可以抓出日期,但是是未分割的




詳細請參考1246樓、1247樓、1257樓

一、

firdate=Split(Trim(HTML.getElementById("scaDate").innertext), " ")





二、

debug.print Html.getElementById("scaDate")(0).innertext
debug.print Html.getElementById("scaDate")(1).innertext
debug.print Html.getElementById("scaDate")(2).innertext
...
...
...


三、




dim firDate as object,test
Set firDate = Html.getElementById("scaDate")
For Each test In firDate
Debug.Print test.innertext
Next

snare wrote:
集保戶股權分散表,早(恕刪)


好像是大改版了....
之前的都要重寫
謝謝師傅~~!!!!!


[點擊下載]

Snare大神:
我在下載數據後,經常會遇到類似1.屏東[市]轉[巿]的問題,
在數據清洗時,這還可以用Replace方式替換,
可是在2.台糖[𠄞]街轉台糖[二]街時,試了好多方法都行不通,
Len()表示有2個字元,Char()是?號,
我Google發現,可能是漢字ASCII轉Unicode的問題,
想請教怎麼把[𠄞]替換成[二],
或是有更聰明的方法,在數據下載後能有個什麼模組,
將下載數據進行全部自動替換,
否則我每次都是對這些特定自符,
Replace、Replace、Replace...一堆
感謝版主
Dylan67 wrote:
我Google發現,可能是漢字ASCII轉Unicode的問題,
想請教怎麼把[𠄞]替換成[二],
或是有更聰明的方法,在數據下載後能有個什麼模組,
將下載數據進行全部自動替換,


原因是字串裡面混了unicode編碼的字
編碼是對的,它只是不同字
轉了編碼它還是不同字,不然就是變??
所以沒辦法用一次轉整個檔案的方式

但一次性取代字元是可以的
只不過要用ascw() 或 unicode() 函數,自建轉換用的參考資料庫






公式解法(新版excel),可用unichar()處理打不出來的字
h3=UNICODE(C3)
i3=UNICHAR(H3)
j3=SUBSTITUTE(SUBSTITUTE(B3,UNICHAR(24063),"市"),UNICHAR(131358),"二")


vba解法(舊版excel只能用ascw、chrw)





因為地址不會出現?(問號)
可用下面簡單方式檢查字串中是否有雙字元的unicode


Sub test()

Dim i As Integer, j As Integer, s As String

Range("b:b").Interior.Pattern = xlNone

For i = 3 To 6 'b3~b6
s = Cells(i, 2)
For j = 1 To Len(s)
If Asc(Mid(s, j, 1)) = 63 And InStr(s, "?") = 0 Then
Cells(i, 2).Interior.Color = vbGreen
Exit For
End If
Next j
Next i

End Sub


Dylan67

謝謝Snare大神:您提供的簡單模組,解決了我目視檢查的困擾,起到近視延緩加深的作用,以前只會用ChrW,現在學會用Unichar,特別感謝您

2022-10-27 19:28
在麻辣看到一篇用Selenium抓資料的文章
有人想抓yahoo 股市分類行情裡面的資料
https://tw.stock.yahoo.com/class-quote?sectorId=1&exchange=TAI

裡面有38個分類




可是yahoo 股市分類行情,這個網頁有個特性
一次只顯示30筆,如果有分類超過30筆
需要下拉、捲動網頁,才會再次送出資料,沒辦法一次抓完

萬一該分類資料太多
像是分類中的
市認購,1萬9千多筆
市認售,5千多筆








用Selenium,就會變成
模擬下拉(換頁、捲動) => 等資料 => 模擬下拉(換頁、捲動) => 等資料 ......
自己除於30看看有多可怕,而且還有漲跌符號無法正確複制的問題


所以寫一個xmlhttp範例給各位參考

'程式碼放在模組裡,執行main()

Dim Request_denied As Boolean, prid As String
Sub main()

Dim i As Integer, Detail, ttt As Double

Detail = Array("1", "2", "3", "4", "6", _
"7", "37", "38", "9", "10", _
"11", "12", "13", "40", "41", _
"42", "43", "44", "45", "46", _
"47", "19", "20", "21", "22", _
"24", "39", "25", "26", "29", _
"48", "49", "30", _
"33", "51", "52")
'預設下載36個分類,31、32這2個未加入
'31=市認購,32=市認售
'市認購+市認售,約2萬5千筆資料,需要100~200秒,太花時間







'只下載36個分類,大約只要8秒
'如果需要31、32,請自行加入上面Detail 陣列中,也可自行刪減不要的項目






Application.ScreenUpdating = False

ttt = Timer
Request_denied = False
prid = ""

For i = 0 To UBound(Detail)
Call get_stock_classification(Detail(i))
If Request_denied = True Then
MsgBox "Request denied", vbOKOnly, "Error"
Exit Sub
End If
Next i

Application.ScreenUpdating = True

Debug.Print "total time:" & Timer - ttt & "s"

End Sub



Sub get_stock_classification(sectorId)

Dim Xmlhttp As Object, Jsondata As Object, Json, temp, URL As String, offset As Variant, sectorName As String, nextOffset As Variant, check As Boolean, Detail, resultsTotal As String, ttt As Double

Set Jsondata = CreateObject("HtmlFile")
Set Xmlhttp = CreateObject("msxml2.xmlhttp")





On Error Resume Next

ttt = Timer
offset = 0
check = True
Detail = Array("symbolName", "symbol", "bid", "change", "changePercent", "regularMarketOpen", "regularMarketPreviousClose", "regularMarketDayHigh", "regularMarketDayLow", "volumeK", "regularMarketTime")

If prid = "" Then

With Xmlhttp
.Open "GET", "https://tw.stock.yahoo.com/class-quote?sectorId=1&exchange=TAI", False
.setRequestHeader "Cache-Control", "no-cache"
.setRequestHeader "Pragma", "no-cache"
.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.send
prid = Split(Split(.responsetext, """prid"":""")(1), """,""region""")(0)
End With

End If


Do

URL = "https://tw.stock.yahoo.com/_td-stock/api/resource/StockServices.getClassQuotes;exchange=TAI;offset=" & offset & ";sectorId=" & sectorId & "?bkt=&device=desktop&ecma=modern&feature=ecmaModern,useNewQuoteTabColor&intl=tw&lang=zh-Hant-TW&partner=none&prid=" & prid & "®ion=TW&site=finance&tz=Asia/Taipei&ver=1.2.1506&returnMeta=true"


With Xmlhttp

.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"
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.send
If Left(.responsetext, 14) = "Request denied" Then
Request_denied = True
Exit Sub
End If
Set Json = CallByName(Jsondata.JsonParse(.responsetext), "data", VbGet)
nextOffset = CallByName(CallByName(Json, "pagination", VbGet), "nextOffset", VbGet)
resultsTotal = CallByName(CallByName(Json, "pagination", VbGet), "resultsTotal", VbGet)
Set Json = CallByName(Json, "list", VbGet)
sectorName = CallByName(CallByName(Json, 0, VbGet), "sectorName", VbGet)

End With

If check = True Then

If checksheet(sectorName) = False Then
Sheets.Add(After:=Sheets(Sheets.Count)).Name = sectorName
End If

Sheets(sectorName).Cells.Clear
Sheets(sectorName).Range("a1:k1") = Array("股票名稱", "代號", "股價", "漲跌", "漲跌幅(%)", "開盤", "昨收", "最高", "最低", "成交量 (張)", "時間")
check = False

End If

With Sheets(sectorName)
For i = 0 To CallByName(Json, "length", VbGet) - 1
DoEvents
Set temp = CallByName(Json, i, VbGet)
For j = 1 To 11
If InStr("346789", j) = 0 Then
.Cells(i + 2 + offset, j) = CallByName(temp, Detail(j - 1), VbGet)
Else
.Cells(i + 2 + offset, j) = CallByName(temp, Detail(j - 1), VbGet).raw
End If
Next j
If .Cells(i + 2 + offset, j - 1) <> "" And .Cells(i + 2 + offset, j - 1) <> "-" Then
.Cells(i + 2 + offset, j - 1) = DateAdd("h", 8, Replace(Replace(.Cells(i + 2 + offset, j - 1), "T", " "), "Z", ""))
End If

Call add_color(i + offset, sectorName)

Next i
End With

offset = nextOffset

Loop Until IsNull(nextOffset)

Sheets(sectorName).Columns.AutoFit
Sheets(sectorName).Range("c:e").Font.Bold = True

Debug.Print sectorId, sectorName, resultsTotal, Timer - ttt & "s"

Set Xmlhttp = Nothing
Set Jsondata = Nothing
Set Json = Nothing
Set temp = Nothing


End Sub

Function checksheet(sheet_name As String) As Boolean
Dim check As Range
On Error Resume Next
Set check = Sheets(sheet_name).Range("a1")
If Err.Number <> 0 Then checksheet = False Else checksheet = True
On Error GoTo 0
End Function


Sub add_color(r As Integer, sheet_name As String)

With Sheets(sheet_name)

If .Cells(r + 2, 4) <> "-" Then
Select Case .Cells(r + 2, 4)
Case Is > 0
.Range("c2:e2").offset(r, 0).Font.Color = vbRed
.Range("d2").offset(r, 0) = "▲" & .Range("d2").offset(r, 0)
.Range("e2").offset(r, 0) = "▲" & .Range("e2").offset(r, 0) * 100 & "%"
Case Is < 0
.Range("c2:e2").offset(r, 0).Font.Color = -11489280
.Range("d2").offset(r, 0) = Replace(.Range("d2").offset(r, 0), "-", "▼")
.Range("e2").offset(r, 0) = Replace(.Range("e2").offset(r, 0) * 100 & "%", "-", "▼")
End Select
End If

End With

End Sub









注意,不要太頻繁查詢,會擋ip的


[點擊下載]
derguey

原本:"price":"34.45" 改版後:"price":{"raw":"34.45","fmt":"34.45","sort":34.45}(已有解法,在1364樓)

2023-12-15 12:09
kurgman

我想請教在分類行情之下有四個大選項,我要怎麼知道他的網址呢?1.即時行情(這樓主要給了)2.法人買賣3.主力進出4.大戶籌碼不好意思謝謝

2025-01-12 15:43
請教snare大神
範例網址如下
http://5850web.moneydj.com/z/zc/zcr/zcra/zcra_3231.djhtm
用您之前的方法匯入資料
Set Table = HTML.all.tags("table")(1).Rows
temp = Split(Replace(Table(0).Cells(0).innertext, " / ", "/"), vbNewLine)
For i = 0 To UBound(temp)
temp(i) = Trim(temp(i))
Next i

End With

現在擷取的資料, 每個資料筆都會多一行空白隔開如下圖



有試著在資料寫入後再將空白列刪除
Range("A:A").SpecialCells(xlCellTypeBlanks).EntireRow.Delete

不過這樣遇到一個問題
就是參照這些資料的圖表, 經過刪除資料->匯入資料->刪除空白列 的步驟 會導致圖表讀取的資料錯亂

研究了好久還是想不出辦法
不知有無辦法可在資料匯入前 先將多的空白行處理掉?


謝謝
rainbowsperm wrote:
研究了好久還是想不出辦法
不知有無辦法可在資料匯入前 先將多的空白行處理掉?



原始資料本來就沒有空白行
您應該是程式寫錯




Sub getstock()

Dim URL As String, HTML As Object, GetXml As Object, i As Integer, temp
Set HTML = CreateObject("htmlfile")
Set GetXml = CreateObject("msxml2.xmlhttp")
URL = "https://5850web.moneydj.com/z/zc/zcr/zcra/zcra_3231.djhtm"

Sheets("工作表1").Cells.Clear

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"
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.send

HTML.body.innerhtml = .responsetext
Set Table = HTML.all.tags("table")(1).Rows

temp = Split(Replace(Replace(Table(0).Cells(0).innertext, " / ", "/"), """", ""), vbNewLine)
'temp = Split(Replace(Table(0).Cells(0).innertext, " / ", "/"), vbNewLine)

For i = 0 To UBound(temp)
Sheets("工作表1").Cells(i + 1, 1) = temp(i)
Next i

Sheets("工作表1").Columns("A:A").TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, Space:=True, Other:=False, TrailingMinusNumbers:=True

Sheets("工作表1").Columns.AutoFit

End With

Set HTML = Nothing
Set GetXml = Nothing

End Sub


  • 156
內文搜尋
X
評分
評分
複製連結
請輸入您要前往的頁數(1 ~ 156)
Mobile01提醒您
您目前瀏覽的是行動版網頁
是否切換到電腦版網頁呢?