月次決算の時期、経理担当者のデスクから聞こえるのは、キーボードの連打音と深いため息だ。1,000行を超える営業支店別の売上データ。これを1枚ずつ別のシートに転記したり、特定の条件でセルに色を塗ったりする作業は、人間の集中力の限界を軽々と超えていく。100行、200行と進むうちに「今、何行目までやったっけ?」という疑念が頭をよぎり、結果としてわずかな入力ミスがデータの不整合を生んでしまう。こうした単純かつ膨大な繰り返し作業から自分を解放し、実務の精度を100%に引き上げるための唯一の手段が、VBAの「For文」による自動化である。
- VBA 繰り返し処理 For の基本構造とカウンタ変数の本質
- 大量データを一瞬で処理するための最終行取得テクニック
- 経理部の月次処理を劇的に変える条件分岐との組み合わせ
- 在庫管理で失敗しないための行削除と逆順ループ
- 支店別売上データを1枚に集約する複数シート横断処理
- 営業管理を効率化する二重ループとマトリックス表の操作
- 処理速度が10倍変わる画面更新停止と計算モード設定
- デバッグ効率を最大化するローカルウィンドウとステップ実行
- GoogleスプレッドシートのGASとVBAの繰り返し処理の違い
- 現場のトラブルを防ぐエラーハンドリングの実践
- 365世代の新機能とVBAをどう使い分けるべきか
- 明日からの実務に取り入れる3ステップ
VBA 繰り返し処理 For の基本構造とカウンタ変数の本質
プログラミングを学び始めた人が最初に出会う「繰り返し(ループ)」の代表格がFor文だ。実務において、For文は「決まった範囲を、決まったルールで、機械に代行させる」ための司令塔となる。構文自体は非常にシンプルだが、その背後にある「変数の動き」を正確にイメージできるかどうかが、実務で使いこなせるかどうかの分岐点になる。
カウンタ変数は単なる数字の箱ではない
For文を書く際、必ず「Dim i As Long」のように変数を宣言する。この「i」はカウンタ変数と呼ばれ、今何回目の処理をしているかを記憶しておくための場所だ。筆者が社内研修で講師を務めていると、受講生から「なぜ『i』なのですか?」という質問をよく受ける。これはIndex(索引)の頭文字から取られた慣習だが、実務家の視点では「セルの座標(行番号や列番号)を指し示すポインタ」と捉えるのが正解だ。

Long型を使うべき実務上の理由
古いVBAの解説書やネットの記事では、カウンタ変数に「Integer型」を使っている例が散見される。しかし、現代の実務においてInteger型を使うのは明確なリスクだ。Integer型が扱える最大値は32,767。一方で、Excelの最大行数は1,048,576行に達する。
ポイント: 経理や営業管理で扱うデータは、数万行を超えることが珍しくありません。Integer型でループを回すと、データが32,768行目に入った瞬間に「オーバーフロー」エラーでシステムが停止します。最初から「Long型」を使うことを鉄則にしてください。
大量データを一瞬で処理するための最終行取得テクニック
実務において「For i = 1 To 10」のように、繰り返す回数を固定値で書くことはまずない。扱うデータ量は日々変動するからだ。昨日は100行だった売上データが、今日は150行になっているかもしれない。この変化に自動で対応するために、VBAに「データの末尾」を探させる処理が必要になる。
End(xlUp).Row でデータの増減に自動対応する
最も信頼性が高く、実務で多用されるのが「End(xlUp).Row」だ。これは、ワークシートの最下行から上に向かってデータを探し、最初に見つかった入力済みの行番号を返すプロパティである。
Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
' 2行目から最終行までの処理
Next i
この1行を加えるだけで、ツールはデータの増減を気にせず動くようになる。筆者の経験では、この「最終行の自動取得」を教えただけで、担当者の作業時間が毎日30分短縮された事例もある。

