配列のRedimとPreserve:メモリを支配し、VBAを「真の武器」に変える極意
こんにちは。現場で泥臭い自動化を積み重ねてきたエンジニアとして、今日は君たちに「メモリを制する者は、VBAを制す」という話をしよう。
「マクロの記録」から一歩踏み出し、大量のデータを扱うようになると、誰もが一度は「データが何件来るか分からない!」という壁にぶつかる。ここで`Cells(i, 1).Value`をループで何度も叩くような非効率な書き方をしていては、プロとは呼べない。
今回は、VBAにおける「動的配列の管理術」を伝授する。これができれば、君のコードは劇的に速く、美しくなる。
—
1. なぜ「動的配列」なのか?
VBAでデータを処理する際、最も避けるべきは「セルへの頻繁なアクセス」だ。セルは重い。Excelというアプリケーション全体を揺さぶるからだ。
だからこそ、データを一旦メモリ上の「配列」という箱に引き揚げて処理する。しかし、データ量が不明な時、あらかじめ巨大な箱を用意するのはメモリの無駄だ。そこで登場するのが `ReDim` と `Preserve` である。
—
2. 配列の「拡張」と「保持」のメカニズム
言葉で覚えるより、このイメージを持ってほしい。
- `ReDim`: 配列のサイズを再定義する命令。ただし、そのまま使うと中身が全消去される。
- `Preserve`: 「今のデータを残したまま」サイズ変更を許可する魔法のキーワード。
実装のテンプレート
まずは、この基本形を叩き込んでほしい。
Sub DynamicArrayExample()
Dim myData() As String ‘ サイズ未定の動的配列を宣言
Dim i As Long
Dim count As Long
count = 0
‘ データを取得するループを想定
For i = 1 To 10
‘ 3の倍数の時だけ配列に格納したい、という状況を想定
If i Mod 3 = 0 Then
‘ 配列を拡張しつつ、既存のデータは保持する
ReDim Preserve myData(count)
‘ データを格納
myData(count) = “データ_” & i
‘ カウンタをインクリメント
count = count + 1
End If
Next i
‘ 結果を出力
MsgBox “格納されたデータ数: ” & UBound(myData) + 1
End Sub
—
3. 注意点:ここが「初心者の墓場」だ
この技術を使う上で、必ず知っておかなければならない「罠」が2つある。
① 「多次元配列」の制限
`Preserve` が使えるのは、「最後の次元」だけだ。
例えば `myData(10, 10)` と宣言した場合、`ReDim Preserve myData(10, 20)` はできるが、`ReDim Preserve myData(20, 10)` はエラーになる。
実務で複雑なデータを扱う際は、配列の構造を「行を動的に増やす」形に設計するのが鉄則だ。
② パフォーマンスの限界
`ReDim Preserve` は、実は裏側で「新しい巨大なメモリ領域を確保し、古いデータをコピーし、古い領域を破棄する」という重い処理を行っている。
数千件程度なら問題ないが、10万件を超えるようなデータ処理で、ループのたびに `ReDim Preserve` を呼ぶのは避けるべきだ。
【解決策】
あらかじめ「最大件数」で配列を確保しておき、最後に不要な分を削るか、あるいは「1000件ずつ拡張する」といったバッファ戦略をとるのが、プロのエンジニアの流儀だ。
—
4. 今日から君がやるべきこと
まずは、今書いているコードで「セルを一つずつ読み書きしているループ」を探してみてほしい。
1. データを配列に格納する。
2. `ReDim Preserve` で必要分だけ箱を作る。
3. メモリ上で高速に計算し、最後に一気にセルへ書き戻す。
この3ステップを意識するだけで、処理速度は10倍、いや100倍変わることもある。
—
まとめ
- `ReDim` は箱の再定義。
- `Preserve` は中身を捨てないための守護者。
- メモリ効率を意識することは、ユーザーの時間を節約することに直結する。
VBAは決して古い言語ではない。メモリの呼吸を感じ、配列を自在に操れるようになれば、君はどんな複雑な業務要件も、スマートなコードで解決できるはずだ。
ここをクリアした君なら、次は「コレクション」や「辞書(Scripting.Dictionary)」を使ったより高度なデータ管理の世界もすぐそこだ。一歩ずつ、確実に力をつけていこう。応援しているよ。
