VBA進階|利用VBA數組管理數據清單和表格

LBound(ArrayName[,dimension])

ArrayName - 必需的參數。該參數對應於數組的名稱。

Dimension - 一個可選參數。 這需要一個與數組的維度相對應的整數值。如果是“1”,則返回第一維的下界; 如果是“2”,則返回第二維的下界,依此類推。

二維數組的行數:UBound(arr,1) -LBound(arr,1) + 1

(可以寫為:UBound(arr) -LBound(arr) + 1)

二維數組的列數:UBound(arr,2) -LBound(arr,2) + 1

3 單元格區域映射到數組

如將Range("A1:E4")映射到數組arr:

Sub 單元格區域映射到數組()

dim arr()

arr = Range("A1").Resize(4, 5)

Range("A6").Resize(UBound(arr), UBound(arr, 2)) = arr

End Sub

將單元格區域的數據保存到數組以後,數據在內存中處理,速度更快。

4 利用索引號(下標)獲取數組中的元素

數組元素的值可以通過下標獲取。

Sub 二維數組()

arr = [{11,12,13;21,22,23;31,32,33}]

Range("B5").Resize(UBound(arr, 2), UBound(arr)) = arr

cells(1,1) = arr(2,2) 'arr(2, 2)對應22

End Sub

有時需要重新定義數組大小,才能使用索引。

5 數組轉置

正如單元格區域可以轉置一樣,數組也可以同樣操作。

Sub 數組轉置()

Dim arr

arr = [{1,2,3,4}]

arr2 = Application.WorksheetFunction.Transpose(arr)

Range("A5").Resize(UBound(arr), 1) = arr2

End Sub

以上操作相當於一維轉二維,一維(一行n列)轉為一個n行1列的二維數組。

同樣的,二維數組也可以進行相同的操作。

dim arr(i to j) as variant

dim arr(i to j, n to m) as variant

上面的i,n必須是正整數,表示索引號(下標)開始值(最小值)。i可以通過Lbound(arr)獲得,n可以通過Lbound(arr,2)獲得;

如果i,n是零,可以略寫為:dim arr(j) as variant,dim arr( j, m) as variant

j,m必須是正整數,表示索引號(下標)的結束值(最小值)。j可以通過Ubound(arr)區得,m可以通過Ubound(arr,2)獲得;

當然,聲明時也可以不考慮維數,如dim arr() as variant。

Dim arr(1 To 3, 1 To 4) '表示行、列的索引號都是從1開始,聲明一個3行4列的數組

For i = 1 To 3

For j = 1 To 4

arr(i, j) = i * 10 + j

Next j

Next i

Range("A1").Resize(UBound(arr), UBound(arr, 2)) = arr

End Sub

Dim arr(3) '表示索引號從0-3的4個元素,等同於arr(0 to 3)

For i = 0 To 3

arr(i) = i + 10

Next i

Range("A1").Resize(1, UBound(arr) + 1) = arr

End Sub

關於列索引號的開始上標的默認值,如果採用缺少上標的聲明,則開始上標的默認值是0.。如果沒有聲明直接使用數組變量,則上標的默認值是1。(可以使用Option Base 1語句來強制指定該數組的下界。該指令必須置於VBA模塊任何Sub語句上面的聲明部分。如果你不明確Option Base 1,那麼VBA在使用數組是就會假定使用Option Base 0來從0開始編號你的數組成員。)

另外,如果在聲明時沒有聲明數據類型,或聲明的是variant數據類型,在對數組元素分別賦值時,可以是不同的數據類型。

Sub 不同類型的數組元素()

Dim arr(5)

arr(0) = "1" 'Number as String

arr(1) = "VBScript 'String"

arr(2) = 100 'Number

arr(3) = 2.45 'Decimal Number

arr(4) = #10/7/2013# 'Date

arr(5) = #12:45:00 PM# 'Time

Range("A1").Resize(1, UBound(arr) + 1) = arr

End Sub

也可以利用VBA的內置函數Array()聲明常量數組:

arr = Array(Array("a", 10), Array("b", 20), Array("c", 30))

[a1] = arr(1)(1)

Array()函數允許你在代碼執行中間創建一個數組,而不必事先確定其大小。該函數總是返回一個Varant數組。

6 動態數組

上面使用的都是靜態數組,靜態數組在執行期間不可以改變其最大的結束下標(最後一個元素的索引號),而動態數組可以隨時修改其結束下標。

有dim語句定義了一個靜態數組後,可以用Redim 語句或者Redim Preserve 對定義的靜態數組多次重新定義大小。

Redim 語句或者Redim Preserve語句的作用是為了動態數組變量重新分配內存空間,包括指定的維數及聲明其結束下標。但Redim語句重置數組變小,會使數組中的值丟失;而Redim Preserve語句重置數組變小時可以保留原數組中的值。可以使用Redim語句反覆地改變數組的元素及維數的數目,但是不能將一個數組定義為某種數據類型後,再使用Redim將該數組改成為其他數據類型,除非是variant所包含的數組。具體看以下數組:

Sub 重置數組()

Dim arr1(), arr2()

arr1 = [A1:D11].Value

arr2 = [A1:D11].Value

ReDim arr1(1 To 2, 1 To 3) '重置數組大小為2行3列的二維數組,數組的中的值丟失

ReDim Preserve arr2(1 To 11, 1 To 3) '重置數組大小為11行3列的二維數組

