VBA 繰り返し処理 For

VBA 繰り返し処理 For アイキャッチ画像 マクロ・VBA

1,000行を超える営業支店別の売上データ。これを1枚ずつ別のシートに転記したり、特定の条件で色を塗ったりする作業。手作業で進めると、100行を過ぎたあたりで集中力が切れ、入力ミスが必ずと言っていいほど発生する。こうした単純な繰り返し作業から自分を解放してくれるのが、VBAの「For文」だ。

初級:まず基本を押さえる「VBA 繰り返し処理 For」の仕組み

プログラミングを始めたばかりの人が最初にぶつかる壁が、この繰り返し処理だろう。しかし、構造自体は非常にシンプルだ。決まった回数だけ同じ動作を繰り返す。それだけの話である。

For Next構文の書き方とルール

基本となる書き方は、以下のコードブロックの通り。

Sub BasicLoop()
    Dim i As Long
    For i = 1 To 10
        ' ここに繰り返したい処理を書く
        Cells(i, 1).Value = i & "行目"
    Next i
End Sub

「For i = 1 To 10」は、変数iの値を1から10まで1ずつ増やしながら、Nextまでの間にある処理を実行せよ、という意味になる。筆者が社内研修で教えている際、最も多く受ける質問が「この『i』って何ですか?」というものだ。これは「カウンタ変数」と呼ばれるもので、今何回目の処理をしているかを数えるための箱だと考えればいい。

VBA 繰り返し処理 For - A列に「1行目」から「10行目」まで文字が入力されたExcel画面
A列に「1行目」から「10行目」まで文字が入力されたExcel画面

カウンタ変数の役割を理解する

変数iは、単に回数を数えるだけではない。先ほどの例のように、セルの行番号としてそのまま利用できる。

ポイント: カウンタ変数には「Long型」を使おう。昔の解説書にはInteger型と書かれていることが多いが、Excelの行数はIntegerの最大値(32,767)を簡単に超えてしまう。最初からLong型を使う癖をつけておくのが実務家の鉄則だ。

実務でよく見かけるのは、この変数iを列番号に使ったり、複数の変数(iとj)を組み合わせて表全体を操作したりする場面だろう。

VBA 繰り返し処理 For - VBEのエディタ画面で変数iを定義しFor文を入力する様子
VBEのエディタ画面で変数iを定義しFor文を入力する様子

中級:実務で使えるレベルに引き上げる

基本がわかったところで、実際の業務でどう使うかを考えたい。10回繰り返すと決まっている作業は稀で、多くの場合は「データの最後まで処理したい」はずだ。

最終行を自動で取得してループさせる

実務で「1 To 10」と固定して書くことはまずない。データの件数は日々変わるからだ。そこで、データの最終行を自動で取得するコードと組み合わせる。

Sub SalesDataProcess()
    Dim lastRow As Long
    Dim i As Long
    
    ' A列の最終行を取得
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row
    
    For i = 2 To lastRow ' 1行目は見出しなので2からスタート
        ' 営業部ごとの売上金額を確認し、50万円以上ならセルを黄色にする
        If Cells(i, 3).Value >= 500000 Then
            Cells(i, 3).Interior.Color = vbYellow
        End If
    Next i
End Sub

Microsoft公式: Range.End プロパティを利用すれば、データの増減に柔軟に対応できる。筆者の経験では、この最終行取得をマスターするだけで、VBAの活用の幅は3倍以上に広がる。

VBA 繰り返し処理 For - 売上金額が50万円以上の行だけ背景色が黄色に塗られた管理表
売上金額が50万円以上の行だけ背景色が黄色に塗られた管理表

セルの値を順番に判定・操作する

経理の現場では、経費精算データの中に「不備」がないかチェックする作業が頻繁にある。例えば、勘定科目が空欄の行を見つけてメッセージを出すといった処理だ。

ここで初心者がつまずきやすいポイントを挙げておこう。それは「シートの指定」を忘れることだ。複数のブックやシートを開いて作業しているとき、単に「Cells」と書くと、今開いている(アクティブな)シートが対象になってしまう。意図しないシートを書き換えてしまった失敗は、誰しもが一度は経験するものだろう。

注意点: 実務用のコードでは、必ず「Sheets(“売上データ”).Cells(i, 1)」のように、どのシートを操作しているのかを明示しよう。この一手間が、重大な事故を防ぐ。

上級:効率化とトラブル回避のテクニック

さらに一歩進んで、より複雑な処理や、処理速度を意識した書き方を身につけたい。

Stepキーワードで1行おきに処理する

通常、For文は1ずつ増えるが、「Step」を使えば増え方を変えられる。

For i = 2 To 20 Step 2
    ' 2, 4, 6...と偶数行だけ処理する
Next i

筆者はこれを、表の1行おきに背景色をつけて見やすくする(縞々にする)際によく利用している。また、行を削除する場合は「Step -1」として、下から上に向かってループさせるのが定石だ。上から削除すると、行番号がずれて処理が飛ばされてしまうからだ。

二重ループでマトリックス表を操作する

縦軸に「支店名」、横軸に「月」が並んだ予算実績比較表など、縦横の広がりがある表を処理するには、For文の中にさらにFor文を入れる「二重ループ」が必要になる。

