VBA陣列使用方法整理,看這篇就夠了




在進入本篇文章之前,先來了解一下什麼是陣列。

根據維基百科對陣列的敘述:
在電腦科學中,陣列資料結構(英語: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
欄位的資料格式這邊選擇一般,即可看見下方的預覽結果。接著按下完成


步驟6 : 接著就可以看到資料已經被切割了。



以上說明使用資料剖析的方式,在這邊先不深入其他的範圍,
接下來主要說明如果是這種情況,應該怎麼使用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


執行的結果如下





張貼留言 (0)
較新的 較舊