【初心者向け】エクセルVBAの配列とは?配列の使いどころを解説します

エクセルVBAの「配列」は、概念はわかりやすいけれど、使い道がわからないという方が多いようです。

そこで、このページでは、配列の基本的な使い方とともに、どういう用途で使うのかについて詳しく解説していきます。


配列とは何か?

配列は、

  • 複数の変数を一気に確保して
  • どの変数を使うかを添え字で指定できる

機能のことをいいます。

後で、詳しく書きますが「添え字で指定できる」というところが大きなポイントです。

書式

次のように、通常の変数宣言の後に「( ... to ...)」という形の指定をします。

Dim 配列名([下限] to [上限])

たとえば、

Dim Data(1 to 3)

という変数宣言をすると、

  • Data(1)
  • Data(2)
  • Data(3)

という3つの変数を一気に確保することができます。

添え字の「下限」は「0」「1」のどちらかにしましょう。

VBAの場合は、セル範囲を配列に格納すると「下限」が自動的に「1」になってしまうので、それに合わせてこだわりがなければ下限は「1」にすることをおすすめします。

下限の入力を省略した場合

Dim文で、下限の入力を省略して、

Dim Data(3)

と変数宣言をすることもできます。

この場合には、モジュール冒頭の「Option Base」文の指定に応じて、下限は「0」または「1」に自動的に設定されます(「Option Base」の指定がない場合には、下限は「0」になります)。

たとえば、Option Baseの指定がない場合に「Dim Data(3)」と変数宣言をすると、下記のように4つ分の領域が確保されます。

  • Data(0)
  • Data(1)
  • Data(2)
  • Data(3)

具体例

次のマクロを実行すると、
A1セルに10、B1セルに20、C1セルに30が記入されます。

Sub ArrayTest()
  Dim Data(1 to 3)

  Data(1) = 10
  Data(2) = 20
  Data(3) = 30

  Cells(1, 1).Value = Data(1)  ' A1セルに10を記入
  Cells(1, 2).Value = Data(2)  ' B1セルに20を記入
  Cells(1, 3).Value = Data(3)  ' C1セルに30を記入

End Sub

配列の書式はわかったけれど、どう使えばいいの?

配列の勉強をしていると、配列の書式はわかった。でも、どう使えばいいのかピンと来ないというふうに感じる方が多いようです。

そこで、ここからは、配列の具体的な使い道を紹介しようと思います。

For~Nextと配列を組み合わせる

配列は、どの変数を使うかを「添え字」で指定できることが特徴です。

そして、この特徴は「For~Next」ループと非常に相性がいいのです。

 

実際の例として「新規シートを3枚挿入して、指定の名前に変更する」処理を書いてみようと思います。

配列を使わない場合
Sub AddSheet()
  Dim NewSheetNames1
  NewSheetNames1 = "新シート1"
  
  Dim NewSheetNames2
  NewSheetNames2 = "新シート2"
  
  Dim NewSheetNames3
  NewSheetNames3 = "新シート3"

  Worksheets.Add after:=Worksheets(Worksheets.Count) '末尾にワークシートを挿入
  ActiveSheet.Name = NewSheetNames1
  
  Worksheets.Add after:=Worksheets(Worksheets.Count) '末尾にワークシートを挿入
  ActiveSheet.Name = NewSheetNames2
  
  Worksheets.Add after:=Worksheets(Worksheets.Count) '末尾にワークシートを挿入
  ActiveSheet.Name = NewSheetNames3

End Sub
配列を使った場合
Sub AddSheetArray()
  Dim NewSheetNames(1 To 3)

  NewSheetNames(1) = "新シート1"
  NewSheetNames(2) = "新シート2"
  NewSheetNames(3) = "新シート3"

  Dim SheetNo As Long
  For SheetNo = 1 To 3
    Worksheets.Add after:=Worksheets(Worksheets.Count) '末尾にシートを挿入
    ActiveSheet.Name = NewSheetNames(SheetNo)          '挿入したシートの名前を変更
  Next

End Sub

注目してほしいのは32行目です。

配列を使って「添え字」で、参照する変数を切り替えることができるため、「シート挿入」→「シート名変更」のロジックをFor~Nextループでまとめることができるのです。

