VBA技術解説
配列の使い方について

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
公開日:2013年5月以前 最終更新日:2019-11-29

配列の使い方について


配列に関する記事は多数掲載していますが、今回は配列についての基礎知識をまとめました。
配列に関する基本的事項のみを解説しています。


配列とは

まずシートのセルを考えて下さい。
縦1列だけを取り出した場合は、1次元の配列です。
縦横の複数行列を取り出した場合は、2次元の配列です。
このようなデータを変数で扱うのが、配列になります。

2次元以上の次元の配列を、多次元配列とも言います。

1次元の配列

Dim 配列名(10) As Variant

これで、11個の要素を持つ1次元の配列になります。
あれっ、10個じゃないの?となりますが、
10個で正しいのです。
配列は、0~10になるのです、ですから11個になります。
データ型は、自由に指定可能です。

1次元配列の使用方法
配列名(インデックス)
インデックスとは、つまりは何番目かという事です。
添え字とも言います。
配列の要素に振られた番号です。
通常は、0,1,2と振られています。
また、
Dim 配列名(5 To 10) As Variant
のような記述もあります。
これは、5番目から10番目のみ使用するといった感じです。
さすがに、下限として5を指定することはないのですが、
1から開始することは頻繁に使用されます。
Dim 配列名(1 To 10) As Variant
後述の注意でもあるように、使用すると便利な場合が多々あります。

2次元の配列

Dim 配列名(10, 5) As Variant

これで、縦11個、横6個の要素を持つ2次元の配列になります。
縦横と表現しましたが、イメージしやすいように言ったまでで、
10が1次元目、5が2次元目になります。

2次元配列の使用方法
配列名(1次元インデックス上限, 2次元インデックス上限)
Dim 配列名(10, 5)
これは、つまり、
配列名(0, 0)~配列名(0, 5)

配列名(10, 0)~配列名(10, 5)
このようになります。

3次元以上の配列

3次元以上についても同様に扱えますが、使用はお勧めしません。
エクセルVBAにおいて、感覚的に直ぐに理解できるのは、2次元までだと思います。

動的配列

上記のように、最初から次元数、要素数を定義する配列の事を、
以下で説明する動的配列に対し、静的配列と呼びます。

プログラムを作成していると、配列の要素数が固定で決められない場合が多くなります。
実行時に、シートの内容によって、要素数を決定したくなります。
このような場合に、使用するのが、動的配列です。
プログラムの中で、次元数、要素数を決定したり、途中で要素数の変更をします。

動的配列

Dim 配列名() As Variant
このように、変数宣言時は配列であることだけを定義します。

1次元配列の要素数の変更
ReDim 配列名(10)
これで、1次元10の配列になります。
これは何回でも、変更(ReDim)可能です。
ただし、それまでのデータは全てなくなります。

データが消えてしまっては都合が悪い場合があります。
それまでのデータをそのままにして、要素数のみ変更したい場合は、
ReDim Preserve 配列名(10)
このようにPreserveを指定することで、データが残り要素数のみ変更できます。

ただし、Preserveを指定した場合は、
添字(インデックス)の下限は変更できません、変更できるのは上限だけです。
ReDim 配列名(0 To 10)
これを
ReDim Preserve 配列名(1 To 10)
これはエラーとなります。。

2次元配列の次元、要素数の指定
ReDim 配列名(5, 10)
これで、2次元配列になり、1次元目が5、2次元目が10の配列になります。
これも何回でも、変更(ReDim)可能です。

1次元配列同様に、データを残す場合は、
Preserve
を指定します。
ただし、Preserveを指定した場合は、
変更できるのは、最下位の次元のみです。
上で言えば、2次元目の10のみ変更可能です。
つまり、
ReDim 配列名(5, 10)
ReDim Preserve 配列名(6, 10) '×
これはエラーとなります。
できるのは、最下位の次元のみになります。
ReDim 配列名(5, 10)
ReDim Preserve 配列名(5, 11) '〇

動的配列の要素数の取得

動的配列を使っていると、VBA実行の中で今この配列の要素数がいくつなのかを知る必要が出てきます。
取得方法は、

要素数の最大値:UBound(配列名[,次元数])
要素数の最小値:LBound(配列名[,次元数])
※次元数を省略した場合は1次元目になります。

例えば、
ReDim 配列名(5, 10)
この場合、
UBound(配列名) → 5が返されます。
UBound(配列名, 1) → 5が返されます。
UBound(配列名, 2) → 10が返されます。

配列使用時の注意

普通に定義した配列、
ReDim 配列名(5, 10)
これは、インデックスが0から始まります。
つまり、0~5、0~10になります。
しかし、人間の感覚では0番目というのはいかにも使いづらく感じます。
そこで、0番目を無視して1番目から使っているVBAを見かけることがあります。
配列名(0, 〇)、配列名(〇, 0)
これらをVBA内では意図的に使用せず、
配列としては0から使えても、実際のVBA記述は1からしか使用しないということです。
これはこれで問題ありませんし、プログラムも分かりやすい場合もあります。
ただし、シートのセル範囲とデータをやりとりする場合は注意が必要です。

ReDim 配列名(5, 10)
この配列に、配列名(1, 1)~配列名(5, 10)の範囲にデータを入れ、
シートに戻す場合、
Range("A1:J5").Value = 配列名
としてしまいそうです。
しかし、これでは、配列名(0,0)~配列名(4,9)の範囲しか入りません。
もちろん、配列を2重ループで1つづつ入れれば良いのでしょうが、
それでは、処理時間がかかり過ぎます。
数千、数万行のデータでは、現実的には厳しくなります。

