• 156

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

snare wrote:
沒排版
擋住畫面的按鈕
您把我故意留的全改掉了
我本來想讓抄的人,稍微辛苦一下的說sorry

不過,這種美觀、輸入的修改也沒關係啦
不要改到“100%完全自動化”就好,留一點變數給他們思考
71樓、75樓的範例,內文就有寫,本來就是寫出來給大家抄的XD
您願意幫他們改,我很欣賞100分,那些都是我不願意做的事...(恕刪)


謝謝 snare大大 的鼓勵^^
在下原先不了解 snare大大 您原本是有這樣的初衷^^"
經您的說明後,在下也已能明白您的原本好的用意,
如此,在下決定還是把動手的機會留給有興趣的人好了...呵呵^^"


snare wrote:
....
.length 是 CreateObject("htmlfile") 的功能
Table.Length,該資料表格的最大長度(列數)
Table(2).Cells.Length,該資料表格的最大寬度(欄數),為什麼用2前面解釋過了

會這樣做,是因為資料量太多
有時是上萬格的資料,如果用迴圈一次一格填入,會浪費excel 的處理時間
所以先把資料丟到陣列裡

range.cells(第一格,最後一格)=陣列(需和cells同大小)
一次填入全部資料


很謝謝 snare大大 的指點^^
那麼在下還想先再請教一下,那就是這個例子中的 Table 其本質是否比較等同於 VBA 中的"陣列"一樣? 包括用法等等?
因為若是以 VBA 中的陣列來說,看起來好像比較相近於這個 Table 的用法,
但是似乎又不完全相同,因為陣列的用法沒有 Length 這一個屬性,
而且,語法中又和 Cells 混在一起用,那在下就更加迷惑了..
這倒底是 Range 還是 Array 的歸屬?
雖然在下是知道 Range 和 Array 是有一些共通性質,可卻又不完全是相同的東西,
因為在下也試過把 Array 指定給 Range (Range = Array )這是可以的,
但若反過來把 Range 指定給 Array (Array = Range) 卻是有問題的....
或者應該這麼說,在下對於這個 Table 物件的相關屬性用法認知的太少了...
所以還無法掌握來自由運用,目前還尚在摸索中...^^"




yuehmao wrote:
在下決定還是把動手的機會留給有興趣的人好了...呵呵^^"
...(恕刪)


因為這種用途的程式,非常多人要,是可以賣錢的…
如果自己有辦法改到很完美的話,我是不介意的
完成度太高的範例,也許有心人士,會沒有付出任何努力,就直接拿去……
1個人收100就好,100個人就有10000收入,如果改成月費制

我不差這點小錢,只是看了一些專業網站上的範例
還有一些“假”分析師在賣的程式,都是那幾種不穩又慢的方法,天下一大抄
(“真”分析師的程式,就超強了,人家在頂樓,而我只到門口而己,那種的才有收費的資格)

這篇範例中,我唯一用到的,只有抓每日收盤價格,來計算我的股票損益而己
其它的只是打發時間,太無聊才po文的

yuehmao wrote:
因為陣列的用法沒有 Length 這一個屬性
...(恕刪)


替代用法

Sub test()
Dim ttt(1 To 4, 1 To 3)
Debug.Print UBound(ttt, 1)
Debug.Print UBound(ttt, 2)

End Sub


yuehmao wrote:
反過來把 Range 指定給 Array (Array = Range) 卻是有問題的....
...(恕刪)


沒問題的

Sub test()
Dim ttt As Variant
ttt = Range("a1:c3")
For Each tt In ttt => 訂正打錯字,原 test 是錯的,修正為ttt
Debug.Print tt
Next
End Sub
snare wrote:
...
替代用法

Sub test()
Dim ttt(1 To 4, 1 To 3)
Debug.Print UBound(ttt, 1)
Debug.Print UBound(ttt, 2)

End Sub
上...(恕刪)


謝謝 snare大大 提供的另一種用法^^
在下會再以此來測試比較二個用法之間的關聯性,
看能能不再進一步了解 Table 這個 CreateObject("htmlfile") 物件的本質,
其實在下是比較想從根本的本質上去了解,而不僅限於用法,
希望能再由您所提供的資訊進一步去更深入的了解。



snare wrote:
...
沒問題的

Sub test()
Dim ttt As Variant
ttt = Range("a1:c3")
For Each tt In test
Debug.Print tt
Next
End Sub
...(恕刪)