複数列のデータがある場合の判定基準
実務では「どの列を基準に最終行を決めるか」が重要になる。例えば、営業部の顧客リストで「顧客名(A列)」は必ず入力されているが、「備考(E列)」は空欄が多い場合、E列を基準に最終行を取ると、データが途中で切れてしまう。
注意点: 最終行を取得する際は、必ず「主キー」となる列(社員番号、伝票番号、商品コードなど、必ず値が入る列)を指定してください。これがずれると、ループ処理が途中で終了し、重要なデータが未処理のまま残る原因になります。
経理部の月次処理を劇的に変える条件分岐との組み合わせ
For文が真価を発揮するのは、If文による「条件分岐」と組み合わせたときだ。上から順番にデータを確認し、特定の条件を満たすものだけを抽出・加工する。これこそが、人間が最も苦手とし、機械が最も得意とする領域である。
勘定科目の入力漏れを自動チェックする
例えば、経費精算システムの書き出しデータに「勘定科目(C列)」の空欄がないかチェックするシナリオを考えてみよう。1,000件の申請を一つずつ目視で確認するのは苦行だが、For文なら数秒で終わる。
For i = 2 To lastRow
If Cells(i, 3).Value = "" Then
Cells(i, 3).Interior.Color = vbRed ' 未入力ならセルを赤く塗る
End If
Next i
筆者が研修で教えていると、こうした「チェックの自動化」は最も喜ばれる。人間は「ミスをしないように気を付ける」よりも「ミスをシステムで見つける」仕組みを構築すべきだ。
特定の売上金額以上に色を付ける実務シナリオ
営業管理において、予算達成状況を可視化する場合もFor文が役立つ。「商品型番 A-001」の売上が100万円を超えている行だけを強調したい場合、セルの値を一つずつ判定していく。実務では単なる色塗りだけでなく、別シートへの転記や、担当者へのメール通知フラグの作成などに応用される。

在庫管理で失敗しないための行削除と逆順ループ
For文を使い始めた初心者が必ずと言っていいほど直面する「落とし穴」がある。それが「ループ中に行を削除する」処理だ。普通に上から順番(1 To 10)に行を削除しようとすると、削除した瞬間に下の行が繰り上がり、次の行の判定がスキップされてしまう。
Step -1 がなぜ行削除に必須なのか
この問題を解決するのが「Step -1」というキーワードだ。通常、For文はカウンタ変数を1ずつ増やすが、Step -1 を指定すると、逆に1ずつ減らしながら処理を進める。
' 下から上に向かってループを回す
For i = lastRow To 2 Step -1
If Cells(i, 5).Value = 0 Then
Rows(i).Delete ' 在庫数が0なら行を削除
End If
Next i
筆者の経験では、この「逆順ループ」を知らずに行削除ツールを作り、「なぜか削除漏れが発生する」と相談に来る初心者が非常に多い。下から上に処理を進めれば、行が繰り上がっても次に判定する行番号には影響が出ないのだ。
在庫数ゼロの商品を別シートへ抽出する
行を削除するのではなく、特定の条件に合うデータを別シートへ書き出す場合も、For文は有効だ。この場合、書き出し先の行番号を管理する別の変数(例:k)を用意するのがコツである。
Dim k As Long
k = 2 ' 書き出し先の初期行
For i = 2 To lastRow
If Cells(i, 5).Value <= 0 Then
Worksheets("在庫切れリスト").Cells(k, 1).Value = Cells(i, 1).Value ' 商品名転記
k = k + 1 ' 書き出し先の行を1つ進める
End If
Next i