For i = 2 To lastRow ' 行方向
    For j = 2 To 13 ' 列方向(1月〜12月)
        ' 予算を実績が下回っていたら文字を赤くする
        If Cells(i, j).Value < Cells(i, j + 15).Value Then ' 実績と予算を比較
             Cells(i, j).Font.Color = vbRed
        End If
    Next j
Next i

二重ループは強力だが、処理回数が「行数 × 列数」と膨大になる。1,000行 × 50列なら5万回の処理だ。ここで工夫を怠ると、Excelがフリーズしたかのように重くなる。

VBA 繰り返し処理 For - 予算と実績が並んだ複雑な表で、未達の数字だけが赤字になっている状態
予算と実績が並んだ複雑な表で、未達の数字だけが赤字になっている状態

現場で使える実例集

ここからは、明日からすぐに使える具体的な業務シナリオを紹介する。

1. 複数支店のデータを1枚のシートにまとめる

各支店(東京、大阪、名古屋)から送られてきた別々のワークシートを、1枚の「集計シート」にコピーする作業。これもFor文の得意分野だ。

Sub ConsolidateSheets()
    Dim ws As Worksheet
    Dim destSheet As Worksheet
    Dim lastRow As Long
    
    Set destSheet = Sheets("全社集計")
    
    For Each ws In Worksheets
        If ws.Name <> "全社集計" Then
            lastRow = destSheet.Cells(destSheet.Rows.Count, 1).End(xlUp).Row + 1
            ws.Range("A2:G100").Copy destSheet.Cells(lastRow, 1)
        End If
    Next ws
End Sub

※ここでは「For Each」という、For文の親戚のような構文を使っている。シートの数だけ繰り返す場合に非常に便利だ。

2. 条件に合致する社員にメールの下書きを作成する

人事総務の担当者なら、特定部署の社員だけに連絡事項を送りたい場面があるだろう。社員リストを上から順に確認し、該当部署の社員がいればOutlookでメールの下書きを作る。

3. 商品在庫リストから在庫切れ商品を抽出する

在庫数が「0」以下の商品を行ごと別のシートへ転記する。このとき、転記先の行番号を管理する別のカウンタ変数を用意するのがコツだ。

Sub ExtractOutOfStock()
    Dim i As Long, k As Long
    k = 2 ' 抽出先の開始行
    
    For i = 2 To 500
        If Cells(i, "E").Value <= 0 Then ' E列が在庫数
            Rows(i).Copy Sheets("欠品リスト").Rows(k)
            k = k + 1
        End If
    Next i
End Sub
VBA 繰り返し処理 For - 元データから在庫0の商品だけが「欠品リスト」シートに綺麗に並んでいる様子
元データから在庫0の商品だけが「欠品リスト」シートに綺麗に並んでいる様子

プロのコツ:実務経験から得た独自の知見

15年Excelを使い倒してきた筆者が、効率化のために必ず行っている工夫を2つ紹介したい。

画面更新を停止して爆速化する

大量のデータをループで処理すると、画面がチカチカと動き、処理に時間がかかる。これを防ぐのが「Application.ScreenUpdating」だ。

Sub FastLoop()
    Application.ScreenUpdating = False ' 更新停止
    
    ' ここにFor文の処理を書く
    
    Application.ScreenUpdating = True ' 更新再開
End Sub

たったこれだけで、処理時間は半分以下になることもある。知らないと損をする、実務家必須のテクニックと言える。

無限ループに陥ったときの脱出策

For文では少ないが、条件設定を誤ると処理が終わらなくなる「無限ループ」に近い状態になることがある。Excelが砂時計状態になり、操作を受け付けない。そんなときは焦らず「Esc」キー、または「Ctrl + Pause/Break」キーを連打してほしい。強制的にマクロを中断できる。

ちなみに、実務でよく見かけるのは、ループの中で「MsgBox」を出してしまうミスだ。1,000回繰り返す処理の途中にメッセージボックスを入れると、1,000回「OK」をクリックする羽目になる。デバッグ中ならいいが、本番用コードでは絶対に避けたい。

Microsoft公式: For...Next ステートメントを確認すると、Exit Forを使ってループを途中で抜ける方法も記載されている。特定の条件で見つかったら即終了、という作りにすればさらに効率的だ。

まとめ

変数i(カウンタ変数)は「Long型」で定義するのが実務のスタンダード。
最終行の自動取得(End(xlUp))と組み合わせることで、データの増減に強いマクロになる。
画面更新の停止(ScreenUpdating = False)を忘れずに入れることで、処理速度が飛躍的に向上する。
行の削除を行うときは「Step -1」で下から順にループさせるのが鉄則。
* シート指定を明示的に行うことで、意図しないデータの書き換えミスを防げる。

基本の構文を覚えるだけなら10分もあれば十分だろう。しかし、それを実務で「安全に」「速く」動かすためには、ここで紹介したような現場の知恵が欠かせない。まずは5行程度の簡単なリストから、自動で動く感動を味わってみてほしい。基本を押さえれば、応用は自然と広がる。

コメント

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