在下能明白您這個測試的用意,
但是這個的測試中有個盲點,那就因為是 ttt 是一個變形型態,
所以,當做執行下面這樣的指令後,只是讓 ttt 變形為 Range 型態而已,
ttt = Range("a1:c3")
感覺這並不是真正的把 Range 指定給 Array,
在下是像下面這樣測試的

Dim ttt as variant()
redim ttt(0 to 9)
ttt = Range("A1:A10")

ttt = Range("A1:J1")

記得之前這樣的測試是可以指定給 ttt 一個 range 資料
但是,當用 LBound 或 Ubound 來取得 ttt 邊界資訊時,卻會出現執行階段的Error..
反覆測試下,還是沒有辦法解決 Error 的問題....

snare wrote:
因為這種用途的程式,非常多人要,是可以賣錢的…
如果自己有辦法改到很完美的話,我是不介意的
完成度太高的範例,也許有心人士,會沒有付出任何努力,就直接拿去……
1個人收100就好,100個人就有10000收入,如果改成月費制口哨

我不差這點小錢,只是看了一些專業網站上的範例
還有一些“假”分析師在賣的程式,都是那幾種不穩又慢的方法,天下一大抄
(“真”分析師的程式,就超強了,人家在頂樓,而我只到門口而己,那種的才有收費的資格)

這篇範例中,我唯一用到的,只有抓每日收盤價格,來計算我的股票損益而己
其它的只是打發時間,太無聊才po文的...(恕刪)


的確如此,
其實您這樣說明之後,在下也比較能明白您的想法了^^
但是,其實在您的PO文中,相信確實也帶給了不少了學習的機會,
感覺這其實也是很有意義的事情,用意十分良善,
不管是有心,還是無意,總之在下是覺得是好的事物那就是好的^^
yuehmao wrote:
但是這個的測試中有個盲點,那就因為是 ttt 是一個變形型態,
所以,當做執行下面這樣的指令後,只是讓 ttt 變形為 Range 型態而已,
ttt = Range("a1:c3")
感覺這並不是真正的把 Range 指定給 Array
...(恕刪)


嚴格來說,應該是指定到記憶體中
這樣資料就可以很容易的在"記憶體中計算"
不用再寫一大堆迴圈,從儲存格,一格一格拿,這很浪費時間的

迴圈中計算所需要的資料,最好全部在記憶體中,對效能有很大的幫助

Sub test() '60萬筆資料測試

Dim ttt As Variant
ttt = Range("a1:j60000")

aaa = Timer
For i = 1 To 10
For j = 1 To 60000
bbb = bbb + Cells(j, i) '從格子拿資料
Next
Next
Debug.Print "timer1=" & Timer - aaa, bbb

aaa = Timer
For Each bbb In ttt
ccc = ccc + bbb '從記憶體中拿資料
Next
Debug.Print "timer2=" & Timer - aaa, ccc

End Sub
時間比較
格子timer1=2.375
記憶體timer2=0.0234375

計算結果是一樣的,不過時間快了100倍
程式也可以簡化一點。



yuehmao wrote:
記得之前這樣的測試是可以指定給 ttt 一個 range 資料
但是,當用 LBound 或 Ubound 來取得 ttt 邊界資訊時,卻會出現執行階段的Error..
反覆測試下,還是沒有辦法解決 Error 的問題....
...(恕刪)


可以呀??

Sub test()

Dim ttt As Variant
ttt = Range("a1:c5")
Debug.Print UBound(ttt, 1)
Debug.Print UBound(ttt, 2)
Range("e1:g5") = ttt

End Sub

不過取邊界好像沒什麼意義耶…
會把range指定到array中,不知道邊界也沒辦法指定的
邊界早就知道了
snare wrote:
可以呀??

Sub test()

Dim ttt As Variant
ttt = Range("a1:c5")
Debug.Print UBound(ttt, 1)
Debug.Print UBound(ttt, 2)
Range("e1:g5") = ttt

End Sub

不過取邊界好像沒什麼意義耶…
會把range指定到array中,不知道邊界也沒辦法指定的
邊界早就知道了...(恕刪)


謝謝 snare大大 的說明^^
您上面的測試做法,在下是知道這樣是OK的,
但這並不是在下本來問題的原意....
在下本是知道 Range 用 LBound 和 Ubound 來求取邊界資訊是沒有意義的,
而且好像也沒有這種用法....^^"
在下是指真的 Array 像是 ----> ttt(0) ttt(1) ttt(2)
這種真正原本的的陣列型態為對像來對應這個問題的,
意思就是把 Range 指定給 Array---> ttt = Range()
然後 ttt 的運用上不是像右邊這樣 ---> ttt.Cells(x,x) 
而是像這個右邊這樣 ---> ttt(0) ttt(1) ttt(2)
在下認為這才是真正的把 Range 指定給 Array.