支店別売上データを1枚に集約する複数シート横断処理
営業管理の現場では、東京、大阪、名古屋といった各支店から送られてきた別々のワークシートを、1枚の「全社集計シート」にまとめる作業が頻繁に発生する。シートの数だけコピペを繰り返すのは時間の無駄であり、For文(特にFor Each構文)を使えばこれを一瞬で終わらせることができる。
WorksheetsコレクションとFor Eachの使い分け
「For Each ws In Worksheets」という書き方は、ブック内のすべてのシートを対象に処理を行う際に便利だ。数値で回すFor文とは異なり、「次のシート、次のシート」とオブジェクトを直接参照するため、シート名が変更されても柔軟に対応できる。
Dim ws As Worksheet
For Each ws In Worksheets
If ws.Name <> "全社集計" Then
' ここにコピー処理を書く
End If
Next ws
集計シートを除外するためのIf文の書き方
上記のコードにある「If ws.Name <> "全社集計"」は、実務において極めて重要な1行だ。これがないと、集計先のシート自体をコピー対象に含めてしまい、無限ループのような挙動やデータの重複を招くことになる。
ポイント: 複数のシートをループ処理する場合、必ず「処理の対象外とするシート」を明確に指定してください。集計シート、設定用シート、マスタデータなどは除外するのが一般的です。
営業管理を効率化する二重ループとマトリックス表の操作
縦軸に「社員名」、横軸に「4月、5月、6月…」と月が並んでいるような、いわゆるマトリックス形式(クロス集計)の表を操作する場合、For文の中にさらにFor文を入れる「二重ループ」が必要になる。
縦(支店)×横(月)のクロス集計を自動化する
例えば、各月の予算実績比較表で、予算を下回ったセルだけを赤字にする処理を考えてみよう。
For i = 2 To 50 ' 行方向(支店)
For j = 2 To 13 ' 列方向(1月〜12月)
If Cells(i, j).Value < Cells(i, j + 20).Value Then ' 予算と比較
Cells(i, j).Font.Color = vbRed
End If
Next j
Next i
この二重ループを使えば、数千セルの判定も一瞬で終わる。筆者が経理部で予算管理ツールの保守をしていた際、この処理を組み込んだことで、月次の予実管理資料の作成時間が2時間から5分に短縮された。

変数iとjが入れ替わる初心者のミスを防ぐ
二重ループで初心者が最も犯しやすいミスが、行用の変数iと列用の変数jをコード内で取り違えることだ。
「Cells(j, i)」と書いてしまうと、縦横が逆転し、最悪の場合Excelがフリーズする。
注意点: 二重ループを書くときは、内側のループがどの範囲を指しているのかをコメントで明記しましょう。「iは行、jは列」という自分なりのルールを固定することが、バグを防ぐ近道です。
処理速度が10倍変わる画面更新停止と計算モード設定
For文による繰り返し処理は非常に強力だが、処理件数が数千件、数万件に達すると、画面がチカチカと動き、動作が重くなることがある。これはExcelが1回の処理ごとに画面を書き換え、再計算を行っているからだ。
ScreenUpdatingプロパティでフリーズを防ぐ
実務用のコードでは、必ず以下の2行で処理を挟むのがプロの鉄則だ。
Application.ScreenUpdating = False ' 画面更新を止める
' --- ここにFor文の処理 ---
Application.ScreenUpdating = True ' 画面更新を再開する
これだけで処理速度は劇的に向上し、ユーザーが「Excelがフリーズした」と勘違いして強制終了させるトラブルも防げる。筆者の研修では、この設定を「VBAのおまじない」として必ず最初に教えている。
膨大な数式があるシートでのCalculation設定
もしシート内に大量のVLOOKUP関数などが埋め込まれている場合、1行処理するたびに再計算が走り、動作が極端に遅くなる。その場合は、一時的に再計算を「手動」に切り替える。
Application.Calculation = xlCalculationManual
' --- 処理 ---
Application.Calculation = xlCalculationAutomatic
Microsoft公式サイト: Application.ScreenUpdating プロパティ

デバッグ効率を最大化するローカルウィンドウとステップ実行
コードを書いて一度で完璧に動くことは稀だ。どこかでエラーが出たり、意図しない動きをしたりする。そんな時、「どこが間違っているのか」を特定する技術が、デバッグだ。
F8キーでコードを1行ずつ動かしてバグを見つける
初心者の多くは、エラーが出るとコードを眺めて考え込んでしまう。しかし、正解は「動かしながら確認する」ことだ。VBE(エディタ)でF8キーを押すと、コードを1行ずつ実行(ステップ実行)できる。For文の中で変数がどう変わっていくのかを、自分の目で追うことが最も確実な学習法だ。
イミディエイトウィンドウによる変数の値確認
「今、変数iには何が入っているのか?」を知りたいときは、イミディエイトウィンドウを活用する。「Debug.Print i」とコード内に書いておけば、実行中の変数の推移がログとして記録される。
筆者が若手社員を指導する際、このデバッグ手法を身につけているかどうかで、自力で問題を解決できるまでの時間が10倍以上変わることを実感している。