MsgBox arr1(2, 3) '結果顯示為空

MsgBox arr2(2, 3) 'C2單元格的數值

End Sub

7 數組與字符串

數組與字符串可以使用split()函數和join()函數相互轉換。

7.1 利用Split()函數將字符串分割為一個數組

Split函數可以將字符串按指定的分隔符轉換成下標為0的一維數組(下標為0,並且不受Option Base語句的影響)。它的語法如下:

Split(expression[,delimiter[,count[,compare]]])

expression 必選參數 包含字符串和分隔符的字符串表達式。

delimiter 可選參數 用於標識字符串邊界的字符串字符。如果忽略,則使用空格字符("")作為分隔符

count 一個可選參數。要返回的子字符串的數量,如果指定為-1,則返回所有子字符串。

如:

Sub splitstr()

Sheets("數組與字符串").Select

s = "紅,red,橙,orange,黃,yellow,綠,green,青,cyan,藍,blue,紫,purple"

arr = VBA.Split(s, ",")

Range("A11").Resize(1, UBound(arr)) = arr

For Each color in arr

MsgBox color

Next

End Sub

7.2 利用Join()函數將數組元素合併為一個字符串

Join函數可用於連接數組中的所有字串符,從而創建一個新的字串符,可隨意指定分隔符,其語法如下:

Join(sourcearray [,delimiter])

sourcearray 代表數組,參數delimiter代表分隔符

如:

Sub joinstr()

a = Array("Red", "Blue", "Yellow")

b = Join(a)

b = Join(a, "$")

arr = Range("A1:B7")

For i = 1 To UBound(arr)

Range("d" & i) = Join(Array(arr(i, 1), arr(i, 2)), "-")

Next i

End Sub

7.3 利用Filter()函數篩選數組元素

Sub itemFilter()

arr = Array("A056", "A079", "B003", "A007", "B017")

arrf = Filter(arr, "A0")

'MsgBox ("The Filter array: " & Join(arrf))

[A1] = arrf

End Sub

單元格A1的值即顯示為:A056 A079 A007

8 數組的最值、求和、個數統計

Application.Max(arr) 最大值

Application.Min(arr) 最小值

Application.Large(arr, 2) 求出第二大值

Application.Small(arr, 2) 求出第二小值

(可以利用上面這些內置函數對數組實現輕鬆排序。)

Application.Sum(arr) 求和

Application.Count(arr) 統計數組元素(數字)的個數

Application.Counta(arr) 統計數組元素(數字+文本)的個數

COUNT函數和COUNTA函數都是計算非空單元格個數。區別在於:

COUNT函數在計算非空單元格的個數時,將把數字型的數字計算進去,錯誤值、文字、邏輯值、空值將被忽略;

如果要統計含有錯誤值、文字、邏輯值,則使用COUNTA函數。

9 數組的查詢和拆分

9.1 Mach()查詢數組

Match()函數可以查詢一個指定值在一組數中的位置,它也可以用於VBA數組的查詢。如:

Sub query()

arr = Array(1, 35, 4, 13)

MsgBox Application.Match(4, arr, 0) '查詢數值4在數組Arr中的位置

End Sub

9.2 Index拆分數組

數組的拆分在VBA中是一個難題,如果是按行拆分數組,除了用循環外也只能借用API函數完成了。幸好我們可以借用工作表函數index達到按列拆分數組,即多列構成的數組,你可以任意拆分出一列構成新的數組。方法是:Application.Index(數組, 列數) ,例:

Sub Index拆分數組()

arr2 = Range("A1:B4") ‘把單元格區域A1:B4的值裝入數組arr2

arr3 = Application.Index(arr2, , 2) '把數組第2列拆分出來裝入新數組arr3中,新數組為二維數組

MsgBox arr3(2, 1) '取出新數組第2行的值

End Sub

10 與數組相關的其它函數

IsArray()函數返回一個布爾值,指示指定的輸入變量是否是數組變量。

Erase()函數用於重置固定大小數組的值並釋放動態數組的內存。

Erase ArrayName

固定數值數組,數組中的每個元素重置為零。

固定字符串數組,數組中的每個元素被重置為零長度""。

對象數組,數組中的每個元素被重置為特殊值Nothing。

11 數組作為函數參數

數據可以在子過程或者函數過程之間作為必須或者可選參數傳遞。如果傳遞的參數不是過程執行一定要的話,那麼這個參數名稱就應該在前面加關鍵字Optional。然而,有些時候,你事先並不知道你要傳遞多少個參數。一個典型的例子就是加法。你可能想要將兩個數字加和,或者,你也許要加和3個,10個,或者15個數字。使用關鍵字ParamArray,你就可以將一個包含任意個成員的數組傳遞給你的子過程和函數過程。下面的函數過程AddMultipleArgs將加和你所需要的任何多個數字。該函數以數組myNumbers的聲明開始,注意關鍵字ParamArray的使用。該數組必須聲明為Variant類型,並且它必須是函數過程的最後一個參數。

Function Addm(ParamArray myNumbers() As Variant)

Dim mySum As Single

Dim myValue As Variant

For Each myValue In myNumbers

mySum = mySum + myValue

Next

Addm = mySum

End Function

[a1] = =addm(1,212,33,424,55)

[a1] 就會返回上面參數的總和:725。你可以提供無限制的參數數目。注意,每個函數的參數之間要用逗號分開。

-End-


分享到:


相關文章: