こんにちは!Excel VBAの自動化の世界へようこそ。
マクロの記録から一歩踏み出し、「自分で動くプログラムを書きたい!」と思っているあなたへ、今日はとても大切で、かつプログラミングの本質に迫るテーマをお届けします。
テーマは「文字列連結の最適化」です。
「文字列をつなぐだけなら、`&` 演算子を使えばいいんじゃないの?」
そう思った方、鋭いですね!もちろん普段のちょっとした処理なら `&` で十分です。しかし、数千行、数万行といった「大量のデータ」をループ処理で結合する時、その書き方のままだと…Excelが急に重くなったり、最悪の場合はフリーズしてしまう原因になります。
今回は、なぜ大量の文字列結合で処理が重くなるのかという「メモリの裏側」の仕組みから、それを華麗に解決する `Join` 関数のテクニックまで、優しく丁寧にお伝えしますね。ここをクリアすれば、あなたのVBAスキルは一段とプロに近づきますよ!
—
1. なぜ「`&` 演算子」でのループ結合は重くなるのか?
まずは、私たちが普段やりがちな「NGパターン」を見てみましょう。
例えば、セルに入っている1万行のデータを、ひとつに繋げたいとします。
やりがちなコード(非効率な例)
Sub BadStringJoin()
Dim i As Long
Dim result As String
result = “”
‘ 1万回のループで文字列を & で繋ぎ続ける
For i = 1 to 10000
result = result & Cells(i, 1).Value & vbCrLf
Next i
MsgBox “完了しました!”
End Sub
このコード、動かしてみると後半になるにつれて、露骨に処理が遅くなるのが体感できるはずです。一体、裏側で何が起きているのでしょうか?
メモリの気持ちになって考えてみよう
VBAの `String` 型(文字列)は、メモリ上に「部屋」を確保してデータを置いています。
1. 1回目:1文字分の部屋を確保する。
2. 2回目:今までの文字 + 新しい文字 の「新しい、より広い部屋」を別の場所に新しく用意し、古いデータをコピーして、古い部屋を捨てる。
3. 3回目:さらに広い部屋を用意し、またコピーして、古い部屋を捨てる。
……これを1万回繰り返します。
想像してみてください。毎回引っ越し業者を呼んで、家財道具一式をより大きな家に運び出す作業を1万回やっているようなものです。そりゃあパソコンも疲れてしまいますよね。これが、`&` 演算子をループ内で使うときの最大の弱点(メモリの再割り当てコスト)です。
—
2. 救世主登場!配列と `Join` 関数による爆速テクニック
では、どうすればいいのでしょうか?
答えは簡単です。「最初から大きなダンボール箱(配列)に荷物をポイポイと入れておき、最後に一気にガムテープで留める(Joinする)」のです。
VBAには、複数の文字列をひとまとめにする `Join` 関数 が用意されています。これを使った効率的なコードがこちらです。
最適化されたコード(効率的な例)
Sub GoodStringJoin()
Dim i As Long
Dim dataList() As String ‘ 荷物を入れる配列を宣言
Dim result As String
‘ あらかじめ1万個分の「部屋(要素)」を確保しておく
ReDim dataList(1 To 10000)
‘ 配列にデータを格納していく(ここはメモリ的にお手軽)
For i = 1 To 10000
dataList(i) = Cells(i, 1).Value
Next i
‘ 【重要】Join関数で一気に結合する!
‘ 第1引数に配列、第2引数に区切り文字を指定します
result = Join(dataList, vbCrLf)
MsgBox “爆速で完了しました!”
End Sub
このコードが速い理由
このやり方では、メモリの確保(`ReDim`)は最初に1回行うだけです。あとは用意された棚(配列)にポチポチとデータをはめていくだけなので、パソコンへの負担が圧倒的に少ないのです。
そして最後の `Join` 関数が一瞬で全ての文字列を結合してくれます。データ数が多ければ多いほど、この差は数秒から数分レベルの圧倒的な違いとなって現れます。
—
3. どっちを使うべき?実務での使い分け基準
「じゃあ、これからは全部 `Join` を使えばいいの?」と思われるかもしれませんが、適材適所という言葉があります。実務での明確な使い分けの基準を整理しておきましょう。
| 比較項目 | `&` 演算子 | `Join` 関数 + 配列 |
| :— | :— | :— |
| 得意なシチュエーション | 2〜3個の短い文字列の結合
(例: `FullName = FirstName & ” ” & LastName`) | ループ内で大量(数百件以上)の文字列を結合する場合 |
| コードの書きやすさ | ★★★★★(直感的で簡単) | ★★★☆☆(配列の準備が必要) |
| パフォーマンス | 大量データでは最悪(フリーズの原因に) | 大量データでも超高速 |
- 数個の文字列を繋ぐだけなら: `&` 演算子でサクッと書くのが一番読みやすいです。
- ループ回数が分からない、あるいは数千件以上あるなら: `Join` 関数(または後述するコレクションや `ADODB.Stream` など)の出番です。
—
4. 初学者が陥りがちなエラーと注意点
`Join` 関数を使う際によくあるミスについても触れておきますね。ここを知っておけばエラーを怖がらずに済みます。
注意点1:配列の型は `String` にすること
`Dim dataList() As String` のように、必ず文字列型の配列として宣言してください。Variant型(型を指定しない)でも動くことは動きますが、メモリ効率や型変換のオーバーヘッドの観点から、文字列型を明示するのがプロの作法です。
注意点2:データ数が途中で変わる場合の対応
今回の例では「1万行と決まっている」前提でしたが、実際の業務ではデータの行数が毎回変わりますよね。その場合は、一度シートの最終行を取得してから `ReDim` をかけましょう。
Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
Dim dataList() As String
ReDim dataList(1 To lastRow)
For i = 1 To lastRow
dataList(i) = Cells(i, 1).Value
Next i
result = Join(dataList, vbCrLf)
これなら、どんなファイルが来ても柔軟に対応できます!
—
まとめ
今回は、文字列連結の裏側の仕組みと、`&` 演算子・`Join` 関数の使い分けについて解説しました。
- ループ内で `&` を使った文字列結合は、メモリの再割り当てが発生するため大量データでは遅い。
- 配列にデータを溜め込んでから `Join` 関数で一気に結合する手法は、メモリに優しく圧倒的に高速。
- 小規模なら `&`、大量データなら `Join` と使い分けるのがスマートなエンジニアの道。
「動けばいいや」のコードから、「速くて美しい、メモリに優しい」コードが書けるようになると、VBAを書くのが何倍も楽しくなりますよ。
ここをクリアしたあなたなら、もうマクロの記録の卒業生ではなく、立派なVBAプログラマーの仲間入りです。ぜひ、日々の業務の自動化に取り入れてみてくださいね。応援しています!