If文の代わりに配列を使う

配列は、見方を少し変えると、添え字(=「整数」)を指定することで、対応する値を取得できるものだとも考えられます。

そのため、整数値に応じて、条件分岐するような場面で「If文の代わりに使う」ことができます。

たとえば、2行目~10行目まで、次のような計算をして、その集計結果をD11セルに表示させようと思います。

  • B列が「1」のときは、D列の値を「足す」
  • C列が「2」のときは、D列の値を「引く」
配列を使わない場合
Sub CalcBalance()
  Dim Balance

  Dim Row
  For Row = 2 To 10
    If Cells(Row, 2).Value = 1 Then
      Balance = Balance + Cells(Row, 4).Value * 1 '入金データは残高に加算
    Else
      Balance = Balance + Cells(Row, 4).Value * -1 '出金データは残高から減算
    End If
  Next
  
  Cells(11, 4).Value = Balance '計算結果を表示

End Sub

配列を使ったときとの対比をわかりやすくするため、7行目、9行目の書き方がすこしわざとらしくなっています。

配列を使った場合
Sub CalcBalanceArray()
  Dim KubunToSign(1 To 2)
  KubunToSign(1) = 1
  KubunToSign(2) = -1
  
  Dim Balance
  
  Dim Row
  For Row = 2 To 10
    Balance = Balance + Cells(Row, 4).Value * KubunToSign(Cells(Row, 2).Value)
  Next
  
  Cells(11, 4).Value = Balance '計算結果を表示
End Sub

26行目に注目してください。

If文で条件分岐をする代わりに、配列を使って同じロジックを実現しています。

文字列の結合

文字列を大量に結合する場合、1つ1つ文字列を結合していくより、配列とjoin関数を使って文字列結合をしたほが動作速度が速くなります。

配列を使わない場合
Sub ConcatStr()
  Dim Data As String
  
  Data = "A"
  Data = Data & ",B"
  Data = Data & ",C"
  
  Debug.Print Data  ' A,B,C
End Sub
配列を使った場合
Sub ConcatStrArr()
  Dim Parts(1 To 3)
  
  Parts(1) = "A"
  Parts(2) = "B"
  Parts(3) = "C"

  Dim Data
  Data = Join(Parts, ",")   'Partsの内容を「,」でつないで連結
  
  Debug.Print Data          ' A,B,C
End Sub

どちらも結果は一緒なのですが、配列を使ったほうが動作速度が速くなります。

また、今回のように、文字列を結合するときに、文字列の間に「区切り文字」をはさんで連結をする場合には、配列+Join関数を使うほうがプログラムをわかりやすく書くことができます。

文字列の分割

文字列を、区切り文字ごとに分割して細切れの文字列を取得したいときにはSplit関数を使うと簡単に分割できます。

Split関数による分割結果は「配列」に格納されるため、配列を使う必要があります。

配列を使わない場合

※複雑なプログラムになるので略

配列を使った場合
Sub SplitArr()
  Dim Data
  Data = "A,B,C"

  Dim Parts                 '※要素数・型を指定しない
  Parts = Split(Data, ",")  'Dataの内容を「,」で分割。
                            '自動的にDim Parts(0 to 2)された状態になる
  
  Debug.Print Parts(0)      'A ※添え字は常に0始まり
  Debug.Print Parts(1)      'B
  Debug.Print Parts(2)      'C
  
End Sub

Split関数を使うときには、その結果を入れる変数は、Dim文で要素数・型を指定しないことに注意してください。

実際、先ほどのソースコードの5行目を見て見ると、「Dim Parts」というように「要素数」「型」のどちらも指定していないことがわかります。

そして、Split関数を使った段階で、変数Partsは、自動的に「配列」になります。

VBAの仕様で、Split関数で作った配列は、必ず、添え字が「0」で始まる配列になりますので、ご注意ください。

2次元配列とは何か?

配列は、添え字を「複数」取ることもできます。

よく使われるのが、添え字を2つ使う「2次元配列」です。

書式

Dim 配列名([下限1] to [上限1], [下限2] to [上限2])

括弧の中を「,」で区切って「... to ...」という指定を「2つ」行います。