但您下面這二句倒是出乎意料,待會再做測試看看,
看結果如何再來回報.
Debug.Print UBound(ttt, 1)
Debug.Print UBound(ttt, 2)

snare wrote:
嚴格來說,應該是指定到記憶體中
這樣資料就可以很容易的在"記憶體中計算"
不用再寫一大堆迴圈,從儲存格,一格一格拿,這很浪費時間的

迴圈中計算所需要的資料,最好全部在記憶體中,對效能有很大的幫助

Sub test() '60萬筆資料測試

Dim ttt As Variant
ttt = Range("a1:j60000")

aaa = Timer
For i = 1 To 10
For j = 1 To 60000
bbb = bbb + Cells(j, i) '從格子拿資料
Next
Next
Debug.Print "timer1=" & Timer - aaa, bbb

aaa = Timer
For Each bbb In ttt
ccc = ccc + bbb '從記憶體中拿資料
Next
Debug.Print "timer2=" & Timer - aaa, ccc

End Sub
時間比較
格子timer1=2.375
記憶體timer2=0.0234375

計算結果是一樣的,不過時間快了100倍
程式也可以簡化一點。
...(恕刪)


謝謝 snare大大 的說明^^
這段編碼,在下先收下來了,
後面會再來做測試。
yuehmao wrote:
意思就是把 Range 指定給 Array---> ttt = Range()
然後 ttt 的運用上不是像右邊這樣 ---> ttt.Cells(x,x) 
而是像這個右邊這樣 ---> ttt(0) ttt(1) ttt(2)
在下認為這才是真正的把 Range 指定給 Array....(恕刪)


我很久沒看書了
很多基本的,會用,但不知道怎麼說明

希望您看的懂
set table=.. ... 某物件集合(可以包含各種不同類型東西)
array() 陣列

雖然物件集合、陣列,類型不同,但都可以使用用陣列的原理來計算
我一向都把物件、陣列,都當陣列用,只能回答到這樣

再補上另一個,跟回答無關的

Sub test2()'60萬筆資料寫入測試
Dim ttt(1 To 60000, 1 To 10)

aaa = Timer
For i = 1 To 10
For j = 1 To 60000
Cells(j, i) = Rnd() * 100 '一格一格寫入
Next
Next
Debug.Print "timer1=" & Timer - aaa

Cells.Clear

aaa = Timer
For i = 1 To 10
For j = 1 To 60000
ttt(j, i) = Rnd() * 100 '丟到陣列中
Next
Next
Range("a1:j60000") = ttt '一次寫入
Debug.Print "timer2=" & Timer - aaa

End Sub
時間差,記憶體的快了50倍
timer1=52.04688
timer2=1.28125
snare wrote:
我很久沒看書了很多基...(恕刪)


這一年來都沒什麼人
最近忽然冒出一堆人
萬點效應....?

但,也算好事,學習VBA的人越來越多
師傅 辛苦啦!

我在網路上也有看到一些分析師,出書的,等等
弄了一些需要付費才能使用的功能
看到也是笑了...
(跟師父提供的程式碼有啥差別...)



snare wrote:
可以呀??

Sub test()

Dim ttt As Variant
ttt = Range("a1:c5")
Debug.Print UBound(ttt, 1)
Debug.Print UBound(ttt, 2)
Range("e1:g5") = ttt

End Sub

不過取邊界好像沒什麼意義耶…
會把range指定到array中,不知道邊界也沒辦法指定的
邊界早就知道了...(恕刪)


經過測試後,看來您是對的^^
Array 和 Range 是完全可以交互引用的,
是在下記憶錯誤..抱歉抱歉.呵呵^^"

Dim i As Long, j As Long
Dim ttt As Variant
ttt = Range("A1:C5")
Debug.Print TypeName(ttt)
Debug.Print "Ubound(1)=" & UBound(ttt, 1)
Debug.Print "Ubound(2)=" & UBound(ttt, 2)
Range("E1:G5") = ttt
Range("A10:E12") = Application.Transpose(ttt)
For i = LBound(ttt, 1) To UBound(ttt, 1)
For j = LBound(ttt, 2) To UBound(ttt, 2)
Debug.Print "ttt(" & i & "," & j & ")=" & ttt(i, j)
Next j
Next i

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