🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の End — End・End Sub・Exit Sub・Stop の違い

|

Excel VBA の End — End・End Sub・Exit Sub・Stop の違い

TL;DR — 素の End 文は マクロ全体 を即座に止めます。すべての変数(モジュールレベルや Static を含む)を消し、UserForm を閉じ、用意しておいた後片付けをすべて飛ばします。これは End Sub(Sub がど こで終わるかを示すだけ)とも、Exit Sub(一つのプロシージャから戻り、プログラムを続けさせる)とも、 Stop(デバッガーで一時停止する)とも別物です。素の End はほとんど決して使いたくないものです。プロシ ージャを出るには Exit Sub を使いましょう。

Sub WhyEndIsDangerous()
    Application.ScreenUpdating = False
    ' ... 作業 ...
    If somethingWrong Then End       ' 今すぐ止まる - ScreenUpdating は False のまま!
    ' ... さらに作業 ...
    Application.ScreenUpdating = True ' この後片付けの行は End のあと決して動かない
End Sub

VBA には end という語を含む構文が四つあり、それらを取り違えると本物のバグを生みます。そのうち実際にプログ ラムを止めるのはただ一つ — 素の End — で、しかも考えうるかぎり最も手荒なやり方で止めます。ほかは単にブロ ックを閉じるか、プロシージャから戻るだけです。どれがどれかを知っていることが、自分で後始末をするマクロと、 Excel を中途半端に設定されたままにするマクロとの違いになります。

この記事で学べること

  • 素の End 文が実際に何をするのか — そしてどれだけの状態を壊すのか
  • End・End Sub・End If・Exit Sub・Stop がなぜ五つの別物なのか
  • 本当のバグ — End がどう後片付けを飛ばし、ScreenUpdating やイベントを無効のまま残すのか
  • 通常の戻りなら保たれるモジュールレベルや Static の変数を、End がなぜ消してしまうのか
  • End が正しい選択になるのはいつか(そもそもあるのか)、そして代わりに何を使うのか
  • Stop が End とどう違うか — デバッグのための一時停止か、終了か

考え方の軸:End はドアではなくプラグ

そっくりな四つを、どれだけ 止めるかで並べてみます。

End If      ' If ブロックを閉じる - 何も止めない; 構造上の目印
End Sub     ' Sub の終わりを示す - プロシージャはどのみちここで終わる
Exit Sub    ' 「この」プロシージャから戻る - プログラムは動き続ける
End         ' マクロ「全体」を終了する - すべてが止まり、後片付けはされない

End Sub と End If は句読点です。ブロックがどこで終わるかを VBA に伝えます。これらは「実行」されません。 Exit Sub は、一つのプロシージャから出る ドア です — あなたは出て、呼び出し元は続き、後片付けが動きま す。素の End は プラグ です。エディターの Reset ボタンを押したかのように、コールスタック全体を一度に止 めます。下流にあるものすべて — 呼び出し元、その呼び出し元、二行下に書いた後片付けの行 — が、ただ見捨てられ ます。この一つの区別、ドア対プラグ こそが、このページのすべてです。

素の End 文が実際に壊すもの

End は「コードを止める」よりはるかに多くのことをします。それが発火すると、VBA はプロジェクトの実行時状態 のすべてを取り壊します。

  • すべての変数がリセットされる — ローカル、モジュールレベル、そして Static の変数が、値を失います。
  • 開いているすべての UserForm がアンロードされる — QueryClose や後片付けのイベントが通常どおり動くこ となく。
  • コールスタックが破棄される — その上のどのプロシージャも、終わることも、残りの行を走らせることもできま せん。
  • On Error ハンドラーがクリアされ、VBA プロジェクトの実行時状態は、起動したてのようにリセットされます。

End が しない のは、ブックや Application にすでに加えた変更を取り消すことです。ここが危険の核心です。 冒頭で Application.ScreenUpdating = False にして、途中で End にぶつかると、画面更新は無効のままになりま す — それを元に戻すはずだった行が、End がたった今見捨てた多くの行の一つだからです。

本当のバグ:End は後片付けを飛ばす

ちょっとしたものを超えるマクロのほとんどは、冒頭で Excel の状態をいくつか設定し、最後にそれを元へ戻します。

Sub Report()
    Application.ScreenUpdating = False
    Application.EnableEvents = False

    If Not FileExists() Then End    ' <-- 落とし穴

    ' ... レポートを組み立てる ...

    Application.EnableEvents = True     ' End が発火したら決して到達しない
    Application.ScreenUpdating = True   ' End が発火したら決して到達しない
End Sub

FileExists が False を返すと、その End はその場ですべてを止めます。EnableEvents と ScreenUpdating は False のまま残されるので、ユーザーの Excel はワークシートのイベントを黙って無視し、再描画もしなくなりま す — クラッシュのように見えて、実際にはただ後片付けが飛ばされただけの「フリーズした Excel」というサポートチ ケットです。直し方は、終了する のではなく 戻る ことです。End を Exit Sub に置き換え、元へ戻す行を必 ず動く場所(単一の出口経路か、エラーハンドラー)に置きます。Exit Sub はプロシージャを出ますが、あなたの後 片付けを — そしてプログラムの残りを — 動かします。

End は Static とモジュールレベルの変数を消す

それだけで一節を割く価値のある、もっと微妙な帰結があります。通常の戻り(Exit Sub、あるいは単に End Sub に到達すること)は、モジュールレベルと Static の変数をそのまま残します — 呼び出しをまたいで保持されること こそ、それらの存在意義です。素の End は、それらをほかのすべてもろとも投げ捨てます。

