第24回 「Excel VBAでの動的配列」と「Rangeオブジェクトと配列の操作」

配列の操作

VBAでは push, shiftなどの気の利いた関数が用意されていない。
というか、動的配列を使うのが少し面倒。

push, shiftなどは用意されていないので普通に、

hoge(10) = "aaa"
hoge(11) = "bbb"

というように代入する形をとる。
このとき配列の大きさは決まっていないといけない。

動的配列

動的に配列を扱いたい場合、
 1.要素数を指定しないで宣言
 2.処理の途中で ReDim を使って要素数を指定
 3.ReDimで要素数を変更した場合にもとの配列の中身を残しておきたいなら Preserve を使う

Sub 動的配列()
 Dim arr
 
 '----------------------------------------------------------------------
 ' まず要素数を決定
 '----------------------------------------------------------------------
 ReDim arr(1)    '要素数を2個に決定 引数の数は-1であることに注意!
 
 arr(0) = "aa"
 arr(1) = "bb"

 Debug.Print Join(arr, ",")         ' 結果 =>  aa,bb
 
 
 '----------------------------------------------------------------------
 '  Preserve を使って ReDim
 '----------------------------------------------------------------------
 ReDim Preserve arr(2)
 
 arr(2) = "cc"
 
 Debug.Print Join(arr, ",")        ' 結果 =>  aa,bb,cc

 '----------------------------------------------------------------------
 '  Preserve を使わず ReDim
 '----------------------------------------------------------------------
 ReDim arr(3)
 
 arr(3) = "dd"
 
 Debug.Print Join(arr, ",")        ' 結果 =>  ,,,dd

 
End Sub

RangeオブジェクトのValue

RangeオブジェクトのValueは2次元配列を返す。
これはA1:A4などの1次元のセルを選択した場合も同様である。

また、Valueに値を代入することでセルの内容を変更することができる。
2次元配列を代入した場合は、2次元のセルを変更できるようである。つまり、複数のセルを同時に書き換えることができる。

実用的な例

Sub A1からA4までのデータをJoin()

  ' str配列を要素数を指定せず宣言
  Dim str() As String

  ' A1:A4の値を取得 Valueは2次元配列で値を返してくる
  arr = Worksheets(1).Range("A1:A4").Value

  ' ReDimでstr配列の要素を決定
  ReDim str(UBound(arr))
  
  ' LBoundはインデックスの最小値、UBoundはインデックスの最大値
  For i = LBound(arr) To UBound(arr)
    ' str配列にA1:A4の値を詰め込み
    str(i - LBound(arr)) = arr(i, 1)
  Next
  
  ' A5にstr配列の内容をJoinして書き込み
  Worksheets(1).Range("A5").Value = Join(str, ",")

End Sub