文字列連結の「常識」を疑え:VBAで大量データを扱う際のパフォーマンス最適化
こんにちは。現場で「動けばいい」というコードから脱却し、エンジニアとしての品格あるコードを書きたいと考えているあなたへ。
今日は、VBAにおける「文字列連結」という、誰もが通る道でありながら、多くの人がパフォーマンスの沼にハマるポイントについてお話しします。
「セルを1万行回して、文字列を足し合わせる」……こんな処理、`&` 演算子だけで書いていませんか? そのコード、実はExcelにかなりの負荷をかけているかもしれません。
—
1. なぜ「&演算子」の多用が危険なのか
VBA初心者が最初に覚えるのが `str = str & “文字”` という書き方です。これ自体は間違っていませんが、「大量のループの中で」使うと話が変わります。
メモリの裏側で起きていること
VBAにおいて、文字列は「固定長」ではありません。`str = str & “A”` を実行するたびに、裏側では以下のことが起きています。
1. 現在の文字列の長さを確認する。
2. 「元の文字列 + 追加分」を格納できる新しいメモリ領域を確保する。
3. 古い文字列を新しい領域にコピーする。
4. 新しい文字を追加する。
5. 古いメモリ領域を破棄する。
これを1万回繰り返すとどうなるか。毎回メモリの確保とコピーが発生し、CPUとメモリリソースを無駄に食い潰しているのです。
—
2. 回避策:Join関数という「魔法」
大量の文字列を扱うとき、伝説のアーキテクトが推奨するのは 「配列(Array)に貯めてからJoinする」 という手法です。
Join関数は、配列内のすべての要素を一度の処理で結合します。メモリ確保の回数が最小限で済むため、処理速度は `&` を繰り返す手法と比較して、数倍〜数十倍速くなることも珍しくありません。
比較コード:どちらが速いか?
‘ 【非推奨】&演算子を繰り返す方法(メモリの断片化を招く)
Sub BadStringConcat()
Dim i As Long
Dim result As String
For i = 1 To 10000
result = result & “Data” & i & vbCrLf
Next i
Debug.Print result
End Sub
‘ 【推奨】配列+Join関数を使う方法(メモリ効率が極めて高い)
Sub GoodStringConcat()
Dim i As Long
Dim arr(1 To 10000) As String
‘ 1. まず配列に値を格納する
For i = 1 To 10000
arr(i) = “Data” & i
Next i
‘ 2. 最後にJoin関数で一気に結合する
Dim result As String
result = Join(arr, vbCrLf)
Debug.Print result
End Sub
—
3. 実務で「やってはいけない」エラーと注意点
Join関数を使う際に、よくある落とし穴をいくつか紹介します。
- 配列のサイズ固定問題:
`Dim arr(1 To 10000)` と決め打つと、データが10001件あるとエラーになります。実務では `ReDim Preserve` を使うか、あらかじめデータの行数を `Range(“A” & Rows.Count).End(xlUp).Row` で取得してから配列を定義するのがプロの流儀です。
- Variant型の罠:
`Dim arr() As Variant` として配列を扱うと、メモリ効率が落ちます。文字列だけで構成されるなら、極力 `String` 型の配列を使うのがベストです。
—
4. まとめ:今日から使える「文字列操作」の極意
ここまでのポイントをまとめます。
1. 少量の連結なら `&` でOK: 10回や20回の連結で `Join` を使う必要はありません。可読性重視でいきましょう。
2. 数千件を超えるなら `Join` 一択: ループ内での `&` は、コードが長くなればなるほど、あなたのPCを確実に鈍化させます。
3. 「メモリの再確保」を意識する: コードを書くとき、「今、コンピュータに余計な引っ越し作業をさせていないか?」と自問自答してみてください。
ここをクリアすれば、あなたのVBAスキルは「初心者」の枠を確実に超えています。マクロの記録で生成されたゴミコードを整理し、洗練されたロジックを書けるエンジニアへと進化していきましょう。
もしコードの書き方で迷ったら、いつでも聞きに来てください。あなたのコードが、より速く、より美しくなるよう導きますから。
それでは、良いコーディングライフを!