' モジュールレベル
Dim gRunCount As Long

Sub Tick()
    gRunCount = gRunCount + 1     ' 実行をまたいで積み上げるつもり
    If gRunCount > 100 Then End   ' End は gRunCount を 0 に戻してしまう!
End Sub

もし設計のどこかが、マクロの実行と実行のあいだ状態が生き残ることに頼っているなら — カウンター、キャッシュし たオブジェクト、読み込んだ設定 — はぐれた End はそれを黙ってリセットし、バグはずっとあとになって「数がい つまでも振り出しに戻る」という形で現れます。これも、素の End がまれで意図的であるべきもう一つの理由です。

Stop は End ではない:終了せず、デバッグのために一時停止する

Stop は関係がありそうに見えて、終了とは正反対のことをします。実行を 中断 し、その行で VBA エディター の中断モードへあなたを落とし込みます。すべての変数はまだ生きているので、中身を調べられます — コードに書き込 んだブレークポイントとまったく同じです。

Sub Investigate()
    Dim total As Double
    total = ComputeTotal()
    Stop                     ' ここでエディター内で一時停止; total はまだ読める
    Range("A1").Value = total
End Sub

Stop はデバッグ中に使い、出荷する前に取り除きます(F9 のブレークポイントと違い、Stop はソースの中に残る ので、消し忘れが一つあればユーザーのマクロをエディターで止めてしまいます)。End は終了させ、Stop は一時 停止させます。どちらも、ユーザーが実行するコードの中で発火してほしいものではありません — マクロを止めずに動 きを観察するには、VBA Debug.Print を参照してください。

End が正しい選択になることはあるのか?

まれに、そして常に意図的に、です。正直な使いどころは狭いものです。壊れた状態のまま続ける危険を冒すくらいな ら、いっそすべてを止めたい、スタンドアロンのツールでの破滅的で回復不能な状況。あるいは、プロジェクト全体を 本当にリセットしたい、モードレスな UserForm 駆動のアプリを畳むとき。それでも、単一のきれいな出口にたどり着 く — Application の設定を元へ戻し、開いたものを閉じる — ほうを選び、それから止めましょう。日々のマクロで は、「ここでどう止めるか?」の答えは Exit Sub(このプロシージャを出る)か、コードが自力で End Sub にたど り着くよう組み直すことです。素の End を打ち込んでいるなら、いったん止まって、本当に すべてを終了し、後片 付けをすべて飛ばす つもりなのかを確かめてください。

ExcelMaster の活用

素の End は、小さな語なのに不釣り合いに大きな爆発半径を持ち、その被害は、実は ScreenUpdating が無効のま まなだけの「フリーズした」Excel をユーザーが報告するまで、目に見えません。間違いは、Exit Sub のつもりで End を使うことと、出荷したコードに Stop を残すことです。

ExcelMaster は、単一のきれいな出口から出る プロシージャを書きます。戻るための Exit Sub、必ず動く復元の行、そしてユーザーが触れるコードには、はぐれた End も Stop もありません。マクロが早めに切り上げる必要があるときも、Excel を中途半端に設定したまま残すこ となくそうします。ブックとコードはあなたの手元に残ります。

よくある質問

VBA の End 文は何をしますか?

素の End 文は、マクロ全体を即座に終了させます。すべての変数(モジュールレベルと Static を含む)をリセッ トし、開いている UserForm をアンロードし、コールスタックを破棄し、On Error ハンドラーをクリアします — です が、ブックや Application にすでに加えた変更は取り消 しません。ですから、用意しておいた後片付けはすべて 飛ばされます。こうせずにプロシージャを出るには、Exit Sub を使いましょう。

End と End Sub の違いは何ですか?

End Sub は、Sub プロシージャがどこで終わるかを示すだけです — 構造上の目印であり、プロシージャはどのみち そこで終わります。それ単独で書かれた素の End は、どこに現れようと、その場でプログラム全体を終了させます。 End Sub はブロックを閉じ、End はすべてを止めます。

マクロを止めるのに End を使うべきですか?

たいていは、いいえ。現在のプロシージャを出るには Exit Sub を使います。これは呼び出し元へ戻り、後片付けを 動かします。素の End は後片付けをすべて飛ばし、ScreenUpdating を無効のまま、あるいはイベントを無効のまま にしかねず、フリーズしたように見える Excel を生みます。End は、まれで、意図的で、回復不能な状況のために取 っておきましょう。

End と Stop の違いは何ですか?

End はマクロを終了させ、その状態をクリアします。Stop は実行を一時停止し、すべての変数がまだ生きたまま、 VBA エディターの中断モードへあなたを落とし込むので、デバッグできます — コードに書き込んだブレークポイントの ようなものです。Stop は出荷前に取り除きましょう。F9 のブレークポイントと違い、ソースの中に残り、ユーザー のマクロを止めてしまうからです。

マクロを実行したあと、ScreenUpdating がまだ無効なのはなぜですか?

もっとも考えられるのは、Application.ScreenUpdating = True に戻す行の手前で、素の End(または処理されなか ったエラー)がマクロを止めたことです。End は残りのコードを飛ばすので、復元は一度も動きませんでした。End を Exit Sub に置き換え、復元の行を単一の出口経路かエラーハンドラーに置いて、必ず実行されるようにしましょ う。

検証環境

検証環境: Excel 365 (Windows 11)、VBA 7.1 — 最終確認 2026-09-24。

関連ガイド: VBA Exit For · VBA GoTo · VBA On Error · VBA Debug.Print · VBA Sub