たとえば、

Dim Data(1 to 3,1 to 2)

という変数宣言をすると、

  • Data(1,1)
  • Data(1,2)
  • Data(2,1)
  • Data(2,2)
  • Data(3,1)
  • Data(3,2)

という6つの変数を一気に確保することができます。

2次元配列の使い道

2次元配列は、複数セルのデータを変数に取り込みたいときに便利です。

「セル」と「配列」の書き方がそっくりなので便利

次のマクロを実行すると、A1セル~B3セルの内容が、D1セル~E3セルに転記されることになります。

Sub RangeCopy()
  Dim Data(1 To 3, 1 To 2)

  Data(1, 1) = Cells(1, 1).Value ' A1セルの内容を代入
  Data(1, 2) = Cells(1, 2).Value ' B1セルの内容を代入
  Data(2, 1) = Cells(2, 1).Value ' A2セルの内容を代入
  Data(2, 2) = Cells(2, 2).Value ' B2セルの内容を代入
  Data(3, 1) = Cells(3, 1).Value ' A3セルの内容を代入
  Data(3, 2) = Cells(3, 2).Value ' B3セルの内容を代入

  Cells(1, 4).Value = Data(1, 1) ' D1セルに10を記入
  Cells(1, 5).Value = Data(1, 2) ' E1セルに20を記入
  Cells(2, 4).Value = Data(2, 1) ' D2セルに30を記入
  Cells(2, 5).Value = Data(2, 2) ' E2セルに40を記入
  Cells(3, 4).Value = Data(3, 1) ' D3セルに50を記入
  Cells(3, 5).Value = Data(3, 2) ' E3セルに60を記入
End Sub

先ほどのプログラムを見ると、Dataを2次元配列にしたおかげで、CellsとDataの書き方がそっくりになりました。

このように、2次元配列は「セル範囲を丸ごと読み込んだり、丸ごと書き込む」用途に使うと、プログラムがわかりやすく書けます。

セル範囲への読み込み、書き込みを高速にする

先ほどのプログラムを改良すると、さらにシンプルに書くことができ、しかも、実行速度を速くすることができます。

Sub RangeCopy2()
  Dim Data                       '※要素数・型を指定しない
  Data = Range("A1:B3").Value    ' A1セル~B3セルの内容をDataにコピー
                                 ' 自動的にDim Data(1 to 3,1 to 2)が実行された状態になる

  Range("D1:E3").Value = Data    ' D1セル~E3セルにDataの内容をコピー

End Sub

先ほどとまったく同じ意味のプログラムですが、一気に行数が短く・シンプルになりました。

しかも、実行速度もかなり速くなります。

 

実は、Range(あるいはCells)を呼び出す回数が少なくなればなるほど実行速度は速くなります。

改良前と改良後で呼び出す回数を比較すると改良後のほうが回数が少ないため、改良後のプログラムのほうが動作速度が速くなるのです。

  • 改良前:12回(Cellsの読み込みが6回、書き込みが6回)
  • 改良後:2回(Rangeの読み込みが1回、書き込みが1回)

今回程度のプログラムであれば体感できる差は付きませんが、セルへの読み書きが多いと、場合によっては、数十倍近く動作速度が変わります。

実行速度が遅いと感じたら、セルの読み書きは複数セルをまとめて行うように心がけてみてください。

セル範囲を読み書きするときに気をつけるべき点

セル範囲と2次元配列との間で、データの読み書きをするときには、何点か気をつけないといけないポイントがあります。

Dim文では何も指定しない

Dim文で配列として変数宣言をしてしまうとうまく動かず、エラーが出ます。

少し気持ち悪いかもしれませんが、変数宣言時は添え字の下限・上限の指定をせず、Variant型変数として宣言をしてください

  Dim Data
  Data = Range("A1:B3").Value    ' A1セル~B3セルの内容をDataにコピー

型を何も指定しなければ、自動的にVariant型になりますので、上記のように変数名のみ指定するのがおすすめです。

少し気持ち悪いかもしれませんが、3行目の代入後は2次元配列として使えるようになります

添え字は1から始まる

セル範囲を変数に代入した段階で、自動的に2次元配列になるわけですが、そのときの添え字は1から始まります

