VBA例外処理モデルを整理する

VBA例外処理モデルを整理する

VBAのOn Errorを、処理の流れとスタックの巻き戻しから理解する

Copyright © 2026 LWP 山中 一弘

本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。

記事要約

VBAのエラー処理は、見た目よりも扱いが難しい仕組みです。On Error Resume Next と On Error GoTo は、単なる書き方の違いではありません。どちらを使うかによって、エラーが発生したときに処理を続けるのか、エラーハンドラーへ制御を移すのかが変わります。

この記事では、過去の調査メモをもとに、VBAのエラー処理を「局所的なエラー確認」「エラーハンドラーの有効化」「スタックの巻き戻し」「Resumeによる再開」という観点で整理します。

結論として、VBAではエラー処理の範囲を明示的に細かく区切りにくいため、むやみに上位へ例外を流す設計よりも、関数内で処理を閉じ、必要な結果だけを戻り値や参照型引数で返す方が読みやすくなる場面が多くあります。

本記事の対象とゴール

想定読者

  • VBAで On Error Resume Next と On Error GoTo の違いを整理したい人

  • エラーハンドラー内でさらにエラーが起きたときの動きを理解したい人

  • Resume と Resume Next の使いどころを判断したい人

  • 業務マクロでエラー処理の書き方がばらついていると感じている人

本記事で得られること

  • VBAのエラー処理を、文法ではなく処理モデルとして理解できます。

  • エラー発生時にどのエラーハンドラーが使われるのかを説明できます。

  • On Error Resume Next と On Error GoTo の使い分けを、実務上の判断として整理できます。

  • VBAのエラー処理で無理をしない設計方針を持てます。

本記事で扱わないこと

  • VBA内部実装の厳密な仕様解説

  • すべてのErrオブジェクトプロパティの網羅

  • Access、Excel、Wordなどアプリケーション固有のエラー番号一覧

  • 大規模アプリケーション向けの例外処理フレームワーク設計

先に結論

VBAのエラー処理は、関数ごとに状態を持つ局所的な仕組みとして考えると整理しやすくなります。

On Error Resume Next を実行すると、以後のエラーでは処理が止まらず、次の行へ進みます。発生したエラーは Err オブジェクトで確認します。そのため、エラーが起きる可能性のある処理の直後で Err.Number を確認し、必要な処理を行い、Err.Clear で状態を戻す使い方に向いています。
On Error GoTo ラベル を実行すると、その関数内でエラーハンドラーが有効になります。エラーが発生すると、指定したラベルへ制御が移ります。この方式は、複数行にまたがる処理の後始末や、同じ関数内で共通のエラー処理を行いたい場合に向いています。

ただし、VBAのエラーハンドラーはブロック単位で範囲を指定できません。関数の途中で有効にすると、その後の処理全体に影響します。この性質を理解しないまま使うと、本来は上位や下位で扱いたかったエラーまで、途中の関数が捕まえてしまいます。

したがって、実務では、エラー処理を必要以上に広げないことが重要です。局所的に判定できるものは On Error Resume Next で直後に確認し、関数全体の異常終了をまとめたいときだけ On Error GoTo を使う、という整理が扱いやすくなります。

第1章(VBAのエラー処理は三つに分けて考える)

VBAのエラー処理は、大きく三つの状態で考えると分かりやすくなります。何もしない場合、On Error Resume Next を使う場合、On Error GoTo を使う場合です。

1.1 何もしない場合

On Error を書かない場合、エラーが発生すると、その場で処理が止まります。呼び出し元に有効なエラーハンドラーがあれば、そこへ制御が移ることもあります。

小さな確認用マクロでは、この動きでも問題ありません。しかし、業務マクロでは、ファイルが見つからない、シートが存在しない、入力値が不正である、といったエラーを想定して処理したい場面が多くあります。

1.2 On Error Resume Next

On Error Resume Next は、エラーが発生しても次の行へ進む指定です。処理を止めずに進めるため、使い方を誤るとエラーを見落とします。

一方で、エラーが起きるかどうかを局所的に確認したい場合には便利です。たとえば、存在しない可能性のあるオブジェクトを取得し、直後に Err.Number を確認するような場面です。

この書き方では、エラーが起きる可能性のある処理と、Err.Number の確認を離さないことが重要です。確認が離れるほど、どの処理で発生したエラーなのかが分かりにくくなります。

1.3 On Error GoTo

On Error GoTo は、エラーが発生したときに指定したラベルへ制御を移します。一般に、関数の最後の方にエラーハンドラーを置き、途中でエラーが起きた場合に後始末やメッセージ出力を行います。

