從一個(gè)實(shí)例開(kāi)始 Sub v4() '運(yùn)行時(shí)間0.01秒 Dim t t = Timer For x = 1 To 100000 m = m + 1000 '真接調(diào)用內(nèi)存中的值 Next x MsgBox Timer - t End Sub Sub v5() '運(yùn)行時(shí)間0.5秒 Dim t t = Timer For x = 1 To 100000 m = m + Cells(1, 1) '調(diào)用單元格中的值 Next x MsgBox Timer - t End Sub 運(yùn)行的結(jié)果是直接調(diào)用內(nèi)存中的值比調(diào)用單元格的值快了50倍,,為什么會(huì)這樣呢,?我們需要了解一下 VBA的運(yùn)算原理 ********** VBA的運(yùn)算原理 ********* VBA中的運(yùn)算最終是在內(nèi)存中進(jìn)行的,,如果數(shù)據(jù)已經(jīng)在內(nèi)存中,則直接進(jìn)行運(yùn)算,,但如果數(shù)據(jù)是 儲(chǔ)存在第三方對(duì)象(如單元格里,控件里)里,,則還需要先把數(shù)據(jù)從第三方對(duì)象里調(diào)入到內(nèi)存中,然后再 在內(nèi)存中對(duì)數(shù)據(jù)進(jìn)行運(yùn)算,。 如果把v5的程序進(jìn)行稍微改動(dòng),,運(yùn)行時(shí)間會(huì)大大縮短。 Sub v5_2() '運(yùn)行時(shí)間0.5秒 Dim x, t t = Timer x = Cells(1, 1) '把單元格的值先交給變量 For x = 1 To 100000 m = m + x Next x MsgBox Timer - t End Sub 如果VBA多次調(diào)用同一樣單元格,我們可以先把這個(gè)單元格放在一個(gè)變量中,如果是多行多列的單元 格區(qū)域呢?我們同樣可以把把這個(gè)區(qū)域的值裝入一個(gè)VBA變量,。 Sub v6() x = Range("a1:10000") End Sub 這個(gè)VBA變量裝入大于1個(gè)的數(shù)據(jù)時(shí),就構(gòu)成了VBA內(nèi)存數(shù)組,。 那什么是VBA數(shù)組呢? 1,、什么是VBA數(shù)組呢,? VBA數(shù)組就是儲(chǔ)存一組數(shù)據(jù)的數(shù)據(jù)空間,。數(shù)據(jù)類型可以數(shù)字,,可以是文本,,可以是對(duì)象,也可以是 VBA數(shù)組,。 2 VBA數(shù)組的分類 A.按維數(shù)劃分 1維數(shù)組 Sub t1() Dim arr(1 To 10) For x = 1 To 10 arr(x) = x Next x Stop End Sub 2維數(shù)組 Sub t2() Dim arr(1 To 10, 1 To 2) For x = 1 To 10 For y = 1 To 2 arr(x, y) = x * y Next y Next x Stop End Sub 3維數(shù)組 Sub t3() Dim arr(1 To 10, 1 To 2, 1 To 3) For x = 1 To 10 For y = 1 To 2 For z = 1 To 3 arr(x, y, z) = x * y + z Next z Next y Next x Stop End Sub B 按儲(chǔ)存類型劃分 常量數(shù)組 Sub t4() arr = Array(1, 2, 3, 4, 5) arr1 = Array(Array(1, 2), Array(10, 20), Array(100, 200)) '數(shù)組的中儲(chǔ)存數(shù)組 arr2 = [{"a",1;"b",2;"c",3}] '調(diào)用工作表內(nèi)存數(shù)組構(gòu)成VBA二維數(shù)組 Stop End Sub 靜態(tài)數(shù)組:固定大小的數(shù)組 靜態(tài)數(shù)組聲明方法 dim/public/private 數(shù)組名稱( 第一維數(shù)組上標(biāo) to 第一維數(shù)組下標(biāo),第二維上標(biāo) to 第二維下標(biāo)......) Sub t5() Dim arr1(10) '聲明一個(gè)上標(biāo)是0,下標(biāo)是10的數(shù)組 Dim arr2(1 To 10) '聲明一個(gè)上標(biāo)是1,下標(biāo)是10的數(shù)組 Dim arr3(1 To 10, 1 To 2) '聲明一個(gè)10行2列的二維數(shù)組 End Sub 動(dòng)態(tài)數(shù)組:大小不固定的數(shù)組 動(dòng)態(tài)數(shù)組的聲明方法:和靜態(tài)數(shù)組不同的時(shí),,動(dòng)態(tài)數(shù)組需要先用Dim聲明,數(shù)組大小得出 結(jié)果后還需要再用Redim進(jìn)行二次聲明,。 Dim 數(shù)組名稱() Redim 數(shù)組名稱( 第一維數(shù)組上標(biāo) to 第一維數(shù)組下標(biāo),第二維上標(biāo) to 第二維下標(biāo)...) 例1: Sub darr() Dim arr() '聲明一個(gè)動(dòng)態(tài)的arr數(shù)組(不知道它能盛多少數(shù)據(jù)) Dim k k = Application.WorksheetFunction.CountIf(Range("a2:a60"), ">10") '計(jì)算大于10的個(gè)數(shù) ReDim arr(1 To k) '再次聲明arr的大小,正好盛下k數(shù)量的值 For x = 2 To 6 If Cells(x, 1) > 10 Then m = m + 1 arr(m) = Cells(x, 1) '通過(guò)循環(huán)把大于10的數(shù)字裝入數(shù)組 End If Next x MsgBox arr(2) End Sub 如果數(shù)組需要隨一個(gè)變量不斷的擴(kuò)充,,數(shù)組就需要多次聲明,每擴(kuò)充一次就聲明一次: Redim Preserve (1 to k) 如果數(shù)組是多維的,,只能動(dòng)態(tài)聲明第末維的,,如果需要把讓第一維不斷擴(kuò)充,還需要先轉(zhuǎn)置,, 有點(diǎn)麻煩,,這里就不再詳述,遇到這種情況,,我們可以聲明一個(gè)足夠大的靜態(tài)數(shù)組來(lái)取代動(dòng)態(tài)數(shù)組,, 運(yùn)行速度較前者快。 1 單元格區(qū)域存入VBA數(shù)組 Sub test() Dim arr '聲明一個(gè)變量用來(lái)盛放單元格數(shù)據(jù) Dim x As Integer arr = Range("a2:d5") '把單元格數(shù)據(jù)搬入到arr里,,它有4列4行 For x = 1 To 4 '通過(guò)循環(huán)在arr數(shù)組中循環(huán) arr(x, 4) = arr(x, 3) * arr(x, 2) '數(shù)組的第4列(金額)=第3列*第2例 Next x Range("a2:d5") = arr '把數(shù)組放回到單元格中 End Sub 2 一維VBA數(shù)組放入單元格區(qū)域中 Sub test1() Dim arr(1 To 5) '聲明一維數(shù)組 For x = 1 To 5 arr(x) = x * 2 '通過(guò)循環(huán)給每個(gè)位置賦值 Next x Range("A1:E1") = arr '把數(shù)組導(dǎo)入到excel中的a1:e1單元格中 Range("A1:A5") = Application.Transpose(arr) '如果是放在一列中,就需要對(duì)數(shù)組進(jìn)行轉(zhuǎn)置后 再存放 End Sub 1.計(jì)算VBA數(shù)組的大小 Sub b1() Dim arr(-3 To 4) MsgBox UBound(arr) '下標(biāo) MsgBox LBound(arr) '上標(biāo) For x = -3 To 4 arr(x) = x * 2 Next x MsgBox Application.Count(arr) '含有數(shù)據(jù)元素的個(gè)數(shù) End Sub Sub b2() Dim arr arr = Sheets(1).UsedRange 'Usedrange的行數(shù)和列數(shù)是未知的 MsgBox UBound(arr, 1) '可以計(jì)算這個(gè)區(qū)域有多少行 MsgBox UBound(arr, 2) '可以計(jì)算出這個(gè)區(qū)域有多少列 End Sub 2.VBA數(shù)組的篩選 Sub b3() arr = Array("ABC", "A", "D", "CA", "ER") arr1 = VBA.Filter(arr, "A", True) '篩選所有含A的數(shù)值組成一個(gè)新數(shù)組 arr2 = VBA.Filter(arr, "A", False) '篩選所有不含A的數(shù)值組成一個(gè)新數(shù)組 Stop End Sub 3 VBA數(shù)組的拆分與合并 Sub t2() arr2 = Range("A1:B4") '把單元格區(qū)域A1:B4的值裝入數(shù)組arr2 arr3 = Application.Index(arr2, , 2) '把數(shù)組第2列拆分出來(lái)裝入新數(shù)組arr3中,, Stop 新數(shù)組為二維數(shù)組 End Sub 如果想按行拆分,除了api函數(shù)外是沒(méi)有其他辦法的 另通過(guò)用index很容易解決 arr2 = Range("A1:B4") '把單元格區(qū)域A1:B4的值裝入數(shù)組arr3 arr4 = Application.Index(arr2, 1, 0) ' 提取第一行數(shù)據(jù)放入數(shù)組 arr5 Range("d1").Resize(1, UBound(arr4)) = arr4 ' 把數(shù)組 arr5 賦值單元格
如果想把兩個(gè)數(shù)組進(jìn)行組合成一個(gè)數(shù)組,只有一個(gè)辦法,就是通過(guò)循環(huán)
另通過(guò)用index很容易解決 arr2 = Range("A1:B4") '把單元格區(qū)域A1:B4的值裝入數(shù)組arr3 arr4 = Application.Index(arr2, 1, 0) ' 提取第一行數(shù)據(jù)放入數(shù)組 arr5 Range("d1").Resize(1, UBound(arr4)) = arr4 ' 把數(shù)組 arr5 賦值單元格 4,、VBA數(shù)組的最值 Sub t3() arr = Array(1, 35, 4, 13) MsgBox Application.Max(arr) '最大值 MsgBox Application.Min(arr) '最小值 End Sub Sub t4() arr = Array(1, 35, 4, 13) MsgBox Application.Large(arr, 2) '第2大值 MsgBox Application.Small(arr, 2) '第2小值 End Sub 5 數(shù)組的統(tǒng)計(jì)與求和 Sub t5() arr = Array(1, 35, 4, 13) MsgBox Application.Sum(arr) '對(duì)數(shù)組進(jìn)行求和 Dmsch 大師的觀點(diǎn) End Sub Sub t6() arr = Array(1, 35, "a", 4, 13, "b") MsgBox Application.Count(arr) '返回?cái)?shù)字的個(gè)數(shù)4 MsgBox Application.CountA(arr) '返回?cái)?shù)組文本和數(shù)字的總個(gè)數(shù) End Sub 6.數(shù)組的查詢 Sub t7() arr = Array(1, 35, 4, 13) MsgBox Application.Match(4, arr, 0) '查詢數(shù)值4在數(shù)組Arr中的位置 End Sub 7 數(shù)組的轉(zhuǎn)置 Sub t8() arr = Array(1, 35, "a", 4, 13, "b") arr1 = Application.Transpose(arr) Stop End Sub Sub t9() arr = Range("a1:a5") arr1 = Application.Transpose(arr) Stop End Sub 8.字符串與VBA數(shù)組 Sub t1() Dim arr, myst As String myst = "A-REW-E-RWC-2-RWC" arr = Split(myst, "-") '按-分隔成一組數(shù)裝入數(shù)組中 k = Join(arr, ",") '再用","把數(shù)組的每個(gè)值連接成一個(gè)字符串,結(jié)果為"A,REW, Stop E,RWC,2,RWC" End Sub 9.巧妙利用數(shù)組的標(biāo) 因?yàn)閿?shù)組的標(biāo)是唯一的,所以我們就利用這個(gè)特點(diǎn)去除重復(fù)的數(shù)值 Sub r1() Dim arr, arr2(1 To 13, 1 To 1) arr = Range("a1:a13") For x = 1 To UBound(arr) arr2(arr(x, 1), 1) = arr(x, 1) Next x Range("b1").Resize(13) = arr2 End Sub 10.重新初始化數(shù)組 Sub r2() Dim arr(1 To 10) For x = 1 To 10 arr(x) = x Next x Stop Erase arr '如果arr是動(dòng)態(tài)數(shù)組,,下次使用前還需要用redim設(shè)置數(shù)組的大小 Stop For x = 1 To 10 arr(x) = x Next x Stop End Sub
|