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

justinyutw wrote:
會 Error 在 .PasteSpecial NoHTMLFormatting:=True
...(恕刪)

justinyutw wrote:
如果是使用 Debug 模式執行,則完全不會有 Error產生,並執行完畢。請問是和網路品質有關嗎或是哪個指令執行太慢了造成貼不過去?
...(恕刪)

這我無法回答,我用迴圈跑了幾千次都無法重現出您的錯誤
您可以試著把這行
.PasteSpecial NoHTMLFormatting:=True
改成
.Paste
試看看

單純資料可以不用nohtml,因為這棟樓的範例都是抓網頁資料
所以我才會一律用nohtml的功能

或是使用348樓的副程式
在貼上表格之前,稍微延遲一下程式的速度


justinyutw wrote:
雖然自己的方法不是很好,就是想要不超過65536下,一部份一部份的轉置。
...(恕刪)


這不是不好的方法,不用迴圈,在陣列中只取出想要的部分,是arraylist進階用法
我沒預料到有人只看msdn的說明,在google不到範例的情況下,自己想到這個方式
因為屬於特殊技巧,加上沒人認真看,所以一直都用arraylist的基本用法來寫範例

justinyutw wrote:
照著 ArrayList 的 msdn 說明,嘗試著新的指令,卻試不出來。
與其說要試出小量 Transpose,不如說是想知道遇到一個新指令,照著說明輸入指令,但還是Error,要如何才能改到好。
google只有 msdn 的說明,卻沒有人使用後的心得可供參考。
...(恕刪)


大部份的人,都不會深入了解,您google不到使用心得,很正常

msdn沒vba的寫法,arraylist是.net的功能,照著參數說明寫會出錯
不是所有的參數都可以正常用在vba
vba的寫法應該要用getrange + toarray


請看範例,使用f8逐行執行,試著自行理解
'======================================
Sub test5()

Cells.Clear


Dim DataArray As Object, TargetArray(), lastrow As Double
Set DataArray = CreateObject("System.Collections.ArrayList")


lastrow = 30

For i = 1 To lastrow
DataArray.Add i
Next i

Range(Cells(1, 1), Cells(1, lastrow)) = DataArray.toarray()

Range(Cells(1, 1), Cells(lastrow, 1)) = Application.Transpose(DataArray.toarray())


Dim Start As Integer '>=0 <=lastrow-1 , or as long as double ...
Dim N As Integer 'start+n <=lastrow , or as long as double ...


Start = 12: N = 7
TargetArray = DataArray.getrange(Start, N).toarray
Range(Cells(3, 5), Cells(3, 5 + N - 1)) = TargetArray


Start = 0: N = 4
TargetArray = DataArray.getrange(Start, N).toarray
Range(Cells(5, 5), Cells(5, 5 + N - 1)) = TargetArray

Start = 3: N = 10
TargetArray = DataArray.getrange(Start, N).toarray
Range(Cells(7, 5), Cells(7, 5 + N - 1)) = TargetArray

Start = 21: N = 8
TargetArray = DataArray.getrange(Start, N).toarray
Range(Cells(9, 5), Cells(9 + N - 1, 5)) = Application.Transpose(TargetArray)


Start = 15: N = 2
TargetArray = DataArray.getrange(Start, N).toarray
Range(Cells(9, 7), Cells(9 + N - 1, 7)) = Application.Transpose(TargetArray)

Start = 0: N = 30
TargetArray = DataArray.getrange(Start, N).toarray
Range(Cells(9, 9), Cells(9 + N - 1, 9)) = Application.Transpose(TargetArray)



Set DataArray = Nothing



End Sub

'======================================

請問先進
用範例抓Yahoo finance 台股大盤要用什麼代號呢
試^TWII之類的都不行
tsengca wrote:
用範例抓Yahoo finance 台股大盤要用什麼代號呢
試^TWII之類的都不行...(恕刪)


程式確定沒問題,^TWII 代號可以用






提示:

https://finance.yahoo.com/quote/^TWII/history?p=^TWII

stock = InputBox ………

最近用Web方式抓進來的海外ETF History變成無法運作…
得來好好學習一下。
蔬食抗暖化,減碳救地球!

snare wrote:
vba的寫法應該要用getrange + toarray...(恕刪)


感謝樓主的回覆
所以樓主也是從msdn一個一個試,才能知道哪個指令是可以使用囉?


另外請教樓主 #219 Sub TAIEX() 相關問題

(1)
Url = "http://mis.twse.com.tw/stock/api/getStockInfo.jsp?ex_ch=tse_t00.tw|otc_o00.tw|tse_FRMSA.tw&json=1&delay=0&_="

請問是否在其他的網頁,只要網址幾乎一樣時,就可以使用"|"一次抓取各個單一網址的資料。



(2)
Jsondata.write ""