GoogleスプレッドシートのGASとVBAの繰り返し処理の違い
最近では、ExcelだけでなくGoogleスプレッドシートを併用する職場も増えている。スプレッドシートの自動化(GAS: Google Apps Script)でもFor文は使われるが、VBAと同じ感覚で書くと「非常に遅い」という問題に直面する。
getValue()の回数を減らす考え方
VBAでは「Cells(i, 1).Value」のように、ループの中で毎回セルにアクセスしても、ある程度の速度で動く。しかし、GASでこれをやると、Googleのサーバーとの通信が毎回発生し、処理が途中でタイムアウトしてしまう。
GASの場合は「一度に範囲の値を配列として取得(getValues)し、メモリ上でループさせ、最後にまとめて書き出す」というアプローチが必須となる。
クラウド環境特有の実行時間制限
VBAには(PCのスペックが許す限り)実行時間の制限はないが、GASには「6分制限」という壁がある。大規模な繰り返し処理を行う場合、この環境の差を理解してツールを設計しなければならない。
ポイント: 会社がMicrosoft 365からGoogle Workspaceへ移行した場合でも、For文の「論理的構造」は共通です。まずはVBAでロジックを身につけ、環境に合わせて最適な書き方を選べるようになりましょう。
現場のトラブルを防ぐエラーハンドリングの実践
実務で使うツールを他人に渡す際、最も恐ろしいのが「想定外のエラーによる停止」だ。データの途中に文字化けがあったり、シートが保護されていたりすると、For文は途中で力尽きてしまう。
On Error GoTo で予期せぬ停止を回避する
エラーが発生しても強制終了させず、適切なメッセージを出して終了させるのが、実務家のマナーだ。
On Error GoTo ErrorHandler
' --- For文の処理 ---
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました。データを確認してください。"
End Sub
シート名変更によるエラーを防ぐオブジェクト名の活用
「Sheets("売上データ")」と書いていると、ユーザーがシート名を「売上データ_5月」に変えた瞬間にツールが動かなくなる。これを防ぐには、VBEのプロパティウィンドウで設定できる「オブジェクト名」を直接コードで使うのが上級者のテクニックだ。
Microsoft公式サイト: On Error ステートメント
365世代の新機能とVBAをどう使い分けるべきか
Microsoft 365の普及により、かつてはVBAが必要だった処理が「標準関数」で完結するケースが増えている。例えば、データの抽出ならFILTER関数、重複削除ならUNIQUE関数、並べ替えならSORT関数だ。これらは「スピル」という機能により、1つの数式で複数のセルに結果を返してくれる。
FILTER関数やスピルで十分なケース
単に「特定の条件に合うデータを抽出して表示したい」だけであれば、もはやFor文を書く必要はない。関数のほうがメンテナンス性も高く、動作も軽い。
それでもVBAが必要になる「ファイル操作」や「保存」
一方で、「100個のPDFファイルを作成して名前を付けて保存する」「他のブックを開いてデータを書き込む」「特定の時間にメールを自動送信する」といった「Excelの外側」への操作は、関数の領域ではない。これこそが、令和の時代においてもFor文を学ぶべき真の理由だ。
ポイント: 「関数でできることは関数でやり、関数でできない自動化だけをVBAで行う」のが、現代の最もスマートなExcel活用法です。
明日からの実務に取り入れる3ステップ
VBAのFor文は、一度身につければ一生モノの武器になる。しかし、最初から複雑な二重ループや大規模なシステムを作ろうとする必要はない。まずは、目の前にある「単純作業」を一つ、コードに置き換えることから始めてほしい。
明日から実践すべきステップは以下の通りだ。
まずは「行番号の自動取得」を1行書いてみる:データの最終行を正しく認識できているか、メッセージボックス(MsgBox lastRow)で確認すること。
小規模なチェック作業から自動化する:いきなりデータの削除や加工をするのは怖いもの。まずは「条件に合うセルを黄色く塗る」といった、元のデータを壊さない処理から着手する。
* 画面更新停止(ScreenUpdating)をセットで覚える:これを書くだけで「プロが作ったツール」のような快適な動作になる。
実務家として15年Excelを使い続けてきた筆者が断言できるのは、For文をマスターした瞬間に「仕事の終わらせ方」が変わるということだ。手作業による残業をゼロにし、よりクリエイティブな分析や企画に時間を使えるようになることを願っている。


コメント