このような場合は、やはりインデックスの0から使用するか、
ReDim 配列名(1 To 5, 1 To 10)
このように、最初から下限値を指定する必要があります。
これなら全く問題はありません。
また、Option Base 1で変更するのは、誤解のもとになるのでお勧めしません。

また、
Dim 配列名() As Variant
これに対し、
配列名 = Range("A1:J5").Value
とした場合は、配列は、(1 To 5, 1 To 10)となりますので注意して下さい。

0番目をどうするかは、意見の分かれる所でしょうし、まあ好みかもしれません。
私は、ほとんどの場合、LBound~UBoundで処理するように記述しています。
そのようにしておけば、どちらの場合でもプログラムに変更はありません。

ここまで書きすすめると、やはり、
初心者の方は、(1 To 5, 1 To 10)のように定義し、1から使用する。
これが、最も分かりやすく間違いが無いだろうと思います。

追加の説明として、
Split関数(文字列を区切り文字で分割し配列にする)や、
コンボボックスのListの取得等は、Option Base 1に関わらず必ず0からになりますので、
0スタートにも慣れておく必要はあります。



同じテーマ「マクロVBA技術解説」の記事

配列の使い方について
VBAの配列まとめ(静的配列、動的配列)

・配列の概念 ・静的配列 ・動的配列 ・セル範囲⇔配列の基本 ・配列で必要となるVBA関数とステートメント ・配列に関する記事の一覧
最終行の判定、Rangeオブジェクトと配列、高速化の為に
最終行の判定 エクセル顧客管理の記事からのスピンオフ記事になります。以前に、モジュール「顧客一覧へ登録」において、.Cells.SpecialCells(xlLastCell).End(xlUp).Row と Cells(Rows.Count,1).End(xlUp).).Row を紹介しましたが、
記述による処理速度の違い
・1.変数の型指定 ・2.罫線の引き方 ・3.行高の変更 ・4.配列を使用した処理 ・処理速度を早くする為には
速度比較決定版【Range,Cells,Do,For,ForEach】
何度も言っているのですが、RangeとCellsでどっちが早いか、とか、DoとForとFor Eachでどれが早いか とか、そもそも、その議論がナンセンスなんです。以下のコードと結果を見て、各自で判断して下さい。巷の議論が、いかに無意味で、実は良く解っていないのだと言う事を、理解してもらいたい。
エクセルVBAのパフォーマンス・処理速度に関するレポート
ExcelのマクロVBAは遅い・重いと良く言われることが多いようですが、マクロVBAが遅い・重いのではなく、その書かれたVBAコードが遅いのです。正しい高速化・速度対策をしたコードなら、それほど遅くはありません。むしろ、巨大なスプレッドシートを扱っている事を考えれば、驚異的なパフォーマンスとも言えるのです。
VBAのFindメソッドの使い方には注意が必要です
・1.処理速度が遅い ・2.指定オプションがシート操作とリンクしている ・「値」で検索した場合は、表示形式に依存した検索になる ・最後に
マクロVBAの高速化・速度対策の具体的手順と検証
マクロVBAが遅い・重いという相談が非常に多いので、遅い・重いマクロVBAを高速化・速度対策する場合の具体的な手順をここに解説・検証します。マクロVBAの速度に関する記事は既にいくつか書いています。特に、以下はぜひお読みください。
動的2次元配列の次元を入れ替えてシートへ出力(Transpose)
動的配列を使い様々な処理をした後にシートへ出力しようとしたとき、縦横が違っている為そのまま出力できません、そもそも、動的配列の要素数をRedimで変更できるのは、最下位の次元のみになります。2次元配列の場合、ReDimmyArray(2,10) ReDimmyArray(2,11) これはOKですが、
大量データで処理時間がかかる関数の対処方法(SumIf)
・大量データで処理時間がかかるサンプルデータ ・普通にマクロVBAコ-ドを書いた場合 ・指定範囲を絞ってみる ・配列を使って書いてみる ・アルゴリズムを考えてみる ・Dictionary(連想配列)を使う ・大量データで処理時間がかかる関数の対処方法の最後に
大量データにおける処理方法の速度王決定戦
VBAで自動化したが、大量データ処理に時間がかかってしまう… そんな悩みが非常に多いようです、そこで、各種処理方法の速度比較を行い、どの処理方法が最も速いかを検証します。つまり、処理方法の速度王決定戦です。検証する題材としては、最も一般的な集計で行います。


新着記事NEW ・・・新着記事一覧を見る

ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
累計を求める数式あれこれ|エクセル関数応用(2024-01-22)
複数の文字列を検索して置換するSUBSTITUTE|エクセル入門(2024-01-03)
いくつかの数式の計算中にリソース不足になりました。|エクセル雑感(2023-12-28)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.RangeとCellsの使い方|VBA入門
4.ひらがな⇔カタカナの変換|エクセル基本操作
5.繰り返し処理(For Next)|VBA入門
6.変数宣言のDimとデータ型|VBA入門
7.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
8.並べ替え(Sort)|VBA入門
9.セルのクリア(Clear,ClearContents)|VBA入門
10.Findメソッド(Find,FindNext,FindPrevious)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。


このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