1.
Jsondata.write ""
請問這行要如何修改,才能使這行能與樓主寫得功能一樣。


2.
這行使用匿名函式運算式,並將"值"指派給JsonParse,JsonParse 變數? 還是是函式名稱?

一般平常看到的具名函式如下圖,還有匿名函式。


雖然說看得懂,但就只是看得懂而以。
但比較想知道怎麼知道要document.JsonParse,需要怎樣的資料格式才可以使用"."來連接



(3)
Debug.Print DecodeJson.queryTime.sysTime
物件內有key, 使用如上式可讀出值

Debug.Print DecodeJson.msgArray["1"].ch
請問如果是物件陣列,上式要如何修改才能讀出值



(4)
UNIXTime = Round(((Date - #1/1/1970#) * 86400 + Timer) * 1000, 0)

請問一下怎會知道這個值是這樣算出來的?
過去一直都覺得是流水號,所以遇到類似的,都直接跳過不理,數據依然可以下載,所以不知道原來這是可以經由計算出來。
justinyutw wrote:
所以樓主也是從msdn一個一個試,才能知道哪個指令是可以使用囉?
...(恕刪)

如果您問的是 getrange.toarray,不是,這個方式我用很久了


如果是其它物件,但在msdn上沒有vba範例,也google不到
只要vba可以正確的createobject(),引用成功
我就會參考msdn上的java 、 c …等等的範例寫法
再改寫成vba
其它語言,我也看的懂,加上程式寫久了,通常是靠直覺,很少一個一個試

該怎說呢?
這就像努力學會開手排車後,突然改開自排車一樣
大同小異,靠直覺

不過msdn確實是我寫程式、學習新方法時,最常用的網站
雖然不一定有範例,但對有一些程式基礎的人來說
參數說明才是最重要的





justinyutw wrote:
請問是否在其他的網頁,只要網址幾乎一樣時,就可以使用"|"一次抓取各個單一網址的資料。
...(恕刪)

不行的,要看網頁設計
只是剛好這是網站拿資料的方式,所以可以這樣玩


justinyutw wrote:
Jsondata.write ""
請問這行要如何修改,才能使這行能與樓主寫得功能一樣。
...(恕刪)


改寫??看不懂
您是說po文變空白嗎?那是因為有些符號被論譠當作指令造成錯誤
所以我才會改成全形字po文
(附檔內的是正常的)

justinyutw wrote:
這行使用匿名函式運算式,並將"值"指派給JsonParse,JsonParse 變數? 還是是函式名稱?
...(恕刪)


justinyutw wrote:
要document.JsonParse,需要怎樣的資料格式才可以使用"."來連接
...(恕刪)


JsonParse ?? "."來連接 ?? 還是看不懂
圖片中的java程式碼,是網頁按鈕的function
可參考452樓,ie object如何點擊java按鈕
或是269樓456樓 xmlhttp寫法
那串java 就像vba 的按鈕,只是語言不同而己
Private Sub CommandButton1_Click()
a=b
c=d
End Sub


或是您寫個可正常執行的範例,我再看看您在問什麼



justinyutw wrote:
UNIXTime = Round(((Date - #1/1/1970#) * 86400 + Timer) * 1000, 0)
請問一下怎會知道這個值是這樣算出來的?
...(恕刪)


justinyutw wrote:
過去一直都覺得是流水號,所以遇到類似的,都直接跳過不理,數據依然可以下載,所以不知道原來這是可以經由計算出來。
...(恕刪)


unix 時間,印像中是在學組合語言時候就會了
所以一看到這個流水號,就知道是unix時間

說穿了沒什麼特別,就是1970年1月1日0時0分0秒起到現在的總秒數
知道規則後,要計算就很簡單了
(這棟樓有2種unixtime計算方式)

至於為什麼跳過,還是可以下載,那是因為網站沒檢查,網址上的參數,不一定全部都會用到

個人習慣是,瀏覽器查詢時出現什麼網址、參數,就用vba做出一模一樣的查詢
可減少日後除錯的麻煩,所以才會寫出2個計算unix 時間的function

詳細請google "unix 時間"







snare wrote:
改寫??看不懂
您是說po文變空白嗎?那是因為有些符號被論譠當作指令造成錯誤
所以我才會改成全形字po文
(附檔內的是正常的)...(恕刪)



雖然說是PO文章,經樓主這一說,好像是文章的 <script> ... </script> 被當成是 javascript 使用了
我記得預覽時,字應該都沒有跑掉,實際竟然變空白了

重新再PO一次

(2)
Jsondata.write ”<script>document.JsonParse=function (s) {return eval(’(’ + s + ’)’);}</script>”

1.
Jsondata.write ”<script>document.JsonParse=function (s) {return JSON.parse( s );}</script>”
Google eval 的使用方法,同時有介紹 JSON.parse 的使用,但實力太弱了,照著打還是沒辦法執行。
請問這行要如何修改,才能使這行與樓主寫得功能一樣。


2.
這行使用匿名函式運算式,並將"值"指派給JsonParse,JsonParse 是變數? 還是是函式名稱?

除了匿名函式,一般平常看到的具名函式如下圖


雖然說看得懂樓主寫得,但這行也是看很久才看懂,就只是看得懂而以。
但比較想知道怎麼知道document.JsonParse,需要怎樣的資料格式才可以使用"."來連接,是 JsonParse 是變數?或是函式名稱才可以這樣使用



(3)
Debug.Print DecodeJson.queryTime.sysTime
物件內有key, 使用如上式可讀出值

Debug.Print DecodeJson.msgArray["1"].ch
請問如果是物件陣列,上式要如何修改才能讀出值
justinyutw wrote:
Google eval 的使用方法,同時有介紹 JSON.parse 的使用
...(恕刪)


JSON.parse() 這個是javascript

在vba中需要引用api、class、activex、lib...等等的第3方工具
或使用
CreateObject("scriptcontrol")
CreateObject("MSScriptControl.ScriptControl")
載入其它高手開發的,解json專用java程式碼,來執行解碼動作
(我在219樓就有說明scriptcontrol無法在excel 64位元中正確引用、呼叫,會出錯)

簡單搜尋幾個網址,請參考
https://github.com/VBA-tools/VBA-JSON
https://coderwall.com/p/pbxsyw/vba-web-requests
http://exceldevelopmentplatform.blogspot.com/2018/01/vba-parse-json-safer-with-jsonparse-and.html
https://raw.githubusercontent.com/douglascrockford/JSON-js/master/json2.js
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse


justinyutw wrote:
這行使用匿名函式運算式,並將"值"指派給JsonParse,JsonParse 是變數? 還是是函式名稱?
...(恕刪)



JsonParse,應該說是function 名稱,您喜歡怎麼改都可以
document.aaa or document.bbb
您就把它理解成 vba 的function,只是我用JsonParse來命名
Sub test()
Debug.Print JsonParse("test")
End Sub

Function JsonParse(t As String)
t = t & Now()
JsonParse = t
End Function

另外,關於將"值"指派給JsonParse,這個問題

(假設網頁是使用json)
1的程式碼是按鈕,在網頁上按下去之後,依據所選的選項,產生資料
如果是用ie object,網頁原始碼中的程式,會把json字串解碼,並排列成所要的表格、資料

如果是用xmlhttp,因為傳回值是 responsetext 文字(網頁原始碼)
程式碼不會啟動,所以無法解碼、拆解,所以要另外寫vba處理

嗯~我猜,您大概是以為
1=>裡面的程式碼,會把結果輸出到=>2 吧
2的JsonParse,沒辦法直接到網頁那邊拿資料,中間要經過vba
1、2 是2個分開的獨立事件

正確是
xmlhttp send =>網站上1的程式碼跟網站拿資料=> 傳回 responsetext 到vba
vba把 responsetext(jaon)的值,用一個變數(物件)
set => 指派到CreateObject("HtmlFile")物件中jsonparse function做解碼,拿到整理好的 json


justinyutw wrote:
document.JsonParse,需要怎樣的資料格式才可以使用"."來連接
...(恕刪)


document. 這個我猜您可能也誤會了
那是java程式碼的語法

那個"."就像下面vba的用法
sheets(1).cells(1,1)
sheets(1).cells(1,1).row
application.worksheetfunction.match()

可以是函數、可以是資料…跟格式無關
是規定好的語法,不能隨便亂改的


justinyutw wrote:
Debug.Print DecodeJson.queryTime.sysTime
物件內有key, 使用如上式可讀出值
...(恕刪)

這個只是拿時間啊
我還是不知道您要問什麼?


justinyutw wrote:
Debug.Print DecodeJson.msgArray["1"].ch
請問如果是物件陣列,上式要如何修改才能讀出值

...(恕刪)


219樓的 Sub TAIEX() 副程式中
這3個就是json的物件陣列
Set 加權指數 = CallByName(CallByName(DecodeJson, "msgArray", VbGet), "0", VbGet)
Set 櫃買指數 = CallByName(CallByName(DecodeJson, "msgArray", VbGet), "1", VbGet)
Set 寶島指數 = CallByName(CallByName(DecodeJson, "msgArray", VbGet), "2", VbGet)
我是用callbyname,拆陣列,再取值
您是問這個嗎??


(2018-11-17 補充)


關於這2行取值的程式碼
我總算搞懂您在問什麼了

Debug.Print DecodeJson.queryTime.sysTime
Debug.Print DecodeJson.msgArray["1"].ch

您想問下圖中的1,可以用 DecodeJson.queryTime.sysTime 取值
但2要如何打指令才能取值
您大概google到很多都是用
DecodeJson.msgArray.0.c
DecodeJson("msgArray")(0).c
DecodeJson.msgArray(0)(c)
之類的方式吧……

那些都是用第三方工具,或是ScriptControl(僅32位元可用)




想了很久,不知道怎麼解釋比較容易懂
因為這牽扯到2個程式語言,vba + javascript

簡單的說明一下,希望您能看的懂

在物件集合(decodejson)中
為什麼 DecodeJson.queryTime.sysTime 可以取值
因為.systime的型態是variant/string
所以可以直接取值

但jscripttypeinfo是很特別的物件,因為vba雖然知道它是物件,但不認識它
沒辦法用標準的物件方式取值,就連for each 也不行,所以直接取值會出錯

剛好vba有callbyname這個特殊函數可用
能直接把jscripttypeinfo物件拆開獨立出來,裡面型態是variant/string的item
就可以用標準物件方式取值

所以,關於您第2行程式碼DecodeJson.msgArray["1"].ch,是否可取值
答案是不行,需配合callbyname,先把msgarray中的1獨立出來之後,才能取得ch的值
(callbyname 詳細功能,請google)

至於為什麼我用這個方式,因為在我所知道的方法中
(不好意思,能力有限,知道的不多)
這個方式程式碼易懂,最適合寫範例,而且 excel(32位元、64位元),通用
純vba寫法,不需外掛lib,相容性高
只要一行eval() + callbyname ,就可解決jscripttypeinfo的問題



如果您還是想用vba 物件方式取值,就是您google到的那些方式
使用key ,直接取得好幾層jscripttypeinfo物件陣列內的值
那請用ScriptControl 方式,解析出來的就是標準物件
詳細請google "ScriptControl JScript json"
有超多的範例可參考,您也會發現,在不用第3方工具(api、lib …)時,程式碼會變得很複雜
不過要注意ScriptControl 只能在excel 32位元使用
樓主我的程式要抓wantgoo的資料,如下圖



但我的程式只能抓到標題第一列資料如下:
代碼 股票 股價 漲跌% 周漲% 開盤 最高 最低 昨收 成交量 周轉% 當日/近月/一季/半年/一年

其它資料皆抓不到,可否看看我的程式是哪有問題,謝謝。

'=============================================================================
Sub test()

Cells.Clear

Dim myXML As Object
Set myXML = CreateObject("WinHttp.WinHttpRequest.5.1")

Dim myHTML As Object
Set myHTML = CreateObject("HTMLFile")

With myXML
.Open "GET", "https://www.wantgoo.com/hottip/search/resultlist?DateInterval=MM9ykkXEg54wgeqwg&StartDate=OuO0igb78hPbvTr7O5Q1Kwwgeqwgwgeqwg&EndDate=kqbG9LRTq15Owgdividewg2xLyuOzbgwgeqwgwgeqwg&Condition=oTgYqwgdividewgVhqQlmm6WHeTtqcFHWiKloPh5wgdividewg&HeadID=uGN2BL3uST4wgeqwg&MyCollectionNo=tlSTaaIIlwgpluswgkwgeqwg&pHeadIDs=105;&pSelectItems=sHeadSN_105,10;&orgDateInterval=range&orgStartDate=20181008&orgEndDate=20181107" '先抓取日期"
.send
myText = .responseText

i = 1

myHTML.body[removed] = .responseText
Set myTable = myHTML.getElementsByTagName("table")(0)

For Each myrow In myTable.Rows

j = 1

For Each mycell In myrow.Cells

Cells(i, j) = mycell.innerText
j = j + 1

Next

i = i + 1

Next

End With

Set myXML = Nothing
Set myHTML = Nothing

End Sub

'==============================================================================
kadyysc5044 wrote:
樓主我的程式要抓wantgoo的資料,如下圖

但我的程式只能抓到標題第一列資料如下:
代碼 股票 股價 漲跌% 周漲% 開盤 最高 最低 昨收 成交量 周轉% 當日/近月/一季/半年/一年

其它資料皆抓不到,可否看看我的程式是哪有問題,謝謝。

...(恕刪)




wantgoo 這一頁的資料,需登入會員
要搜尋需經過手機認證,免費的只有七天試用期,之後繼續用需付費才行

建議您找資料源頭下載後再處理,或是其它不需付費、登入的網站
(資訊來源:臺灣證券交易所TWSE、財團法人中華民國證券櫃檯買賣中心GTSM、台灣期貨交易所及本資訊內容係經玩股網有限公司處理提供)


不好意思,幫不上忙
我不希望這棟樓出現,一篇只能用七天的範例
而且跟“”沾上邊,都不會有好事
付費資料變免費,我可不想被“
關閉廣告
文章分享
評分
評分
複製連結
請輸入您要前往的頁數(1 ~ 144)

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