VBAを用いて大量のデータを処理する際、配列の活用は欠かせない要素です。変数を個別に用意する手間が省けるため、コードの記述量を大幅に削減する効果が期待できます。
この記事では、固定長配列(静的配列)と動的配列の初期化方法に加え、Array関数やForループを使った値の代入方法、Eraseステートメントによる要素のリセット手順まで、VBAの配列操作に必要な知識を一通り解説する記事です。
配列を正しく動作させるには、適切な初期化の手順を踏む必要があります。用途に応じて使い分ける2つの宣言方法を確認しましょう。
VBAで配列を初期化する基本的な方法
VBAの配列には、作成時に要素数を決める静的なタイプと、後から変更できる動的なタイプの2種類が存在します。プログラムの設計に合わせて選択するのが一般的です。
それぞれの初期化における特徴を、以下の表に整理しました。
| 項目 | 静的配列 | 動的配列 |
|---|---|---|
| 要素数の決定 | 宣言時に固定 | 実行時に変更可能 |
| 主なステートメント | Dim | ReDim |
| サイズ変更の可否 | 不可(宣言後は固定) | ReDimで再定義可能 |
ReDimによる再定義は、既存の配列領域を解放してから新しいサイズを確保する処理です。実行回数が多い処理では負荷につながる場合があるため、要素数や再定義の頻度をあらかじめ検討しておくと安心です。
Dimステートメントで静的配列を定義する
静的配列は、扱うデータの個数があらかじめ確定している場合に利用します。宣言時に括弧内へ要素数を記述し、メモリ領域を確保する仕組みです。
具体的な宣言方法と代入の書き方は、以下のコードの通りです。
Dim numbers(4) As Long
numbers(0) = 10
numbers(4) = 50
要素の番号は基本的に0から始まります。例えば「(4)」と指定した場合は、0番から4番までの合計5つの要素が用意される点に注意しましょう。
ただし、この既定の下限はOption Baseステートメントの指定によって変わるため、0始まりを確実に保証したい場合はDim numbers(0 To 4) As Longのように下限を明示して宣言すると安全です。
下限を明示する書き方には、以下のようなメリットがあります。
- メモリの管理が容易で予期せぬエラーを防げる
- コードの記述がシンプルになり読みやすい
- インデックスの範囲が固定されるため安全性が高い
宣言と同時にデータ型を明示するのが定石です。これにより、配列内に格納されるデータの種類が統一され、デバッグ作業の効率が高まるメリットが得られます。
ReDimステートメントで動的配列を再定義する
取り扱うデータの件数が実行中に変動するケースでは、動的配列を選択します。最初は括弧内を空にして宣言を行い、具体的な数値が決まった段階でサイズを割り当てる手順です。
基本的な宣言とサイズ変更の書き方は、以下のコードの通りです。
Dim numbers() As Long
ReDim numbers(2)
numbers(0) = 1
numbers(1) = 2
numbers(2) = 3
サイズの変更が必要になった際は、再度命令を出すことで領域を拡張します。ただし、通常の再定義では格納済みの値が消去される仕様です。
Preserveキーワードを併用すると、既存のデータを保持したまま要素数を増やせます。具体的な書き方は、以下のコードの通りです。
ReDim Preserve numbers(4)
numbers(3) = 4
numbers(4) = 5
ただし、Preserveを使う際に変更できるのは配列の最後の次元の上限のみという制約があります。多次元配列で先頭側の次元やサイズを変更したい場合は、Preserveを使わずに配列を作り直すか、別の変数へ値を移し替える、以下の手順が必要です。
- Dim変数の括弧を空にして動的配列を宣言
- プログラムの途中でデータ件数を算出
- ReDimを用いて必要なサイズを割り当て
頻繁にサイズを変更すると処理が重くなる傾向にあります。そのため、あらかじめ余裕を持った数を設定するか、変更回数を最小限に抑える工夫が有効です。
これは、頻繁な再定義がメモリ確保のたびに発生し、プログラム全体のパフォーマンスを低下させる要因になるためです。
VBAの配列要素を一括でクリアする手順
配列内のデータを整理する際は、個別に値を代入するよりも専用の命令を使うほうが、コードの記述量を抑えられて効率的だといえます。
Eraseステートメントで値をリセットする
VBAには配列全体を一度に初期化するための専用コマンドが用意されています。これを使用すると、要素数が多い場合でも一瞬で処理が完了するのがメリットです。
具体的な書き方は、以下のコードの通りです。
Dim numbers(4) As Long
numbers(0) = 10
Erase numbers
Eraseステートメントを実行すると、以下のような挙動を示します。
- 固定長配列の場合は各要素の値が初期値(数値型なら0、可変長文字列なら長さ0の文字列)に戻ります
- 動的配列の場合はメモリ領域そのものが解放される仕組みです
- 個別のループ処理が不要なため、コードの記述を簡略化できます
ただし、String * 10のように長さを指定した固定長文字列の要素は、空文字列になるのではなく指定した長さを保ったままヌル文字でリセットされる仕様です。オブジェクト型など他のデータ型の初期値も、代表的な例として押さえておくと想定外の挙動を防げます。
大量のデータを扱うマクロでは、処理の節目でこの命令を使いデータをリセットするのが一般的です。メモリの効率的な利用にもつながります。
配列変数のメモリを完全に解放する
プログラムの実行速度や安定性を保つためには、不要になった配列のメモリを適切に管理することが求められます。配列の種類によってクリア後の状態が異なる点に注意が必要です。
| 配列の種類 | Erase実行後の挙動 | 再利用時の注意点 |
|---|---|---|
| 固定長配列 | 要素の値のみが初期化される | 要素数は変わらずそのまま維持されます。 |
| 動的配列 | メモリ領域が完全に解放される | 再度使用する前にReDimでの再定義が必須です。 |
動的配列をクリアした後は、配列に割り当てられていたメモリ領域が解放され、要素へアクセスできない未割り当ての状態です。そのため、再利用時には必ずReDimでサイズを再指定する必要があります。
解放後に再利用する場合の書き方は、以下のコードの通りです。
Dim numbers() As Long
ReDim numbers(2)
numbers(0) = 1
Erase numbers
ReDim numbers(4)
numbers(0) = 100
このように配列の状態を正しく把握することが、エラーのないスムーズなプログラム開発の土台となります。適切なタイミングでのリセットを習慣化しましょう。
VBAで特定の値を代入して配列を初期化する
配列を作成した直後は、要素の中に具体的な値が入っていない状態です。特定の値をあらかじめ準備しておく初期化作業には、主に2つのアプローチが存在します。
用途に応じて手法を使い分けるのが、スムーズなプログラム作成のコツです。それぞれの特徴を整理した比較表を確認しましょう。
| 初期化の手法 | 適したケース | メリット |
|---|---|---|
| Array関数 | 項目名や定数など、決まった値を少数入れるとき | 記述が短く直感的に値を指定できる |
| Forループ | 連番や規則的なデータ、大量の要素を扱うとき | 柔軟な代入処理を自動化できる |
扱うデータの性質や件数に合わせてどちらかを選べば、無駄のない初期化処理を実装できます。以降のH3で、それぞれの具体的な書き方を確認しましょう。
Array関数を使って要素を生成する
Array関数は、引数に指定した値を順番に格納した配列を生成する仕組みです。Variant型の変数に対して、複数のデータを一括で割り当てる際に重宝します。
具体的な書き方は、以下のコードの通りです。
Dim fruits As Variant
fruits = Array("apple", "orange", "banana")
Debug.Print fruits(0)
利用時の主な特徴は以下の通りです。
- カンマ区切りで値を並べるだけで代入が完了する
- 添字(インデックス)の最小値はOption Baseステートメントの指定によって変わる
- 文字列や数値など、異なる種類のデータを混在させる運用も可能
Option Baseを指定していない場合、添字は0から始まりますが、モジュールにOption Base 1が記述されているとArray関数の下限も1に変わります。常に0始まりを保証したい場合は、VBA.Arrayを使用するか、LBound関数で実際の下限を確認してから処理する方法が安全です。
コードの行数を抑えつつ、少ない手順で決まった初期値をまとめてセットしたい場面に適した選択肢だといえるでしょう。
Forループで各要素に初期値を格納する
決まった規則に基づいて値を代入したい場合は、Forループによる繰り返し処理が力を発揮します。インデックス番号を変数として扱い、各要素へ順番にアクセスする手法です。
具体的な書き方は、以下のコードの通りです。
Dim numbers(4) As Long
Dim i As Long
For i = LBound(numbers) To UBound(numbers)
numbers(i) = i * 10
Next i
この方法には次のような利点があります。
- 1から100までの連番など、規則的な数値を一瞬で格納できる
- 条件分岐と組み合わせて、特定の要素のみ値を変更する制御が容易
- 動的配列のサイズが実行時に決まる場合でも柔軟に対応できる
一括処理による効率化が、この手法の最大の魅力です。ループの範囲をLBoundとUBoundで取得しておけば、Option Baseの設定に関わらず代入漏れを防ぐ構造を構築できます。
VBAの配列初期化に関するよくある質問
配列をNothingで初期化することは可能ですか?
VBAの配列はオブジェクト変数と異なり、Nothingを代入して初期化することはできません。参照を破棄するNothingの代入は、クラスインスタンスなどオブジェクト型変数専用の操作です。
配列のメモリ領域そのものを完全に解放したい場合は、Nothingではなく代わりにEraseステートメントを使用してください。
多次元配列を一度に初期化する方法はありますか?
宣言済みの多次元配列を一括で埋める標準機能はVBAにありません。基本的には、ネストしたForループを使って各要素へ値を代入する必要があります。
1次元の範囲で足りる場合はArray関数でも代用できますが、多次元配列を直接生成する機能ではない点に注意してください。
動的配列の要素数だけをリセットしたい場合はどうすればよいですか?
動的配列の要素数を維持または変更しながら中身をすべて空にするには、Preserveキーワードを付けずにReDimを実行してください。この操作により、配列内のすべての値がデータ型に応じた初期値にリセットされます。
ITやプログラミングに関するコラム
【Python】FastAPIで料金プラン見積もりシミュレーターを作ってみた
【Python】pandasとmatplotlibで在庫データのABC分析と構成比を可視化してみた
【Python】Flaskで社内FAQをカテゴリ検索できるWebアプリを作ってみた
【Python】argparseでJSON整形・構文検証・キー検索CLIを試してみた
【Python】NumPyとmatplotlibでモンテカルロ法による円周率推定と収束過程の可視化を試してみた
【Python】Playwrightでスクレイピングを試してみた
【CSS】notで複数の件を除外する方法
【Git】remote設定を変更する方法
【VBA】コメントアウトを設定する方法
x86とx64の違いを分かりやすく解説
ITやプログラミングに関するニュース
VercelがAI GatewayにSeedream 5.0 Proを追加、AI SDKのモデル指定で画像生成と編集が可能に
AWSがAmazon LocationのPlaces APIを強化、住所表記の指定と移動手段別の検索が可能に
VercelがトレースにTree・Waterfallビューを追加、ログ画面で処理の階層と所要時間を確認可能に
Googleがエージェント評価の再考を提唱、難易度を情報量で測るDiscovery Benchを解説
Google CloudがCloud Runサンドボックスを公開プレビューで提供、サービスヘルスは一般提供に
Google Cloud EMEAが英国金融の重要第三者に指定、イングランド銀行・PRA・FCAの直接監督下に
AWS DMS Schema ConversionがSQL Serverのオフライン変換に対応、ソースDBへ接続せずスキーマを変換可能に
EC2 G7インスタンスが米国東部(バージニア北部)で利用可能に、G6比でAI推論性能が最大4.6倍
SageMaker HyperPodが継続プロビジョニングでのAMIベース構成に対応、S3のスクリプト管理なしでSlurmクラスターを作成可能に
AWSがEMR on EKSでSparkトラブルシューティングエージェントに対応、失敗ジョブの原因分析を自然言語で依頼可能に
