【入門編】For EachとFor Nextの使い分け:コレクション操作におけるパフォーマンスの最適解 – Excel VBA解析バイブル

スポンサーリンク

こんにちは!マクロの記録から一歩抜け出して、「自分の手で自由自在にExcelを動かしたい」と熱心に学んでいるあなたへ。

Excel VBAを書いていると、何度も何度も繰り返し処理を行う場面に出会いますよね。「データを上から順に見たい」「シートを一枚ずつめくって確認したい」――そんなときに必ず使うのがループ(繰り返し)処理です。

ここで多くの人が「あれ、どっちを使えばいいんだっけ?」と立ち止まるのが、`For…Next``For Each…Next` の使い分けです。

「とりあえず動けばいいや」と適当に選んでいると、処理が異様に遅くなったり、思わぬエラーでマクロが止まったりしてしまいます。でも、ご安心ください。それぞれのキャラクターと使い所さえ分かってしまえば、もう迷うことはありません。

今回は、現場のプロたちがどのようにこの2つを使い分けているのか、パフォーマンスの裏側も含めて優しく、そして深く解説していきますね。ここをクリアすれば、あなたのVBAスキルは一段と洗練されますよ!

1. 2大ループの基本キャラクターを知ろう

まずは、この2つのループが「何をどう見ているのか」をイメージで掴みましょう。

① `For…Next` =「番号(インデックス)で数える職人」

  • イメージ: 「1番目、2番目、3番目……」と、順番に番号を指定して引き出しを開けていくスタイル。
  • 得意なこと: 「3行目から100行目まで」「2個飛ばしで」といった、数字をベースにした規則正しい処理

② `For Each…Next` =「目の前にあるものを次々に手にとる職人」

  • イメージ: 段ボール箱の中にある商品を、番号を気にせず「次、これ! 次、これ!」と端から手に取っていくスタイル。
  • 得意なこと: コレクション(シートの集まり、セルの集まりなど)の中にある「実体(オブジェクト)」を丸ごと相手にする処理

2. 【実例コード】どう書くのか見比べてみよう

百聞は一見にしかず。A1からA10セルに「テスト」と文字を入れるコードを、両方の書き方で見比べてみましょう。

`For…Next` の場合(数字で管理)

Sub Sample_ForNext()
Dim i As Long

‘ 1から10までの「数字」を使ってループする
For i = 1 To 10
Cells(i, 1).Value = “テスト”
Next i
End Sub

解説:
`i` という変数が、1、2、3……と10まで変化します。`Cells(i, 1)` は、「i行目の1列目のセル」を指定しているので、意図した通りのセルに書き込むことができます。

`For Each…Next` の場合(実体を直接つかむ)

Sub Sample_ForEach()
Dim rng As Range
Dim targetCell As Range

‘ 対象となるセル範囲をセット
Set rng = Range(“A1:A10”)

‘ 範囲内のセルを1つずつ「実体」として取り出す
For Each targetCell In rng
targetCell.Value = “テスト”
Next targetCell
End Sub

解説:
ここでは「何番目か」という数字は一切登場しません。`Range(“A1:A10”)` というセルの集まり(コレクション)から、1つずつセルという「実体(オブジェクト)」を `targetCell` に放り込んでいきます。

3. どっちが速い? パフォーマンスの真実と使い分けの極意

さて、ここからが本題です。「どっちを使っても同じなら、短い方がいいや」と思っていませんか? 実は、処理のスピードにおいて明確な違いが出るケースがあります。

結論:使い分けの黄金律

1. 「セル範囲(Range)」や「シート(Worksheets)」をただ順番に舐めるだけなら:
👉 `For Each…Next` が速くてスマート!
2. 「行番号そのもの」を使って計算をしたり、特定の行を飛ばしたり、行を削除したりするなら:
👉 `For…Next` の一択!

なぜ `For Each` の方がセル操作で速いのか?

Excel VBAの最大のボトルネックは、VBAとExcelの本体(ワークシート)の間で行われる「通信」です。

`For…Next` で `Cells(i, 1)` と書くたびに、VBAはExcelに対して「おい、i行目の1列目のデータをくれ!」と毎回パスを出しています。これが積もると地味に動作が重くなります。
一方、`For Each` は最初に範囲をごっそり掴んでメモリ上に保持するため、VBAとExcelの往復回数が少なくなり、結果として処理スピードが向上する傾向にあります。

4. ⚠️ 初学者が絶対にハマる「落とし穴」とエラー対策

最後に、実務でよくある失敗パターンをご紹介します。ここを知っておくだけで、無駄な残業を防げますよ!

罠その1:`For Each` でループ中に「行を削除」してはいけない!

「条件に一致する行を削除したい!」というとき、`For Each` を使うとエラーになるか、判定がバグってデータを盛大に消し飛ばします。

  • NGな例(For Eachで削除):

‘ ※絶対にやってはいけない例
Dim c As Range
For Each c In Range(“A1:A10”)
If c.Value = “削除” Then
c.EntireRow.Delete ‘ ←ループの途中で足場を壊すのでバグる!
End If
Next c

  • 正解(For…Next を「下から上へ」回す):

行を削除したり挿入したりする場合は、必ず `For…Next` を使い、下から逆順(Step -1)で回します。

Dim i As Long
‘ 下の行(10行目)から上の行(1行目)に向かってカウントダウン
For i = 10 To 1 Step -1
If Cells(i, 1).Value = “削除” Then
Cells(i, 1).EntireRow.Delete
End If
Next i

(上から順に消すと、行番号がズレて判定漏れが起きるため、下から消すのが鉄則です!)

まとめ

いかがでしたでしょうか?

  • `For…Next` は、数字でコントロールする万能選手。行の削除や複雑な位置計算が必要なときに頼りになる。
  • `For Each…Next` は、目の前のオブジェクトを優しく順番に撫でていくような、コレクション操作のスピードスター。

この2つの特性を理解しておけば、シチュエーションに応じて最適なコードが書けるようになり、マクロの動作スピードも見違えるほど快適になります。

「ここをクリアすれば、Excel VBAの基本はバッチリですよ!」
自信を持って、次の自動化の扉を開いていきましょう。あなたのVBAライフを応援しています!

タイトルとURLをコピーしました