この方式は、まとまった処理を一つの単位として扱う場合に便利です。たとえば、ファイルを開き、データを読み込み、最後にファイルを閉じる処理では、途中で失敗しても後始末が必要になります。

ただし、On Error GoTo は関数内の広い範囲に効きます。どこで発生したエラーも同じハンドラーへ流れやすいため、エラーの原因を丁寧に切り分けるには工夫が必要です。

第2章(エラーオブジェクトとハンドラーの状態)

VBAでエラーが発生すると、Err オブジェクトにエラー情報が入ります。On Error 文を実行すると、このエラー状態やエラーハンドラーの設定が、その関数内で更新されます。

2.1 Errオブジェクトは共有された状態に見える

Err.Number、Err.Description などには、直近のエラー情報が入ります。この情報を使って、何が起きたのかを判断します。

注意が必要なのは、Err オブジェクトが処理の途中で上書きされることです。エラー処理中に別のエラーを発生させると、最初の原因が見えにくくなります。

そのため、必要な情報は早めに変数へ退避する、エラー処理の中で不用意に別のエラーを起こさない、という注意が必要です。

2.2 ハンドラーは有効でも常に使えるわけではない

On Error GoTo でエラーハンドラーを指定すると、その関数ではハンドラーが有効になります。ただし、有効であることと、現在使えることは同じではありません。

エラーハンドラーに制御が移って処理中の状態では、そのハンドラーはすでに活性化されています。活性化されたハンドラーの中でさらにエラーが発生した場合、同じハンドラーへもう一度戻るのではなく、呼び出し元方向へ処理が巻き戻されます。

この挙動を理解していないと、エラーハンドラー内のエラーを同じ場所で受けられると誤解してしまいます。

第3章(スタックの巻き戻しを理解する)

VBAでエラーが発生したとき、現在の関数で処理できなければ、呼び出し元へ向かってエラーハンドラーを探します。この動きを、ここではスタックの巻き戻しとして整理します。

3.1 有効かつ活性化されていないハンドラーを探す

エラーが発生すると、VBAは現在の関数から呼び出し元へ向かって、有効なエラーハンドラーを探します。

ただし、見つかったハンドラーがすでに活性化されている場合は、そこでは処理されません。さらに上位の関数へ巻き戻されます。

つまり、エラーを捕まえるのは、単に近いハンドラーではありません。有効であり、なおかつ現在処理中ではないハンドラーです。

3.2 下位関数のエラーが上位の呼び出し行で発生したように見える

関数Aが関数Bを呼び、関数Bの中でエラーが発生したとします。関数Bで処理できなければ、関数Aの呼び出し行でエラーが起きたように扱われます。

この性質により、上位関数のエラーハンドラーから見ると、実際の原因が下位関数の内部にあっても、表面上は関数呼び出し行で失敗したように見えます。

原因を追いやすくするには、下位関数で必要な情報を補足するか、戻り値やエラー情報用の引数で状況を返す設計が必要になります。

第4章(Resumeはリトライに近い)

エラーハンドラー内で Resume を使うと、エラーが発生した行から処理を再開します。Resume Next を使うと、エラーが発生した行の次の行から再開します。

4.1 Resumeは同じ行へ戻る

Resume は、エラーになった処理をもう一度実行したいときに使えます。たとえば、失敗の原因を取り除いた後で、同じ処理をやり直す場合です。

この意味では、Resume はリトライ処理に近いものとして考えると理解しやすくなります。

ただし、原因を取り除かないまま Resume すると、同じエラーを繰り返します。エラーハンドラーの中で値を修正する、ファイルを開き直す、ユーザーに再入力させるなど、再実行して成功する理由が必要です。

4.2 Resume Nextは失敗箇所の次へ進む

Resume Next は、失敗した処理をあきらめて次へ進む場合に使います。後続処理に影響しない失敗であれば、この選択もあります。

ただし、失敗した処理の結果を前提に後続処理が動く場合、Resume Next は危険です。原因を解消せずに進むため、別の場所で分かりにくい不具合を起こすことがあります。

Resume と Resume Next は、エラー処理の中で「戻ってやり直す」のか、「失敗を受け入れて先へ進む」のかを明確に分けるためのものです。

第5章(VBAのエラー処理で起きやすい問題)

VBAのエラー処理には、構造上の扱いにくさがあります。特に、エラー処理の範囲を細かいブロック単位で指定できないことと、連鎖例外のような仕組みがないことが問題になりやすいです。

