VBA業務マクロのエラー処理を三層と三分類で設計する
On Error を場当たり的な後始末ではなく、業務継続とUI判断の設計部品として扱う
Copyright © 2026 LWP 山中 一弘
本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。
記事要約
VBAの業務マクロでは、エラー処理が後付けになりやすい。On Error GoTo で最後にまとめて捕まえるだけでは、処理を止めるべきエラー、ユーザーに選ばせれば続行できるエラー、データ検証として通常の戻り値で返すべきエラーが混ざってしまう。
難しいのは、VBAに構造化例外の仕組みがなく、Err オブジェクトと On Error の制御範囲を手続き的に扱う必要がある点である。さらに、業務マクロでは下位関数の途中でUI判断が必要になる場面があり、そこで安易にメッセージボックスを出すと、業務処理、画面操作、再実行制御が一体化してしまう。
この記事では、エラーをA/B/Cの三分類で整理し、UI層、業務層、データ層の三層へ責務を分ける。Err.Raise で止めるべきものと、戻り値構造で返すべきものを分離し、業務継続とユーザー判断を扱えるエラー処理設計へ落とし込む。さらに、8通りの責務配置、状態機械による再開制御、ログ、テスト、命名規約、チーム規約まで含めて、実務で維持できる設計体系としてまとめる。
本記事の対象とゴール
想定読者
Excel VBAで業務マクロを作っていて、エラー処理が毎回ばらつく人
On Error GoTo ErrHandler は書けるが、どこで捕まえるべきかに迷う人
下位関数からメッセージボックスを出す設計に違和感がある人
業務継続、処理中断、ユーザー判断を設計として分けたい人
本記事で得られること
VBAのエラー処理を、例外、業務エラー、継続判断に分けて考えられる。
UI層、業務層、データ層のどこが何を担当するかを決められる。
Err.Raise と戻り値構造を使い分けるための実装方針を持てる。
エラー処理をコード末尾の後始末ではなく、業務マクロの設計項目として扱える。
ログ、テスト、命名、レビュー観点まで含めたエラー処理規約を作れる。
本記事で扱わないこと
VBAの全構文リファレンス
すべてのExcel実行時エラー番号の一覧
特定ブックや特定プロジェクトの個別実装
クラスモジュールを使った大規模フレームワークの完全実装
先に結論
VBAのエラー処理は、すべてを On Error で捕まえる設計では破綻しやすい。
まず、処理不能なものは例外として止める。業務上の不成立は、戻り値構造で返す。ユーザーが選べば続行できるものは、UI層へ判断を返す。
そのうえで、下位関数は画面を出さない。データ層は検出する。業務層は分類する。UI層は通知し、必要なときだけユーザー判断を受け取る。
この分離ができると、VBAでも、例外、エラー、業務継続を混ぜずに扱える。
1. `On Error` だけでは設計にならない
1.1 `On Error` は捕捉手段であって分類ではない
VBAでは、実行時エラーを扱う代表的な構文として On Error GoTo を使う。
ただし、On Error は「エラーが起きたらどこへ飛ぶか」を指定する構文であり、「そのエラーが何を意味するか」は決めてくれない。
ファイルが開けないのか、必須列がないのか、入力値が空なのか、ユーザーがキャンセルしたのか。これらを全部同じ ErrHandler に送ると、最後はメッセージを出して終了するだけの設計になる。
業務マクロでは、それでは足りない。止めるべきエラーと、戻すべきエラーと、ユーザー判断を挟むべきエラーを分ける必要がある。
1.2 `Err` は情報置き場であって責務分離ではない
Err.Number や Err.Description は便利だが、Err に入っている情報だけで設計が整理されるわけではない。
Err は直近のエラー情報を持つ仕組みであり、業務上の意味を持った結果オブジェクトではない。したがって、業務処理の結果として「処理成功」「業務上の不成立」「ユーザー判断待ち」を返したい場合は、Err とは別に戻り値構造を用意したほうが読みやすい。
Err は、予期しない実行時エラーや、処理を中断すべき例外を上位へ伝えるために使う。業務上の判定結果をすべて Err に詰め込むと、正常な分岐と異常系の分岐が混ざる。
1.3 下位関数でUIを出すと再利用できなくなる
業務マクロでは、処理中に「このまま続けますか」「この行はスキップしますか」「別ファイルを選び直しますか」といった判断が必要になる。
ここで下位関数が直接 MsgBox を出すと、その関数はUIと結びつく。単体テストもしにくくなり、別の画面や別の呼び出し元から再利用することも難しくなる。
下位関数は、ユーザーに聞くのではなく、「判断が必要である」という結果を返す。UI層がその結果を受け取り、ユーザーへ通知し、選択結果を業務層へ戻す。このほうが、処理の責務が明確になる。
2. エラーをA/B/Cの三分類で見る
2.1 A: 致命的なシステムエラー
Aは、処理を継続できない構造的な失敗である。
たとえば、ファイルを開けない、必要なシートが存在しない、アクセス権がない、想定外の実行時エラーが発生した、といった状態である。
この種のエラーは、下位で握りつぶしてはいけない。業務層で補足情報を付け、最終的にはUI層または最上位の実行入口で捕捉して、処理を止める。
2.2 B: 致命的な業務エラー
Bは、プログラム自体は動いているが、業務処理として成立しない状態である。
たとえば、必須項目がない、金額と明細が一致しない、登録対象として扱えないデータである、といった状態である。
Bはシステム障害ではない。しかし、そのまま登録や転記を続けると、誤った成果物を作る。したがって、業務層で「処理不能」と分類し、上位へ返すか、例外として止める。
2.3 C: 継続可能な業務エラー
Cは、業務上は注意が必要だが、判断によって処理を続けられる状態である。
たとえば、重複候補がある、任意項目が空である、警告を出したうえでスキップできる、ユーザーが確認すれば続行できる、といった状態である。
Cをすべて例外として止めると、業務マクロは使いにくくなる。一方で、何も聞かずに続行すると危険である。Cは戻り値構造として返し、UI層で判断を受け取り、業務層が次の処理を決めるのがよい。
3. 三層で責務を分ける
3.1 データ層は検出する
データ層は、ファイル、シート、セル、配列、辞書、テーブルなど、処理対象に近い場所で異常を検出する。
ここで重要なのは、データ層が「表示」まで担当しないことである。データ層は、存在しない、型が違う、値が不正である、といった事実を検出する。どう通知するか、続行するか、ユーザーに聞くかは、上位の責務である。
3.2 業務層は分類する
業務層は、データ層から上がってきた状態をA/B/Cへ分類する。
同じ「値が空」でも、必須項目ならB、任意項目ならC、そもそも列が存在しないならAになりうる。この判断は、データ層だけでは決められない。業務ルールを知っている層が分類する必要がある。
業務層は、分類した結果を戻り値構造にして返すか、処理不能として Err.Raise で上位へ投げる。
3.3 UI層は通知し、判断を受け取る
UI層は、ユーザーへ通知し、必要な判断を受け取る。
ただし、UI層が業務ルールを全部持つわけではない。UI層は「何を表示するか」「どの選択肢を出すか」「選択結果をどう返すか」を担当する。選択結果を受けて、スキップする、再試行する、中断する、といった処理方針は業務層が決める。
この分離により、業務ロジックは画面に依存しにくくなる。あとからメッセージボックスをフォームに変える、ログ出力を追加する、テスト用の疑似UIに置き換える、といった変更もしやすい。
4. `Err.Raise` と戻り値構造を使い分ける
4.1 止めるものは `Err.Raise` で上げる
Aのように処理継続できないものは、例外として上げる。
VBAでは、構造化例外のような仕組みはないが、Err.Raise により上位の On Error GoTo へ伝播させることはできる。下位で捕まえた場合も、必要な文脈を付けて再送出する。
次のコードは概念例である。実際のエラー番号体系はプロジェクトごとに決める。
Private Sub RaiseFatal(ByVal sourceName As String, ByVal message As String) Err.Raise vbObjectError + 1000, sourceName, messageEnd Sub大事なのは、下位でエラーを消さないことである。処理不能な状態を握りつぶすと、上位は成功したものとして次へ進んでしまう。
4.2 業務上の分岐は戻り値で返す
BやCの一部は、例外ではなく処理結果として返したほうがよい。
たとえば、入力行の検証で「必須項目がない」と分かった場合、その行をエラー一覧に積み、全件検査を続けたいことがある。この場合、毎回 Err.Raise で止めると、検査処理として扱いにくい。
戻り値構造を使えば、成功、業務NG、ユーザー判断待ち、中断を同じ型で返せる。
Public Enum ProcStatus ProcStatusOk = 0 ProcStatusNg = 1 ProcStatusNeedDecision = 2 ProcStatusAbort = 3End EnumPublic Type ProcResult Status As ProcStatus Value As Variant ErrorNumber As Long Message As String DecisionKey As StringEnd Typeこのような戻り値を用意すると、呼び出し元は Status を見て、成功処理、警告表示、ユーザー判断、中断を分けられる。
4.3 `On Error` は入口と境界で使う
On Error は、あらゆる行に散らすより、入口と境界で使うほうがよい。
具体的には、公開Sub、ファイルI/O、外部アプリ操作、配列や辞書の境界処理、変換処理など、失敗しうる境界に置く。
小さな純粋関数や単純な判定関数まで全部 On Error で包むと、どこで何を守っているのかが分からなくなる。エラー処理は多ければよいのではない。失敗の意味が変わる境界で入れる。
5. 8パターンで責務配置を検討する
5.1 8パターンは全採用候補ではなく、設計検討の地図である
A/B/Cの三分類を、UI層と業務層のどちらで主に処理するかを考えると、理屈上は8通りの責務配置が生じる。
A/B/CをすべてUI層で処理する。
A/BをUI層で処理し、Cを業務層で処理する。
A/CをUI層で処理し、Bを業務層で処理する。
B/CをUI層で処理し、Aを業務層で処理する。
AだけをUI層で処理し、B/Cを業務層で処理する。
BだけをUI層で処理し、A/Cを業務層で処理する。
CだけをUI層で処理し、A/Bを業務層で処理する。
A/B/Cをすべて業務層で処理する。
この8パターンは、「どれも同じように選べる」という意味ではない。実務では、責務の置き場所を考えるための地図として使う。
危険なのは、A/B/Cの意味を決めないまま、近くにある層で処理してしまうことである。下位関数でメッセージを出す、上位Subで業務判定を全部持つ、業務層でユーザーの選択肢文言まで決める、といった設計は、この地図で見ると責務が混ざっている。
5.2 実務の基本形は「A/Bは止める、Cは選ばせる」である
実務では、A/B/Cを次のように扱うと安定しやすい。
Aは処理不能として上位へ上げ、最上位入口で止める。
Bは業務処理として不成立であり、業務層で分類したうえで上位へ返すか、必要なら止める。
Cはユーザー判断を挟めば続行できるため、戻り値構造でUI層へ判断要求を返す。
ここでいう「UI層で処理する」とは、UI層が業務ルールを持つという意味ではない。UI層は通知し、選択肢を提示し、選択結果を返す。業務ルール上どの選択肢を許すか、選択後に何をするかは、業務層で決める。
したがって、推奨形は「A/Bは上位で止めるまたは通知する、Cは業務層が判断要求として返し、UI層が選択を受け取る」である。
5.3 すべて業務層で処理する方式は強く見えるが閉じすぎる
A/B/Cをすべて業務層で処理すると、一見すると業務層が強くなり、UI層が薄くなる。
しかし、業務層の中で通知、判断、再試行、スキップ、中断まで抱えると、結局は業務層がUIに依存する。メッセージボックス、フォーム、ログ、実行入口の都合が業務層へ漏れ込む。
業務層は分類と制御方針を持つ。UI層は通知と入力を持つ。この境界を崩すと、後からUIを差し替えるときに、業務ロジック全体を直すことになる。
5.4 すべてUI層で処理する方式は薄く見えるが業務ルールが漏れる
A/B/CをすべてUI層で処理すると、下位関数は単純になる。
ただし、UI層が「このエラーは止める」「このエラーは警告だけ」「このエラーはスキップ可能」と決め始めると、業務ルールがUI層へ流れる。
画面側が業務ルールの中心になると、バッチ実行、テスト、別画面からの再利用が難しくなる。UI層に置いてよいのは、表示と選択受付である。業務上の意味づけは、業務層へ戻す。
6. UI判断を処理途中へ混ぜない
6.1 ユーザー判断は結果として返す
下位関数でユーザー判断が必要になったときは、直接UIを出すのではなく、判断要求を戻り値として返す。
たとえば、重複候補が見つかった場合、下位関数は「重複候補がある」「選択が必要である」「候補IDはこれである」と返す。UI層はそれを表示し、選択結果を業務層へ渡す。
この設計にすると、業務処理は「判断が必要な状態」を扱えるようになる。UIの種類が変わっても、業務ロジックの中心を作り直さずに済む。
6.2 VBAには本当のyieldがない
処理途中でUIに戻し、あとから同じ場所へ再開するような設計は、VBAでは簡単ではない。
そのため、複雑な再開を無理に作るより、処理状態を外へ出し、「次に何をするか」を明示した状態遷移として扱うほうが安定する。
単純なマクロであれば、判断が必要になった時点でいったん結果を返し、UI層で選択を受け取り、次の処理を呼び直す。複雑なマクロであれば、処理状態を表す値を持ち、状態ごとに次の関数へ進める。
6.3 コールバック注入は最終手段にする
UI判断関数を引数として渡す、関数名を渡して動的に呼ぶ、クラスに判断メソッドを持たせる、といった設計も可能である。
ただし、VBAで動的呼び出しを多用すると、追跡性が落ちる。呼び出し先が文字列になり、検索しにくくなり、実行時まで間違いに気づきにくい。
まずは、戻り値で判断要求を返す設計を標準にする。コールバック注入は、処理の途中でどうしてもUI判断を差し込みたい場合だけ使う。
6.4 複数判断は選択肢を標準化して返す
UI判断は、単純なYes/Noだけでは済まない。
実務では、続行、スキップ、再試行、ファイル選び直し、中断、詳細確認など、複数の選択肢が出る。これを毎回文字列で処理すると、分岐が散らばる。
判断要求を返すときは、選択肢をEnumや定数で標準化する。
Public Enum UserDecision UserDecisionNone = 0 UserDecisionContinue = 1 UserDecisionSkip = 2 UserDecisionRetry = 3 UserDecisionAbort = 4End EnumUI層は、ユーザーの操作をこの値へ変換する。業務層は、この値を受け取って次の状態を決める。
6.5 中断とスキップを混同しない
業務継続設計では、中断とスキップを分ける。
中断は、処理全体を止めることである。スキップは、対象の一部を処理せず、次へ進むことである。
たとえば、1行のデータが不正な場合、行単位の処理ならスキップできることがある。しかし、ヘッダー構造が壊れている場合は、全体を中断すべきである。
この区別を戻り値構造に入れておくと、UI層で「キャンセル」と表示された結果が、業務上は中断なのか、対象スキップなのかを明確にできる。
7. 実装テンプレートの考え方
7.1 最上位Subは捕捉と通知を担当する
最上位の実行入口では、予期しない例外を捕捉し、ユーザーへ通知し、ログが必要なら記録する。
Public Sub RunImport() On Error GoTo FatalError Dim result As ProcResult result = ImportCore() Select Case result.Status Case ProcStatusOk MsgBox "処理が完了しました。", vbInformation Case ProcStatusNg MsgBox result.Message, vbExclamation Case ProcStatusNeedDecision HandleDecision result Case ProcStatusAbort MsgBox "処理を中断しました。", vbInformation End Select Exit SubFatalError: MsgBox Err.Description, vbCriticalEnd Subここで重要なのは、最上位Subが業務の細部を判定しないことである。最上位Subは、業務層から返ってきた結果を見て、通知と判断受付を行う。
7.2 業務関数は分類して返す
業務関数は、データ層から返った状態を見て、処理を続けるか、業務NGとして返すか、ユーザー判断が必要かを決める。
Private Function ImportCore() As ProcResult On Error GoTo FatalError Dim result As ProcResult If Not SourceExists() Then result.Status = ProcStatusNg result.Message = "入力元が見つかりません。" ImportCore = result Exit Function End If If HasDuplicateCandidate() Then result.Status = ProcStatusNeedDecision result.Message = "重複候補があります。" result.DecisionKey = "DUPLICATE_ROW" ImportCore = result Exit Function End If result.Status = ProcStatusOk ImportCore = result Exit FunctionFatalError: Err.Raise Err.Number, "ImportCore", Err.DescriptionEnd Functionこの形にすると、業務関数は画面を出さない。画面を出すのはUI層である。業務関数は分類と結果返却に集中する。
7.3 データ関数は事実を返す
データ関数は、業務判断を持ちすぎない。
入力元が存在するか、列が存在するか、値を読めるか、変換できるか。こうした事実を返す。データ関数が「この業務では中断すべき」と決め始めると、業務ルールが下位へ漏れる。
下位で起きた実行時エラーは、必要に応じて Err.Raise で上げる。通常の検査結果は、Boolean、Enum、または結果構造で返す。
7.4 状態機械型のテンプレートを使う
UI判断を挟んで処理を再開する場合、処理途中のローカル変数に依存したまま再開しようとすると破綻しやすい。
再開が必要な処理では、状態を明示する。たとえば、入力確認、重複確認、ユーザー判断待ち、登録、完了という段階を状態として持つ。
Public Enum ImportState ImportStateStart = 0 ImportStateCheckInput = 1 ImportStateNeedDecision = 2 ImportStateRegister = 3 ImportStateDone = 4End Enum状態を外へ出すと、UI層は「いま何待ちか」を理解できる。業務層は、前回の状態とユーザー判断を受け取り、次の状態へ進められる。
これは本物の yield ではない。しかし、業務マクロでは、処理を段階に分けて再呼び出しできるだけで、十分に扱いやすくなる。
7.5 例外のラップは文脈を足すために使う
下位で発生した例外を上位へ送るとき、単に Err.Number と Err.Description をそのまま投げ直すだけでは、どの業務処理で失敗したかが分かりにくい。
再スローやラップを使う目的は、エラーを隠すことではない。文脈を足すことである。
業務層で再スローするなら、処理名、対象、分類、補足メッセージを付ける。逆に、元のエラー番号や説明を消してしまうと、原因調査が難しくなる。
8. レビューで見るべきポイント
8.1 エラー分類がコードに出ているか
レビューでは、エラー処理の有無だけを見ても足りない。
次を確認する。
A/B/Cのどれなのかが分かるか
例外として止めるものと、戻り値で返すものが分かれているか
ユーザー判断が必要な状態を、UI層へ返しているか
下位関数が直接メッセージを出していないか
Err.Raise で上げ直すとき、どの関数で起きたかが分かるか
8.2 `On Error Resume Next` が狭く使われているか
On Error Resume Next は、使ってはいけない構文ではない。
ただし、使う範囲を狭くする必要がある。存在確認、オブジェクト取得、外部アプリ接続の一部など、失敗を直後に検査する場合に限る。
On Error Resume Next を広い範囲に置いたままにすると、本来止めるべきエラーまで通過する。使った後は、すぐに Err.Number を確認し、必要なら On Error GoTo 0 または通常のエラー処理へ戻す。
8.3 ログは分類と一緒に残す
ログを残すなら、単に Err.Description を保存するだけでは弱い。
最低限、次を残すとよい。
エラー分類
発生した処理名
対象ファイル、シート、行番号などの文脈
ユーザー判断があった場合の選択結果
再試行、スキップ、中断の結果
ログは後から原因を追うためのものなので、画面に出したメッセージと同じ文章だけでは不足する。
8.4 命名で責務が見えるか
エラー処理設計は、関数名にも出る。
たとえば、ImportData、ValidateInput、ReadSource、AskContinue は、それぞれ責務が違う。名前が曖昧だと、どの関数が検出し、どの関数が分類し、どの関数がユーザー判断を扱うのかが見えない。
検証だけをする関数には、Validate や Check を使う。処理を実行する関数には、Do、Run、Import、Register などを使う。ユーザーへ聞く関数には、Ask や Prompt を使う。
命名規約は飾りではない。関数ツリーを見たとき、エラー発生責任と通知責任を追えるようにするための道具である。
8.5 `On Error` の多重定義で構造が崩れていないか
VBAでは、プロシージャ内の On Error の状態が手続き的に切り替わる。
そのため、途中で On Error Resume Next を使い、そのまま通常処理へ戻ると、後続のエラーが見えなくなる。逆に、On Error GoTo ErrHandler を広く置きすぎると、どの行の失敗なのかを追いにくくなる。
レビューでは、On Error の開始位置、解除位置、再設定位置を見る。失敗を許容する短い範囲と、処理全体を守る範囲を混同しない。
9. ログとテストを設計に含める
9.1 ログはUI通知とは別に設計する
ユーザーへ出すメッセージと、開発者や運用者が見るログは目的が違う。
ユーザー向けメッセージは、何が起きたか、次にどうすればよいかを短く伝える。ログは、あとから原因を追えるように、分類、処理名、対象、入力値、行番号、再試行結果を残す。
UI層で例外を捕捉したとき、どこでログを出すかを決めておく。最上位Subでまとめて記録するのか、業務層で文脈を付けて記録するのかを混ぜない。
9.2 戻り値分岐はテストしやすい
戻り値構造でエラーを返す設計は、テストしやすい。
Status が Ok のとき、Ng のとき、NeedDecision のとき、Abort のときで、期待する次の処理を確認できるからである。
一方、下位関数が直接メッセージボックスを出す設計では、テストが難しい。UIを出さずに業務関数を呼び、戻り値だけを検査できる構造にしておくと、エラーケースを網羅しやすくなる。
9.3 UI判断はモックできる形にする
UI判断を含む処理をテストするには、実際の画面を出さずに選択結果を返せる必要がある。
単純な設計なら、UI層へ判断要求を返し、テストではその結果を直接与える。より複雑な設計なら、判断関数や判断オブジェクトを差し替えられる形にする。
重要なのは、業務層が MsgBox の戻り値に直接依存しないことである。業務層が依存するのは、標準化された判断結果である。
9.4 パターン別のテストリストを作る
エラー処理のテストは、正常系だけでは足りない。
最低限、次を確認する。
Aの例外が最上位で捕捉される。
Bの業務エラーが処理不能として返る。
Cの判断要求がUI層へ返る。
ユーザーが続行を選んだとき、次の状態へ進む。
ユーザーがスキップを選んだとき、対象だけを飛ばす。
ユーザーが中断を選んだとき、全体を止める。
ログに分類、処理名、対象が残る。
このテストリストがあると、エラー処理が「書いてある」だけでなく、「期待した分岐として動く」ことを確認できる。
10. 設計規約としてチームへ広げる
10.1 共通規約がないと関数ごとに流儀が変わる
業務マクロのエラー処理は、個人ごとの癖が出やすい。
ある関数は Err.Raise、別の関数は戻り値、別の関数はメッセージボックス、別の関数は何も返さない、という状態になると、呼び出し側が毎回読み直さなければならない。
チームや長期保守を考えるなら、次を共通規約にする。
A/B/Cの分類名
戻り値構造
ユーザー判断のEnum
例外番号の範囲
ログ項目
関数命名
レビュー観点
10.2 既存マクロには段階的に入れる
既存マクロを一度に全部直す必要はない。
まず、最上位入口の捕捉と通知をそろえる。次に、戻り値構造を作る。次に、下位関数の直接UI表示を減らす。最後に、ログとテストを足す。
この順序であれば、既存マクロを壊しにくい。設計方針だけを先に決め、実装は変更しやすい場所から進める。
10.3 レビューではコード量より分岐の意味を見る
エラー処理を入れると、コード量は増える。
ただし、見るべきなのは行数ではない。どの分岐がAで、どの分岐がBで、どの分岐がCなのか。どこで止まり、どこで返し、どこで選ばせるのか。ログとテストで追えるのか。
この観点でレビューすると、エラー処理は単なる後始末ではなく、業務マクロの設計品質そのものになる。
11. 実務での採用順序
11.1 まず最上位入口をそろえる
既存マクロへ導入する場合、最初から全関数を書き換える必要はない。
まず、実行入口のSubをそろえる。最上位で予期しない例外を捕捉し、業務層からの戻り値を Select Case で処理する形にする。
ここがそろうと、処理の終了、警告、ユーザー判断、中断の表示が統一される。
11.2 次に戻り値構造を決める
次に、処理結果を表すEnumやTypeを決める。
名称はプロジェクトごとに異なってよい。ただし、意味は統一する。成功、業務NG、判断待ち、中断の区分が揺れないようにする。
戻り値構造が決まると、各関数は「失敗したら何を返すか」を統一できる。
11.3 最後に下位関数からUIを取り除く
最後に、下位関数から直接のUI表示を減らしていく。
すぐに全部なくす必要はない。まず、データ層や業務層の中にある MsgBox を見つけ、戻り値構造へ置き換えやすいものから移す。
この作業は、単なるリファクタリングではない。業務処理とUI判断の境界を明確にする設計作業である。
まとめ
VBAのエラー処理は、構文の知識だけでは安定しない。
On Error、Err、Err.Raise は道具である。どのエラーを止め、どのエラーを戻し、どのエラーをユーザー判断へ渡すかは、設計として決める必要がある。
実務では、A/B/Cの三分類と、UI層、業務層、データ層の三層分離を先に決めるとよい。データ層は検出する。業務層は分類する。UI層は通知し、判断を受け取る。
この形にすると、VBAでも、場当たり的なエラー処理から、業務継続を支えるエラー処理設計へ進める。
出典メモ
本記事は、VBAのエラー処理、UI判断、業務継続設計に関する内部DOCX素材4件を統合し、公開記事として再構成したものです。
記事化にあたり、個別プロジェクト名、個別モジュール名、個別定数名は一般化しました。追加資料に含まれていた、例外通知の8パターン、状態機械、複数判断、ログ、テスト、命名、チーム規約の論点を本文へ統合しました。
