VBAには配列のunshiftメソッドは無い
主にWeb系で扱うプログラミング言語には配列の操作を行うメソッドがあります。ここでは配列の先頭にデータを追加する処理をVBA用にした関数を紹介します。
先頭に追加する処理はプログラミング言語によって関数名は異なりますが、JavaScriptやPHPやRubyなど一般的には「unshift」という名前が多いため、以下で紹介する関数はそれに合わせて「ArrayUnShift」という関数名にしています。
配列の先頭や終端にデータの追加や削除を行うには
VBAの配列は単にデータを複数保持しているだけですが、現在主流のプログラミング言語では配列はクラスとして管理されており、配列を操作するための関数が複数用意されていることが一般的です。
プログラミング言語によって関数名は異なりますが、配列を操作する関数として一般的には以下のようなものがあります。
関数名 | 用途 | 関数戻り値 |
---|---|---|
shift | 配列の先頭データを切り取る | 切り取った先頭データ |
unshift | 配列の先頭にデータを追加する | 追加後の配列要素数 |
pop | 配列の終端データを切り取る | 切り取った終端データ |
push | 配列の終端にデータを追加する | 追加後の配列要素数 |
これらの関数をVBAでも使えるように以下に説明します。なお、それぞれの実装方法が異なるためページを分けて説明しています。
- VBAの配列の先頭データを切り取る(shift)
- VBAの配列の先頭にデータを追加する(unshift) 当ページ
- VBAの配列の終端データを切り取る(pop)
- VBAの配列の終端にデータを切り取る(push)
配列の先頭にデータを追加するコード(unshift)
以下のコードは配列の先頭(配列のインデックスが0)の位置にデータを追加する関数です。JavaScriptやPHPなどでのunshiftメソッドになります。
JavaScriptなどのunshiftメソッドは複数のデータを1度に追加できますが、ここでは追加できるデータは1つに制限しています。
使い方は、関数の引数の1つ目に配列、2つ目に追加するデータを指定します。関数の戻り値はデータ追加後の配列の要素数です。
戻り値の要素数について補足します。VBAの場合の配列の要素数はUBound関数を使うことが一般的で、UBound関数は配列の要素数ではなく配列終端の要素位置を返すため、例えば[0] [1] [2]の3つのデータを持つ配列でもUBound関数は3ではなく2を返します。それに合わせて厳密な要素数ではなくUBound関数の値を関数戻り値として返却しています。それが気に入らない場合は戻り値に+1した値を返すようにいじってください。
配列は1次元配列を対象としており、配列のデータ型はなんでもOKです。なんでもOKにするために、オブジェクト型かどうかの判定をIsObject関数で行い、オブジェクト型であれば値の代入方法でSetを使い、そうでなければ=で代入するようにしています。
IsObject関数の詳細については「VBAのオブジェクト変数かどうかを判定する(IsObject)」をご参照ください。
引数が配列でない場合は処理しません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
'// 先頭に追加 '// 引数1:配列 '// 引数2:追加するデータ '// 戻り値:追加後の配列要素数(UBound関数結果) Function ArrayUnShift(ar As Variant, addValue As Variant) As Long '// 引数が配列でない場合 If IsArray(ar) = False Then '// 処理せず抜ける Exit Function End If '// 配列要素数を取得 Dim iSize As Long '// 配列サイズ '// 配列サイズを拡張後のサイズで取得 iSize = UBound(ar) + 1 '// 拡張 ReDim Preserve ar(iSize) Dim i As Long '// ループカウンタ '// 最後尾の直前から先頭に向かってループ For i = iSize - 1 To 0 Step -1 '// オブジェクト型変数の場合 If IsObject(ar(i)) = True Then '// 次の要素に現在ループ値を設定 Set ar(i + 1) = ar(i) '// プリミティブ型変数(IntegerやStringなど)の場合 Else '// 次の要素に現在ループ値を設定 ar(i + 1) = ar(i) End If Next '// 配列の先頭に引数の追加値を設定 '// オブジェクト型変数の場合 If IsObject(ar(0)) = True Then '// 先頭に現在ループ値を設定 Set ar(0) = addValue '// プリミティブ型変数(IntegerやStringなど)の場合 Else '// 先頭に現在ループ値を設定 ar(0) = addValue End If '// 要素数を返却 ArrayUnShift = UBound(ar) End Function |
使い方
上のArrayUnShift関数をString型の配列とRange型の配列のそれぞれを使った場合の利用例です。
引数に配列と追加するデータを渡すだけです。戻り値として配列要素数を受け取っています。検証用として、データ追加後の配列の各要素を出力しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
Sub ArrayUnShiftTest() Dim ar() As String Dim s, c '// String型配列 ReDim ar(3) ar(0) = "abc" ar(1) = "bbb" ar(2) = "ccc" ar(3) = "ddd" '// 先頭に追加 c = ArrayUnShift(ar, "AAA") Debug.Print c '// 要素数を出力 For Each s In ar Debug.Print s Next '// 要素が1つの配列 ReDim ar(0) ar(0) = "!" '// 先頭に追加 c = ArrayUnShift(ar, "BBB") Debug.Print c '// 要素数を出力 For Each s In ar Debug.Print s Next '// Range型配列 Dim r() As Range ReDim r(2) Set r(0) = Range("A1") Set r(1) = Range("B2") Set r(2) = Range("C3:D4") '// 先頭に追加 c = ArrayUnShift(r, Range("C1")) Debug.Print c For Each s In r Debug.Print s.Address(False, False) Next End Sub |
実行結果
4
AAA 追加データ
abc
bbb
ccc
ddd
1
BBB 追加データ
!
3
C1 追加データ
A1
B2
C3:D4