VBA 配列
In this Article
VBAでは、配列は複数の値を保持することができる単一の変数です。 配列は、セルの範囲のようなものだと考えてください。配列は、1次元(1つの列を考える)、2次元(複数の行と列を考える)、または多次元にすることができます。 配列の値は、配列内の位置(インデックス番号)でアクセスすることができます。
VBA配列クイックシート
配列
arr(1) = “one”
arr(2) = “two”
arr(3) = “three”
Dim cell As Range, i As Integer
i = LBound(arr)
For Each cell In Range(“A1:A3”)
i = i + 1
arr(i) = cell.value
Next cell
For i = LBound(arr) To UBound (arr)
MsgBox arr(i)
Next i
sName = Join(arr, “:”)
VBAの配列の例
具体的な説明に入る前に、完全な例を見てみましょう。
Sub ArrayExample()
Dim strNames(1 to 4) as String
strNames(1) = "シェリー".
strNames(2) = "スティーブ"
strNames(3) = "ニーマ"
strNames(4) = "ホセ"
msgbox strNames(3)
End Sub
ここでは、サイズ4(4つの値を格納できる)の1次元文字列配列:strNamesを作成し、4つの値を代入しています。最後に、3番目の値をメッセージボックスに表示しています。 この場合、配列の使用によるメリットは小さく、4つの変数宣言の代わりに1つの変数宣言が必要なだけです。
では、配列の真の力を示す例を見てみましょう。
Sub ArrayExample2()
Dim strNames(1 To 60000) As String
Dim i As Long
For i = 1 To 60000
strNames(i) = Cells(i, 1).Value
Next i
End Sub
ここでは、6万個の値を格納できる配列を作成し、ワークシートのA列から素早く配列に代入しています。
配列の利点は? – スピード!
配列はExcelのワークシートに似ていると思われるかもしれません。
- 各セル(または配列の項目)ごとに値を設定することができる
- 各セル(または配列の項目)は、その行と列の位置でアクセスできる。
- ワークシートの例:cells(1,4).value = “1行目、4列目”
- 配列の例:arrVar(1,4) = “1行目、4列目”
では、なぜわざわざ配列なのでしょうか? Excelのセルに直接値を読み書きすればいいのでは? 一言で言えば、「速い」のです。 Excelのセルへの読み書きは時間がかかります。それに比べると配列の方がはるかに速いのです。
配列の作成と宣言
注意: 配列は複数の「次元」を持つことができます。注意:配列は複数の「次元」を持つことができますが、ここではシンプルにするため、1次元の配列のみを扱います。このチュートリアルの後半で、複数次元の配列について紹介します。
静的な配列
静的配列は、サイズを変更することができない配列です。逆に、動的な配列はサイズを変更することができます。 宣言の仕方も少し違います。まず、静的配列について見てみましょう。
注意:もし配列のサイズが変わらないのであれば、静的な配列を使いましょう。
静的配列変数の宣言は、通常の変数の宣言とほとんど変わりませんが、配列のサイズを定義する必要があります。配列のサイズを指定する方法にはいくつか種類があります。
Sub StaticArray1()
'添字が 1,2,3,4 の配列を作成する
Dim arrDemo1(1 To 4) As String
'添字が 4,5,6,7 の配列を作成する
Dim arrDemo2(4 To 7) As Long
'添字が 0,1,2,3 の配列を作成する
Dim arrDemo3(0 To 3) As Long
End Sub
また、配列のサイズだけを入力することもできます。
Sub StaticArray2()
'添字が 0,1,2,3 の配列を作成する
Dim arrDemo1(3) As String
End Sub
重要!配列はデフォルトで0から始まるので、Dim arrDemo1(3)は 0,1,2,3 の添字を持つ配列を作成することに注意してください。 モジュールの先頭でOption Base 1を宣言すれば、配列が 1 の位置から始まるようになります。
Option Base 1
Sub StaticArray3()
'添字 1,2,3 を持つ配列を作成します。
Dim arrDemo1(3) As String
End Sub
しかし、配列の開始位置と終了位置を明示的に宣言する方が、はるかに簡単で、混乱も少ないと思います。
動的な配列
動的な配列は、サイズが変更可能な(あるいはサイズを定義する必要のない)配列です。 動的配列の宣言方法は2通りあります。
Variant型配列
動的な配列を宣言する最初の方法は、配列の型をVariant型に設定することです。
Dim arrVar() As Variant
Variant型配列では、配列のサイズを定義する必要はありません。サイズは自動的に調整されます。 ただ、配列は添字は0から始まることを覚えておいてください。(モジュールのトップにOption Base 1を追加していない限り。)
Sub VariantArray()
Dim arrVar() As Variant
'値の定義 (添字= 0,1,2,3)
arrVar = Array(1, 2, 3, 4)
'値の変更(添字=0,1,2,3,4)
arrVar = Array("1a", "2a", "3a", "4a", "5a")。
'位置4のを出力("5a")
MsgBox arrVar(4)
End Sub
非Variant型の動的配列
非Variant型の配列では、配列に値を代入する前に、配列のサイズを定義する必要があります。ただし、配列を作成する処理は少し異なります。
Sub DynamicArray1()
Dim arrDemo1() As String
'位置1,2,3,4で配列のサイズを変更する
ReDim arrDemo1(1 To 4)
End Sub
まず、配列のサイズを省略する以外は、静的配列と同じように配列を宣言します。
Dim arrDemo1() As String
配列のサイズを設定する場合は、ReDimコマンドを使用して配列のサイズを設定します。
'配列のサイズを 1,2,3,4 の位置で変更します。
ReDim arrDemo1(1 To 4)
ReDimは配列のサイズを変更します。ReDimとReDim Preserveの違いについては、以下をお読みください。
ReDimとReDim Preserveの比較
ReDimコマンドを使用すると、配列から既存の値をすべて消去します。 代わりに、ReDim Preserveを使用すると、配列の値を保持することができます。
'位置1,2,3,4で配列のサイズを変更する(既存の値を保持する)
ReDim Preserve arrDemo1(1 To 4)
配列の宣言の簡略化
上記の内容を読んで、あなたは圧倒されたように感じるかもしれません。そこで、この後は静的な配列を使って説明します。
配列の値を設定する
配列の値を設定するのはとても簡単です。 静的配列の場合、配列の各位置を一度に定義する必要があります。
Sub ArrayExample()
Dim strNames(1 to 4) as String
strNames(1) = "シェリー".
strNames(2) = "スティーブ"
strNames(3) = "ニーマ"
strNames(4) = "ホセ"
End Sub
Variant型配列では、1行で配列全体を定義することができます。(小さな配列の場合のみ実用的です。)
Sub ArrayExample_1Line()
Dim strNames() As Variant
strNames = Array("シェリー", "スティーブ", "ニーマ", "ホセ")
End Sub
存在しない配列の位置に値を定義しようとすると、「Subscript Out of Range」エラーが発生します。
strNames(5) = "シャノン"
以下、「セルの範囲を配列に代入する」では、ループを使って大量の値を素早く配列に代入する方法を紹介します。
配列の値の取得
配列の値も同じように取得することができます。 以下の例では、配列の値をセルに書き込んでいます。
Range("A1").Value = strNames(1)
Range("A2").Value = strNames(2)
Range("A3").Value = strNames(3)
Range("A4").Value = strNames(4)
セルの範囲を配列に代入する
範囲を配列に代入するには、ループを使用します。
Sub RangeToArray()
Dim strNames(1 To 60000) As String
Dim i As Long
For i = 1 To 60000
strNames(i) = Cells(i, 1).Value
Next i
End Sub
これは、セルA1:A60000をループして、セルの値を配列に代入しています。
配列から範囲への出力
また、ループを使って、配列をセルの範囲に代入することもできます。
For i = 1 To 60000
Cells(i, 1).Value = strNames(i)
Next i
これは先の例とは逆に、配列の値をセルA1:A60000に代入することになります。
2次元・多次元配列
これまで、1次元の配列だけを扱ってきました。 しかし、配列は最大で32次元まで持つことができます。 1次元配列はExcelのセル1行や1列、2次元配列は複数の行と列を持つExcelワークシート全体、3次元配列は複数の行と列を持つシートを含むワークブック全体と考えてください(3次元配列はルービックキューブのようなものだとも言えます)。
多次元配列の例
次に、異なる次元の配列を扱う例を示します。
1次元配列の例
このプロシージャは、これまでの配列の例を1つのプロシージャにまとめ、実際の配列の使い方を示しています。
Sub ArrayEx_1d()
Dim strNames(1 To 60000) As String
Dim i As Long
'配列に値を代入する
For i = 1 To 60000
strNames(i) = Cells(i, 1).Value
Next i
'配列の値を範囲に出力する
For i = 1 To 60000
Sheets("Output").Cells(i, 1).Value=strNames(i)。
Next i
End Sub
2次元配列の例
このプロシージャには、2次元配列の例が含まれています。
Sub ArrayEx_2d()
Dim strNames(1 To 60000, 1 To 10) As String
Dim i As Long, j As Long
'配列に値を割り当てる
For i = 1 To 60000
For j = 1 To 10
strNames(i, j) = Cells(i, j).Value
Next j
Next i
'配列の値を範囲に出力する
For i = 1 To 60000
For j = 1 To 10
Sheets("Output").Cells(i, j).Value = strNames(i, j)
Next j
Next i
End Sub
3次元配列の例
このプロシージャには、複数のシートを操作するための3次元配列の例が含まれています。
Sub ArrayEx_3d()
Dim strNames(1 To 60000, 1 To 10, 1 To 3) As String
Dim i As Long, j As Long, k As Long
'配列に値を代入する
For k = 1 To 3
For i = 1 To 60000
For j = 1 To 10
strNames(i, j, k) = Sheets("Sheet" & k).Cells(i, j).Value
Next j
Next i
Next k
'配列の値を範囲に出力する
For k = 1 To 3
For i = 1 To 60000
For j = 1 To 10
Sheets("Output" & k).Cells(i, j).Value = strNames(i, j, k)
Next j
Next i
Next k
End Sub
配列の長さ・サイズ
これまで、さまざまな種類の配列について紹介し、配列の宣言方法と配列の値の取得/設定方法を説明しました。次に、配列を扱うために必要なその他のトピックに焦点を当てます。
UBound関数とLBound関数
配列の長さ/サイズを取得する最初のステップは、UBound関数とLBound関数を使用して配列の上下の境界を取得することです。
Sub UBoundLBound()
Dim strNames(1 To 4) As String
MsgBox UBound(strNames)
MsgBox LBound(strNames)
End Sub
2つの値の差に1を足し、長さを求めます。
GetArrLength = UBound(strNames) - LBound(strNames) + 1
配列の長さ関数
1次元の配列の長さを求める関数を以下に示します。
Public Function GetArrLength(a As Variant) As Long
If IsEmpty(a) Then
GetArrLength = 0
Else
GetArrLength = UBound(a) - LBound(a) + 1
End If
End Function
2次元配列のサイズを計算する必要がありますか?次のチュートリアルをご覧ください:配列のサイズを計算する
配列のループ処理
配列の中をループする方法は2つあります。 ひとつは、配列の番号の位置に対応する整数をループする方法です。配列のサイズがわかっている場合は、サイズを直接指定することができます。
Sub ArrayExample_Loop1()
Dim strNames(1 To 4) As String
Dim i As Long
strNames(1) = "シェリー".
strNames(2) = "スティーブ"
strNames(3) = "ニーマ"
strNames(4) = "ホセ"
For i = 1 To 4
MsgBox strNames(i)
Next i
End Sub
ただし、配列のサイズがわからない場合(配列が動的な場合)には、前節のLBound関数とUBound関数を使用することができます。
Sub ArrayExample_Loop2()
Dim strNames(1 To 4) As String
Dim i As Long
strNames(1) = "シェリー"
strNames(2) = "スティーブ"
strNames(3) = "ニーマ"
strNames(4) = "ホセ"
For i = LBound(strNames) To UBound(strNames)
MsgBox strNames(i)
Next i
End Sub
For Eachによる配列のループ
2つ目の方法は、For Eachループを使う方法です。これは、配列の各項目をループします。
Sub ArrayExample_Loop3()
Dim strNames(1 To 4) As String
Dim Item
strNames(1) = "シェリー"
strNames(2) = "スティーブ"
strNames(3) = "ニーマ"
strNames(4) = "ホセ"
For Each Item In strNames
MsgBox Item
Next Item
End Sub
For Eachによる配列のループは、1次元配列だけでなく、多次元配列でも動作します。
2次元配列のループ処理
UBound関数とLBound関数を使って、多次元配列をループ処理することもできます。この例では、2次元配列の中をループします。 UBound関数とLBound関数では、上限と下限を求める配列の次元を指定できます。(1次元は1、2次元は2)
Sub ArrayExample_Loop4()
Dim strNames(1 To 4, 1 To 2) As String
Dim i As Long, j As Long
strNames(1, 1) = "シェリー"
strNames(2, 1) = "スティーブ"
strNames(3, 1) = "ニーマ"
strNames(4, 1) = "ホセ"
strNames(1, 2) = "シェルビー"
strNames(2, 2) = "スティーブン"
strNames(3, 2) = "ニモ"
strNames(4, 2) = "ジェシー"
For j = LBound(strNames, 2) To UBound(strNames, 2)
For i = LBound(strNames, 1) To UBound(strNames, 1)
MsgBox strNames(i, j)
Next i
Next j
End Sub
その他の配列タスク
配列のクリア
配列全体を消去するには、Eraseステートメントを使用します。
Erase strNames
使用例:
Sub ArrayExample()
Dim strNames(1 to 4) as String
strNames(1) = "シェリー"
strNames(2) = "スティーブ"
strNames(3) = "ニーマ"
strNames(4) = "ホセ"
Erase strNames
End Sub
また、配列の一部を消去して、サイズを変更するReDimも可能です。
ReDim strNames(1 to 2)
これは、配列のサイズを2に変更し、3番目と4番目の要素を削除しています。
配列のカウント
前述のUBound関数とLBound関数を使って、配列の各次元のサイズを得ることができます。 また、入力された項目(または特定の条件を満たす項目)の数を数えるには、配列の中をループさせます。
この例では、オブジェクトの配列をループして、その中で見つかった空白でない文字列の数を数えます。
Sub ArrayLoopandCount()
Dim strNames(1 To 4) As String
Dim i As Long, n As Long
strNames(1) = "シェリー"
strNames(2) = "スティーブ"
For i = LBound(strNames) To UBound(strNames)
If strNames(i) <> "" Then
n = n + 1
End If
Next i
MsgBox n & " 個の空白でない値が見つかりました。"
End Sub
重複の除去
ある時点で、配列から重複を削除したくなることがあります。残念ながら、VBAにはこれを行うためのビルトインの機能がありません。しかし、配列から重複を削除する関数を作成しました(長すぎるので、このチュートリアルでは紹介しませんが、詳細はリンク先をご覧ください)。
Filter
VBAのFilter関数を使うと、配列にフィルタをかけることができます。これは、フィルタリングされた値のみを含む新しい配列を作成することによって行われます。 下記は簡単な例ですが、様々なニーズに対応するため、より多くの例について記事を読むようにしてください。
Sub Filter_Match()
'配列を定義する
Dim strNames As Variant
strNames = Array("スティーブ・スミス", "シャノン・スミス", "ライアン・ジョンソン")
'配列をフィルタする
Dim strSubNames As Variant
strSubNames = Filter(strNames, "スミス")
'フィルタされた配列を数える
MsgBox UBound(strSubNames) - LBound(strSubNames) + 1 & " 名の名前が見つかりました。"
End Sub
IsArray関数
変数が配列かどうかを調べるには、IsArray Functionを使用します。
Sub IsArrayEx()
'配列を作成する
Dim arrDemo1(3) As String
'通常の文字列変数を作成する
Dim str As String
MsgBox IsArray(arrDemo1)
MsgBox IsArray(str)
End Sub
配列の結合
Join関数を使って、配列全体をすばやく「結合」することができます。
Sub Array_Join()
Dim strNames(1 To 4) As String
Dim joinNames As String
strNames(1) = "シェリー"
strNames(2) = "スティーブ"
strNames(3) = "ニーマ"
strNames(4) = "ホセ"
joinNames = Join(strNames, ",")
MsgBox joinNames
End Sub
文字列を配列に分割する
VBAのSplit関数は、文字列を元の文字列から値を含む配列に分割します。例を見てみましょう。
Sub Array_Split()
Dim Names() As String
Dim joinedNames As String
joinedNames = "シェリー,スティーブ,ニーマ,ホセ"
Names = Split(joinedNames, ",")
MsgBox Names(1)
End Sub
ここでは、”シェリー,スティーブ,ニーマ,ホセ”という文字列をカンマ区切り(”,”)でサイズ4の配列に分割しています。
配列定数
VBAでは、配列を定数として宣言することが出来ません。しかし、Arrayとして使用する関数を作成することで、これを回避することができます。
' ConstantArrayを定義
Function ConstantArray()
ConstantArray = Array(4, 12, 21, 100, 5)
End Function
' ConstantArrayの値を取得
Sub RetrieveValues()
MsgBox ConstantArray(3)
End Sub
配列のコピー
VBAを使用して、配列をコピーするビルトインの機能はありません。ある配列から別の配列に値を割り当てるためには、ループを使用する必要があります。
Sub CopyArray()
Dim Arr1(1 To 100) As Long
Dim Arr2(1 To 100) As Long
Dim i As Long
'配列に初期値を代入
For i = 1 To 100
Arr1(i) = i
Next i
'Arr1からArr2へコピー
For i = 1 To 100
Arr2(i) = Arr1(i)
Next i
MsgBox Arr2(74)
End Sub
転置
VBAのビルトイン関数には、配列を転置する関数はありません。しかし、2次元の配列をTransposeする関数を書きました。詳しくは、記事を読んでください。
返り値が配列の関数
VBAの開発者がよく抱く疑問は、配列を返す関数をどのように作成するかということです。ほとんどの困難は、変量配列を使用することで解決されると思います。このトピックに関する記事を書きました。こちらをご覧ください:返り値が配列の関数
Access VBAで配列を使う
上記の配列の例のほとんどは、Access VBAでもExcel VBAと全く同じように動作します。 一つ大きな違いは、Accessのデータを使って配列を生成する場合、RangeオブジェクトではなくRecordSetオブジェクトをループする必要があることです。
Sub RangeToArrayAccess()
On Error Resume Next
Dim strNames() As String
Dim i As Long
Dim iCount As Long
Dim dbs As Database
Dim rst As Recordset
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset("tblClients", dbOpenDynaset)
With rst
.MoveLast
.MoveFirst
iCount = .RecordCount
ReDim strNames(1 To iCount)
For i = 1 To iCount
strNames(i) = rst.Fields("ClientName")
.MoveNext
Next i
End With
rst.Close
Set rst = Nothing
Set dbs = Nothing
End Sub
[テーブル id=21 row_highlight=”YES” /].