セル範囲を丸ごと変数に代入する場合、添え字を「0」始まりにすることはできませんので、気をつけてください。

一方で、前述したSplit関数を使うと、添え字が「0」始まりになってしまいます。

このように、VBAでは、言語仕様として、添え字を「0始まり」「1始まり」のどちらかに統一することはできません

気持ち悪いですが、仕方がないと思ってあきらめてください。

配列を使ううえで知っておいたほうがいい機能

配列の添え字の下限、上限を調べる

  • LBound関数:配列の添え字の「下限」
  • UBound関数:配列の添え字の「上限」

を調べることができます。

書式

LBound(配列名)
UBound(配列名)

具体例(Splitと組み合わせる)

Sub SplitArr2()
  Dim Data
  Data = "A,B,C"

  Dim Parts                 '※要素数・型を指定しない
  Parts = Split(Data, ",")  'Dataの内容を「,」で分割。
                            '自動的にDim Parts(0 to 2)された状態になる
  
  Dim C As Long
  For C = LBound(Parts) To UBound(Parts)
    Debug.Print Parts(C)
  Next

End Sub

このプログラムは、文字列の分割のところで紹介したプログラムを、For文とLBound、UBoundを使って書き換えたものです。

Splitを使うと、プログラムを実行してみるまで、配列の添え字の上限が決まらないため、事前に、For文の「To」の指定ができません。

そこで、UBoundを使うことで、Splitで分割されたデータの個数が変わっても、プログラムの変更をする必要がなくなります。

また、LBoundを使うことで、配列の添え字の「下限」を意識する必要性が少なくなります。

2次元配列の添え字の下限、上限を調べる

2次元配列の場合には、次のような書式で、配列の添え字の下限、上限を調べることができます。

書式

次のように、配列名の後に、添え字の下限・上限を知りたい「次元」を入れると、それぞれの次元の下限・上限を調べることができます。

LBound(配列名, 1)
あるいは
LBound(配列名, 2)
UBound(配列名,1)
あるいは
UBound(配列名,2)

具体例

セル範囲への読み込み、書き込みを高速にするで紹介したプログラムに変更を加えてみようと思います。

「A1~B3セル」の内容を「D1~E3セル」にコピーするときに、値を2倍にしたうえで転記してみます。

Sub RangeCopy3()
  Dim Data

  Data = Range("A1:B3").Value    ' A1~B3セルの内容をDataにコピー
                                 ' 自動的にDim Data(1 to 3,1 to 2)が実行された状態になる

  Dim Row
  Dim Column
  For Row = LBound(Data, 1) To UBound(Data, 1)      '1次元目のループ
    For Column = LBound(Data, 2) To UBound(Data, 2) '2次元目のループ
      Data(Row, Column) = Data(Row, Column) * 2     '内容を2倍する
    Next
  Next
  
  Range("D1:E3").Value = Data    ' D1~E3セルには、A1~B3セルの2倍の値が代入される

End Sub

For~Nextループの二重ループで、ループ変数の初期値、最終値にLBound、UBoundで得た値を使っています。

まとめ

配列を、使わなくても最低限のプログラムは組めます。

ただ、配列を使うことで、次のようなメリットがあります。

  • For~Next文が使えて、プログラムの重複が防げる
  • 処理の高速化ができる

VBAでのプログラミングに慣れてきたら、配列も使えるように練習してみてください。

次の記事はこちら↓

【初心者向け】エクセルVBAのRangeとCellsの使い分け方は?

おすすめ記事

エクセル基礎講座 「無料」動画マニュアル

「経理事務のためのエクセル基礎講座(初級編)」(動画マニュアル 総収録時間162分)を無料プレゼント中です!

このマニュアルで解説していることを一通り学べば、経理事務を行う上で最低限必要となる知識が得られます。

ご登録者の方には、合わせて、公認会計士が実体験を通して身に付けたエクセルを使う技をメールにてお伝えしていきます!

無料動画講座 登録フォーム

※ご登録頂いたメールアドレスに、エクセルを使いこなすための情報を配信するメールセミナー「エクセル倍速講座」も合わせて配信させていただきます。