こんにちは!Excel VBAのスキルを次のステージへと引き上げる、あなたの専属メンターです。
マクロの記録から抜け出し、いざ自分でコードを書こうと思ったとき、多くの人が直面する最初の壁が「大量のデータを高速に処理する方法」です。
セルを1つずつ「ポチポチ」と読み書きしていませんか? それだと、データが数千行になった途端に画面がフリーズしたような状態になってしまいますよね。
今回は、VBAの処理速度を劇的に向上させるための必須テクニック、「配列の動的再定義(ReDim)コストを最小化するバッファ戦略」を徹底解説します。
ここをクリアすれば、あなたのVBAコードは「遅いオモチャ」から「プロの業務用ツール」へと生まれ変わりますよ。さあ、一緒に本質を学んでいきましょう!
—
1. なぜループ内の `ReDim` は「悪者」なのか?
VBAで「いくつデータが入るか分からないから、とりあえず小さく作って、足りなくなったら大きくしよう」と考えたとき、初心者がやりがちなのが次のようなコードです。
‘ 【やってはいけないアンチパターン】
Dim i As Long, data() As String
For i = 1 to 10000
ReDim Preserve data(i) ‘ ⚠️ループのたびにサイズを変更!
data(i) = “データ” & i
Next i
一見、何の問題もなさそうに見えますよね。しかし、この `ReDim Preserve` をループの中で毎回実行するのは、VBAにおいて最もやってはいけないタブーの一つです。
メモリの引越し劇(裏側の挙動を知る)
VBAの配列は、メモリ上に「連続した部屋」として確保されます。
1. `ReDim Preserve data(1)` と書くと、メモリ上に1個分の部屋が用意されます。
2. 次の周で `ReDim Preserve data(2)` と書くと、VBAは「今までのデータを保持したまま、隣にもう1部屋増やそう」とします。
3. しかし、隣の部屋がすでに別のデータで埋まっている場合、VBAは「もっと広い別の場所に引っ越し、古いデータを全部コピーして、新しい部屋を確保する」という重労働を強いられます。
これを1万回繰り返すということは、1万回もメモリの引っ越し作業(データのコピー)を行っていることになります。そりゃあパソコンもフリーズしかけますよね。
—
2. 解決策:バッファ戦略(倍々ゲーム方式)とは?
この「毎回の引っ越し」を防ぐための天才的なアプローチが、「バッファ戦略(余裕を持った領域確保)」です。
イメージとしては、一人暮らしなのに毎回引っ越し業者を呼ぶのではなく、「最初は大きめのシェアハウス(バッファ)を借りておき、部屋がいっぱいになりそうになったら、一気に2倍の広さの物件に引っ越す」という作戦です。
効率的なアルゴリズムの考え方
- 最初に、ある程度まとまった大きめのサイズ(あるいは一定の初期サイズ)で配列を確保します。
- ループを回し、配列の限界に達したときだけ、サイズを「2倍」に拡張します。
- 最終的に、実際に使用したデータ数(有効な要素数)のサイズに、最後に一度だけ縮小(ReDim)します。
これによって、1万回の引っ越しが、わずか14回程度に激減します。パフォーマンスの差は歴然です。
—
3. 実践!バッファ戦略を実装した最強のVBAコード
それでは、実際の業務でそのままコピペして使える、洗練されたコードを見てみましょう。ここでは、シートのデータを効率的に配列に読み込むシーンを想定しています。
Sub BufferStrategySample()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, “A”).End(xlUp).Row
If lastRow < 1 Then Exit Sub ' --- バッファ戦略の核心部 --- Dim capacity As Long capacity = 10 ' 初期バッファサイズ(適宜調整) Dim count As Long count = 0 実際に格納したデータの数 Dim buffer() As String ReDim buffer(1 To capacity) ' 最初から少し大きめに確保! Dim i As Long For i = 1 To lastRow ' 条件に合うデータだけを抽出するシミュレーション If ws.Cells(i, 1).Value <> “” Then
count = count + 1
‘ 【重要】バッファ(容量)が足りなくなったら、一気に2倍に拡張!
If count > capacity Then
capacity = capacity 2 ‘ 容量を倍増
ReDim Preserve buffer(1 To capacity)
End If
‘ データを格納
buffer(count) = ws.Cells(i, 1).Value
End If
Next i
‘ 最後に、実際に使ったデータ数(count)のサイズにピタリと合わせる
If count > 0 Then
ReDim Preserve buffer(1 To count)
Else
MsgBox “有効なデータはありませんでした。”, vbExclamation
Exit Sub
End If
‘ — 結果の確認(例としてイミディエイトウィンドウに出力) —
Debug.Print “— 処理完了 (有効データ数: ” & count & “件) —”
For i = 1 To count
‘ ここで処理を行う
‘ Debug.Print buffer(i)
Next i
MsgBox “処理が高速に完了しました! 抽出件数: ” & count & “件”, vbInformation
End Sub
コードの解説ポイント
1. `capacity`(容量)と `count`(実数)の分離
- 「今、配列が何個分の箱を持っているか(`capacity`)」と「実際に何個のデータを入れたか(`count`)」を明確に区別するのがプロの技です。
2. `capacity = capacity 2`
- 足りなくなるたびに「+1」ずつ拡張するのではなく、倍々に増やすことで、配列が大きくなればなるほど引っ越しの回数が激減します(数学的な等比数列の恩恵を受けます)。
3. 最後のトリミング
- 最後に `ReDim Preserve buffer(1 To count)` とすることで、余分な空き部屋をキレイに切り捨て、メモリを最適化して次の処理にバトンタッチできます。
—
4. 陥りやすいエラーと注意点
初心者がこのバッファ戦略を実装するときに、よくハマる罠がいくつかあります。
- 罠1:1回目の拡張で `capacity 0` になるミス
- 初期値 `capacity` をうっかり `0` にしてしまうと、`0 2 = 0` のままで永遠に配列が拡張できず、エラーになります。初期値は必ず `1` 以上(実務では `10` や `100` など)に設定しましょう。
- 罠2:1次元配列以外への適用
- `ReDim Preserve` は、多次元配列の「一番最後の次元(列方向)」しか拡張できないというVBAの厳格な仕様があります。そのため、データを蓄積するバッファ戦略は、基本的に「1次元配列」で行い、必要に応じて最後に2次元に変換するのが鉄則です。
—
まとめ
いかがでしたでしょうか?
今回は、配列の動的再定義(ReDim)コストを最小化する「バッファ戦略」について解説しました。
- ループ内での毎回の `ReDim Preserve` はメモリの引っ越しを頻発させ、処理を極端に遅くする。
- 初期バッファを確保し、足りなくなったら「倍々(2倍)」で拡張する。
- 最後に実際のデータ数でトリミングする。
たったこれだけのアルゴリズムの工夫で、あなたの書くマクロは見違えるほどの爆速に生まれ変わります。
ここをクリアすれば、Excel VBAのデータ構造の扱いはもうバッチリです! ぜひ次の開発現場からこの「バッファ戦略」を取り入れて、周囲をあっと言わせる高速なプログラムを作ってみてくださいね。応援しています!