5.1 途中の関数がエラーを捕まえてしまう

VBAでは、On Error GoTo を設定した関数が、下位関数で発生したエラーも捕まえることがあります。

これは便利でもありますが、設計上は問題にもなります。上位関数と下位関数で協調してエラー処理をしたい場合、途中の関数がすべてのエラーを捕まえてしまうと、処理の意図が分かりにくくなります。

興味のないエラーは再度 Err.Raise すればよい、という考え方もあります。しかし、実務コードでこれを徹底すると、かえって複雑になります。どのエラーを処理し、どのエラーを上位へ流すのかを全関数で丁寧に書く必要があるからです。

5.2 原因をつないで伝えにくい

他の言語では、ある例外を別の例外で包み、原因を保持したまま上位へ伝える仕組みがあります。VBAでは、このような連鎖例外を簡潔に扱う仕組みが弱いです。

Err.Raise で上位へエラーを投げ直すことはできます。しかし、その過程で元のエラー情報を自然に保持し続けるには工夫が必要です。

そのため、VBAでは、下位関数で起きた失敗をそのまま例外として長く運ぶより、関数の戻り値や結果オブジェクト、参照型引数などで状況を返す方が分かりやすい場合があります。

第6章(実務での使い分け)

VBAのエラー処理では、すべてを例外処理として統一しようとするより、処理の性質に合わせて使い分ける方が現実的です。

6.1 局所的に確認するならResume Next

存在確認、変換可否の確認、失敗しても直後で判断できる処理には On Error Resume Next が向いています。

ただし、使う範囲は短くします。エラーが起きる可能性のある処理の直後で Err.Number を見て、必要な対応をしたら Err.Clear を行います。確認し終えたら On Error GoTo 0 で通常の状態へ戻すことも検討します。

Resume Next を広い範囲に置いたままにすると、マクロが失敗しているのに進み続け、原因が後から分からなくなります。

6.2 後始末をまとめるならGoTo

ファイル、外部接続、一時シート、画面更新の停止など、後始末が必要な処理では On Error GoTo が向いています。

この場合、エラーハンドラーでは、原因の表示やログ出力だけでなく、後始末を確実に行うことが重要です。エラー時だけでなく正常終了時にも同じ後始末が必要なら、終了処理の流れを分けておくと読みやすくなります。

6.3 関数内で閉じる設計を基本にする

VBAでは、エラーを上位へきれいに伝搬させる設計が難しくなりがちです。そのため、関数内で判断できるエラーは、できるだけ関数内で閉じる方が扱いやすくなります。

上位へ伝える必要がある場合でも、単に Err.Raise で投げ直すのではなく、戻り値、ステータス、メッセージ、参照型引数など、読み手が追いやすい形で返すことを検討します。

業務マクロでは、例外処理の美しさより、保守担当者が原因を追えることの方が重要です。

まとめ

VBAのエラー処理は、On Error Resume Next と On Error GoTo の二つを覚えるだけでは不十分です。どちらも、関数内のエラー状態とエラーハンドラーの状態を変える指定として理解する必要があります。

On Error Resume Next は、局所的な確認に向いています。エラーが起きる可能性のある処理の直後で Err.Number を確認し、状態を片付ける使い方です。
On Error GoTo は、まとまった処理の後始末や共通処理に向いています。ただし、関数内で広く効くため、予期しないエラーまで捕まえてしまうことがあります。

エラー発生時には、VBAは有効かつ活性化されていないエラーハンドラーを探して、呼び出し元方向へ巻き戻します。エラーハンドラー内でさらにエラーが起きた場合、同じハンドラーでは処理されない点にも注意が必要です。

実務では、エラーを遠くへ運ぶより、関数内で閉じられるものは閉じる、局所的に確認できるものは直後で確認する、上位へ伝える必要があるものは読みやすい戻り値や結果情報で返す、という方針が扱いやすくなります。

VBAのエラー処理は、完璧な例外処理モデルとして使うより、業務マクロを止めるべきところで止め、続けるべきところで続けるための制御手段として設計するのが現実的です。

元記事

この記事は、Dropbox Paperに残っていた過去記事「VBA 例外処理モデル(ぽいもの)」(2019年4月21日、2019年6月17日修正)を原型として、LWP公開記事用に再構成したものです。

取得日: 2026年5月14日

元記事URL: https://www.dropbox.com/scl/fi/v7ngqz1ii17gxzvvpi0ql/VBA.paper?rlkey=gxpat5aqzm7t8mo5l7pfb6n2r&dl=0