在進入本篇文章之前,先來了解一下什麼是陣列。
根據維基百科對陣列的敘述:
在電腦科學中,陣列資料結構(英語:array data structure),簡稱陣列(英語:Array),是由相同類型的元素(element)的集合所組成的資料結構,分配一塊連續的主記憶體來儲存。利用元素的索引(index)可以計算出該元素對應的儲存位址。
也就是,陣列變數是為了儲存複數多個同種類型的資料所存在的變數。
在程式中若宣告陣列變數,和變數一樣,在記憶體上會依照陣列的資料類型,產生相對應的儲存區域。陣列保存多個資料的區域,而每個區域,都會使用索引值(index)進行辨別。1個變數可以放入2個以上的資料稱為陣列變數。
目錄
{tocify} $title={目錄}
靜態陣列
靜態陣列的定義 :
如果想要宣告變數為陣列變數的時候,變數後面的括號內 ()需要指定索引的上限值。
變數宣告時指定上限值的陣列變數,稱為靜態陣列。
關於陣列的預設索引值 :
陣列的每個元素預設會從索引值0開始,直到上限值為止。一般如果不將索引預設的開始值設定為1開始時,也就是設定 Option Base 1時,預設索引值都會從0開始。
索引值上下限已指定 :
當然在實際使用陣列時,若已指定陣列的開始值及結束值,
例如 Dim 變數名 (3 to 9 ),
透過以上方式可以修改變數的開始和結束值,
然而在這個情況下就算已經設定Option Base 1,
陣列依然會依照 Dim 變數名 (3 to 9 )
所指定的方式開始及結束,
並不會因為 設定Option Base 1,使此已指定開始結束陣列的索引會從1開始。
在使用上必須要注意及了解。
基本格式
Point!
Dim 變數名(索引上限值) As 資料型態
變數名 (索引)= 值
範例
Sub ArrayTest()
' 基本格式
' Dim 變數名(索引上限值) As 資料型態
' 變數名 (索引)= 值
' 索引值預設從 0 開始~
' 宣告索引上限值的陣列為靜態陣列
' 宣告上限值為2的陣列,
' 因為陣列開始值為0, 所以可放入3個元素
Dim myArray(2) As String
myArray(0) = "My"
myArray(1) = "Array"
myArray(2) = "Test"
' 宣告要輸出結果的變數~
Dim result As String
Dim i As Integer
' 輸出結果~
For i = 0 To 2
result = result + " " + myArray(i)
Next
MsgBox result
End Sub
執行後的結果如下
關於靜態陣列可參考以下連結影片
不同資料型態的資料放到同一個陣列
在陣列中,通常會放入相同資料型態的資料,如果在陣列中,想要放入不同資料型態的資料要怎麼處理呢?
基本格式
Point!
Dim 變數名 As Variant
變數名 = Array(元素1 , 元素2 ,元素3 , ...)
範例
Sub arrayTest()
' 宣告陣列的變數為自由型態的變數
Dim arrayTest As Variant
'將元素放到Array函數中
arrayTest = Array("小王", #9/20/2023#, True, 14.123, 1)
'把資料放到儲存格看看
Range("A1").Value = arrayTest(0)
Range("A2").Value = arrayTest(1)
Range("A3").Value = arrayTest(2)
Range("A4").Value = arrayTest(3)
Range("A5").Value = arrayTest(4)
End Sub
執行的結果如下
透過這樣的方式,可以將不同資料型態的資料放到同一個變數內。
想要確認變數的值是否為陣列
如果想要判斷某一個變數是否為陣列,可以使用IsArray函數進行確認。
透過IsArray函數確認,會返回boolean值,如果該變數為陣列,會回傳True;反之該變數如果不是陣列,則傳回False。
基本格式
Point!
IsArray(變數名)
範例
Sub arrayTest()
' 宣告陣列的變數為自由型態的變數
Dim arrayTest As Variant
'此時arrayTest變數還不是陣列
MsgBox IsArray(arrayTest)
'將元素放到Array函數中
arrayTest = Array("小王", #9/20/2023#, True, 14.123, 1)
'此時arrayTest變數已經是陣列
MsgBox IsArray(arrayTest)
End Sub
執行的結果如下
動態陣列
動態陣列的定義 :
如果您想要宣告的陣列,元素個數並不確定的時候,這時只要在變數名()的括號內空白即可。
等到確定陣列的元素個數時,再使用ReDim敘述,進行元素個數的指定。
而這樣的陣列稱為動態陣列。
關於陣列的說明,也可以參考微軟的教學
宣告陣列的說明。
基本格式
Point!
Dim 變數名() As 資料型態
ReDim 變數名(上限值)
範例
Sub 動態陣列()
' 宣告陣列變數 myArray為字串型態,後面()括號空白,不輸入上限值
Dim myArray() As String
'宣告未知上限值變數名稱為 ulValue,為整數型態
Dim ulValue As Integer
'宣告變數名稱 i 為整數型態,供迴圈使用
Dim i As Integer
'宣告變數 result為字串型態,供輸出結果用,預設為空字串
Dim result As String: result = ""
'假設A欄有資料,但不知道會有多少,可能會陸續追加
'因此從A1往下找到最後一筆資料為最後的上限
'取得最後一列的數字並放入ulValue變數
ulValue = Range("A1").End(xlDown).Row
'使用ReDim 設定上限值
ReDim myArray(ulValue - 1)
'使用迴圈輸出資料
For i = 0 To ulValue - 1
myArray(i) = Range("A" & i + 1).Value
result = result + myArray(i) & Chr(10)
Next i
'輸出訊息
MsgBox result
End Sub
使用Preserve關鍵字保留陣列中的值
在使用動態陣列時,有一點要注意的是在第二次ReDim後,之前在陣列的數值會消失,如果不想要讓之前的數值消失,必須要使用Preserve關鍵字來保留之前的數值。
基本格式
Point!
ReDim Preserve 變數名(上限值)
未使用 Preserve 關鍵字時
範例 :
Sub 元素個數變更1()
' 未使用Preserve關鍵字時 ============================
' 宣告陣列變數 myArray為字串型態,後面()括號空白,不輸入上限值
Dim myArray() As String
'使用ReDim決定上限值為1
ReDim myArray(1)
'宣告變數名稱 i 為整數型態,供迴圈使用
Dim i As Integer
'設定myArray要放入的數值
myArray(0) = "甲"
myArray(1) = "乙"
'myArray想要追加資料,使用ReDim 重新設定上限值為2
ReDim myArray(2)
'追加設定myArray要放入的數值
myArray(2) = "丙"
'使用迴圈輸出資料
For i = 0 To 2
Range("A" & i + 1).Value = myArray(i)
Next i
End Sub
執行的結果如下
原本預計將甲乙丙三個字加入A1~A3的儲存格,但因為沒有加上Preserve關鍵字,在重新使用ReDim的時候,第一次ReDim的資料並沒有保存,只剩下第二次ReDim的資料。
使用 Preserve 關鍵字時
範例 :
Sub 元素個數變更2()
' 使用Preserve關鍵字時 ============================
' 宣告陣列變數 myArray為字串型態,後面()括號空白,不輸入上限值
Dim myArray() As String
'使用ReDim決定上限值為1
ReDim myArray(1)
'宣告變數名稱 i 為整數型態,供迴圈使用
Dim i As Integer
'設定myArray要放入的數值
myArray(0) = "甲"
myArray(1) = "乙"
'myArray想要追加資料,使用ReDim 重新設定上限值為2
' 追加Preserve關鍵字
ReDim Preserve myArray(2)
'追加設定myArray要放入的數值
myArray(2) = "丙"
'使用迴圈輸出資料
For i = 0 To 2
Range("A" & i + 1).Value = myArray(i)
Next i
End Sub
執行的結果如下
原本預計將甲乙丙三個字加入A1~A3的儲存格,因為在第二次ReDim加上Preserve關鍵字,因此在重新使用ReDim的時候,資料已保存。
關於陣列的上限值和下限值的確認
陣列索引值的上限值和下限值,會因為是否有 Option Base
設定的起始值或變數宣告所指定的上限值和下限值而有所不同。
又或者在動態陣列內,元素的個數並非如靜態陣列在一剛開始就指定,而是在程式過程中指定,也因為如此,如果要確定陣列的上限值和下限值會變得困難。
在VBA中如果想要確認陣列的上限值和下限值,可以使用LBound函數及UBound函數來確認。
LBound函數 :
確認陣列的下限值
UBound函數 :
確認陣列的上限值
基本格式
Point!
取得陣列下限值 : 使用 LBound函數
LBound (陣列的變數名稱)
取得陣列上限值 : 使用 UBound函數
UBound (陣列的變數名稱)
範例 : 靜態陣列 - 索引值預設為0開始
Sub ArrayTest2()
' 索引值預設從 0 開始~
' 宣告上限值為2的陣列,
' 因為陣列開始值為0, 所以可放入3個元素
Dim myArray(2) As String
myArray(0) = "My"
myArray(1) = "Array"
myArray(2) = "Test"
MsgBox "myArray陣列的" & Chr(10) & "上限值為 : " & UBound(myArray) & Chr(10) & "下限值為 : " & LBound(myArray)
End Sub
執行的結果如下
範例 : 靜態陣列 - 索引值設定為從1開始
Option Base 1
Sub ArrayTest3()
' 加上Option Base 1 , 索引值預設從 1 開始~
' 宣告上限值為2的陣列,
Dim myArray As Variant
'將元素放到Array函數中
myArray = Array("小王", #9/20/2023#, True)
MsgBox "myArray陣列的" & Chr(10) & "上限值為 : " & UBound(myArray) & Chr(10) & "下限值為 : " & LBound(myArray)
End Sub
執行的結果如下
範例 : 靜態陣列 - 索引值範圍為指定時
Sub ArrayTest4()
' 加上指定的索引值,索引值從指定數值開始~
Dim myArray(6 To 8) As String
'將數值指定到myArray陣列中
myArray(6) = "甲"
myArray(7) = "乙"
myArray(8) = "丙"
MsgBox "myArray陣列的" & Chr(10) & "上限值為 : " & UBound(myArray) & Chr(10) & "下限值為 : " & LBound(myArray)
End Sub
執行的結果如下
範例 : 動態陣列 - 未加上 Preserve關鍵字
Sub 元素個數變更3()
' 未使用Preserve關鍵字時 ============================
' 宣告陣列變數 myArray為字串型態,後面()括號空白,不輸入上限值
Dim myArray() As String
'使用ReDim決定上限值為1
ReDim myArray(1)
'宣告變數名稱 i 為整數型態,供迴圈使用
Dim i As Integer
'設定myArray要放入的數值
myArray(0) = "甲"
myArray(1) = "乙"
' 第1次ReDim後的上下限
MsgBox "myArray陣列的" & Chr(10) & "上限值為 : " & UBound(myArray) & Chr(10) & "下限值為 : " & LBound(myArray)
'myArray想要追加資料,使用ReDim 重新設定上限值為2
' 追加Preserve關鍵字
ReDim myArray(2)
'追加設定myArray要放入的數值
myArray(2) = "丙"
' 第2次ReDim後的上下限
MsgBox "myArray陣列的" & Chr(10) & "上限值為 : " & UBound(myArray) & Chr(10) & "下限值為 : " & LBound(myArray)
'使用迴圈輸出資料
For i = 0 To 2
Range("A" & i + 1).Value = myArray(i)
Next i
End Sub
執行的結果如下
範例 : 動態陣列 - 加上 Preserve關鍵字
Sub 元素個數變更4()
' 使用Preserve關鍵字時 ============================
' 宣告陣列變數 myArray為字串型態,後面()括號空白,不輸入上限值
Dim myArray() As String
'使用ReDim決定上限值為1
ReDim myArray(1)
'宣告變數名稱 i 為整數型態,供迴圈使用
Dim i As Integer
'設定myArray要放入的數值
myArray(0) = "甲"
myArray(1) = "乙"
' 第1次ReDim後的上下限
MsgBox "myArray陣列的" & Chr(10) & "上限值為 : " & UBound(myArray) & Chr(10) & "下限值為 : " & LBound(myArray)
'myArray想要追加資料,使用ReDim 重新設定上限值為2
' 追加Preserve關鍵字
ReDim Preserve myArray(2)
'追加設定myArray要放入的數值
myArray(2) = "丙"
' 第2次ReDim後的上下限
MsgBox "myArray陣列的" & Chr(10) & "上限值為 : " & UBound(myArray) & Chr(10) & "下限值為 : " & LBound(myArray)
'使用迴圈輸出資料
For i = 0 To 2
Range("A" & i + 1).Value = myArray(i)
Next i
End Sub
執行的結果如下
宣告為2維陣列
在Excel如果要以陣列的形式操作欄和列時,就需要使用2維陣列來處理。宣告為2維陣列時,在變數後面的()括號,要依據列和欄的順序,指定對應的上限值。
基本格式
Point!
Dim 變數名 (列數 , 欄數 ) As 資料型態
注意:
和指定索引值上下限範圍的 Dim 變數名 (下限值 to 上限值) 不同
千萬不要搞錯囉!!
範例 : 索引值預設為0開始
Sub 二維陣列()
' 宣告 myArray為2維陣列
' 列數(Row)上限值為2 , 因為索引值預設從0開始,所以為 0, 1, 2
' 欄數(Column)上限值為3 , 因為索引值預設從0開始,所以為 0, 1, 2, 3
Dim myArray(2, 3) As Variant
'宣告迴圈處理需要的變數 i , j , 資料型態為整數
Dim i As Integer, j As Integer
' 迴圈處理
For i = 0 To 2
For j = 0 To 3
myArray(i, j) = i * j
Cells(i + 1, j + 1).Value = myArray(i, j)
Next j
Next i
End Sub
執行的結果如下
範例 : 索引值設定為從1開始
Option Base 1
Sub 二維陣列2()
' 宣告 myArray為2維陣列
' 列數(Row)上限值為3 , 因為索引值指定從1開始,所以為 1, 2, 3
' 欄數(Column)上限值為4 , 因為索引值指定從1開始,所以為 1, 2, 3, 4
Dim myArray(3, 4) As Variant
'宣告迴圈處理需要的變數 i , j , 資料型態為整數
Dim i As Integer, j As Integer
' 迴圈處理
For i = 1 To 3
For j = 1 To 4
myArray(i, j) = i * j
Cells(i, j).Value = myArray(i, j)
Next j
Next i
End Sub
執行的結果如下
使用spilt函數切割成陣列
以下舉一個例子,假設取得一連串的資料,每一筆資料都是相連,如果想要分割到其他的儲存格,這時候可以使用Split函數進行操作。
當然你也可以使用資料剖析就可以進行分割。
使用Excel功能的資料剖析
步驟1 : 選取A欄
步驟2 : 點選上方資料頁籤,選取資料剖析
步驟3 : 進入資料剖析精靈 - 步驟3之1
選擇分隔符號,因為每一個列的資料中間都以 , 逗號區隔,接著按下一步
步驟4 : 進入資料剖析精靈 - 步驟3之2
接著分隔符號選取逗點,即可看見下方的預覽結果。接著按下一步。
步驟5 : 進入資料剖析精靈 - 步驟3之3
欄位的資料格式這邊選擇一般,即可看見下方的預覽結果。接著按下完成。
以上說明使用資料剖析的方式,在這邊先不深入其他的範圍,
接下來主要說明如果是這種情況,應該怎麼使用VBA進行操作。
使用Split函數
基本格式
Point!
Split (分割的字串 [, 分隔符號] )
範例 :
Sub splitArrayTest()
' 宣告陣列名稱為myArray 資料型態為字串
Dim myArray() As String
' 宣告變數 i , j , 為整數型態
Dim i As Integer, j As Integer
' 迴圈處理
For i = 0 To 2
' 分割處理每一個列Row的資料,並存到陣列變數
myArray = Split(Cells(i + 1, 1).Value, ",")
'接著處理myArray的資料
For j = 0 To UBound(myArray)
' 把資料存到儲存格內
Cells(i + 1, j + 2).Value = myArray(j)
Next j
Next i
End Sub
執行的結果如下
使用Join函數連接陣列元素成字串
既然有將字串分割的函數Split,那麼如果想要將元素合併成字串呢?
這時候就要使用Join 函數來進行連接了。
使用Join函數
基本格式
Point!
Join (1維陣列 , 分隔符號)
範例 :
Sub JoinToArrayTest()
' 宣告陣列名稱為myArray 資料型態為字串
Dim myArray(2) As String
' 宣告變數 i , j , 為整數型態
Dim i As Integer, j As Integer
' 迴圈處理
For i = 0 To 2
'接著處理myArray的資料
For j = 0 To UBound(myArray)
'處理每一個列Row的資料,將陣列的元素存到陣列變數
myArray(j) = Cells(i + 1, j + 1).Value
Next j
' 把陣列變數的元素Join起來,將資料存到儲存格內
' 分隔符號使用逗號
Cells(i + 1, 4).Value = Join(myArray, ",")
Next i
End Sub
執行的結果如下