このサイトの記事内では「アフィリエイト広告」などの広告を掲載している場合があります。
消費者庁が問題としている「誇大な宣伝や表現」とならないよう配慮しコンテンツを制作しておりますのでご安心ください。
問題のある表現が見つかりましたらお問い合わせよりご一報いただけますと幸いです。

【VBA】エラーハンドリングの基本(サブプロシージャからエラーを投げる)

今回はVBAの上級テクニックを紹介します。

サブプロシージャからエラーを投げて、メイン処理を中止させる方法です。

図にするとこのような状況です。

メインプロシージャがサブプロシージャを呼び出ししていたのだが、サブプロシージャの実行中に問題があると判明したときです。
例えば、サブプロシージャでセルの値を読み込んだけれど、数字のはずの値が実は文字列だったなど。

こうしたとき、エラーメッセージを表示して処理を中止させたいです。

しかし、サブプロシージャ上でExit Subとしても、それはサブプロシージャが終了するだけでメインプロシージャの処理は継続してしまいます。

そのため、サブプロシージャにExit Subではない方法を組み込んで、メインプロシージャを終了させる必要があります。

今回説明するのは、こうしたときに使えるテクニックです。

VBAが難しいと感じたら
ココナラにてVBAの作成依頼を受け付けています。
ご依頼・ご相談はこちらから

[微妙な方法]サブプロシージャをFunctionにしてBooleanを返す

最初に、エラーハンドリングを使わない微妙な方法を紹介します。

具体的には、サブプロシージャ内で問題が起こったときには、サブプロシージャがBoolean(False)を返す方法です。

Sub MainProcedure()
    Dim isSuccess As Boolean
    
    ' サブプロシージャを実行
    isSuccess = ProcessData(Range("A1"))
    
    ' 結果を判定
    If isSuccess = False Then
        MsgBox "エラー: A1セルの処理に失敗しました。処理を中断します。", vbExclamation, "エラー"
        Exit Sub
    End If
    
    ' 正常時の処理
    MsgBox "A1セルの処理が正常に完了しました。", vbInformation, "成功"
    
End Sub

Function ProcessData(targetCell As Range) As Boolean
    ' 目的の処理: A1セルの値を2倍にする
    If IsNumeric(targetCell.Value) Then
        targetCell.Value = targetCell.Value * 2
        ProcessData = True  ' 成功
    Else
        ProcessData = False ' 失敗
    End If
End Function

サンプルプログラムとしてはこのようになります。

サブプロシージャ(ProcessData)はA1セルが数値でないときは、Falseを返します。

メインプロシージャはTrueなら処理を継続して、FalseならExit Subするようになっています。

処理自体はうまくいくのですが、このコードは読み返すとなかなか分かりづらくなります。

サブプロシージャ(ProcessData)はBooleanを返すのですが、なぜBooleanを返すのか、ぱっと見で分かるでしょうか?

もし、未来の自分が(もしくは他人が)読んだらきっと分からないと思います。

なので、この書き方をするならBooleanの意味をコメントする必要が出てきます。

読みやすいプログラムという観点では、これはあまりいいやり方とは言えません。また、返り値をBooleanにしてしまうと、他の本来返したい値を設定することができません。

そこで、Booleanを使わない、別のテクニックが必要になってくるのです。

エラーハンドリングの基本(サブプロシージャからエラーを投げる)

良い方法はサブプロシージャにエラーを投げさせる、というテクニックです。

Sub MainProcedure()
    On Error GoTo ErrorHandler ' エラーハンドラを設定

    ' サブプロシージャを実行(エラーが発生した場合は自動的にエラーハンドラへ)
    ProcessData Range("A1")

    ' 正常終了時の処理
    MsgBox "A1セルの処理が正常に完了しました。", vbInformation, "成功"
    Exit Sub

ErrorHandler:
    ' 独自のエラー 1001 をキャッチ
    If Err.Number = 1001 Then
        MsgBox "エラー: " & Err.Description, vbExclamation, "処理エラー"
    Else
        MsgBox "予期しないエラーが発生しました。" & vbCrLf & "エラー番号: " & Err.Number & vbCrLf & "詳細: " & Err.Description, vbCritical, "システムエラー"
    End If
    Err.Clear
End Sub

Sub ProcessData(targetCell As Range)
    ' 目的の処理: A1セルの値を2倍にする
    If Not IsNumeric(targetCell.Value) Then
        Err.Raise 1001, "ProcessData", "A1セルの値が数値ではありません。"
    End If

    targetCell.Value = targetCell.Value * 2 ' 数値なら処理を実行
End Sub

サンプルプログラムとしてはこのようになります。

先ほどと違い、サブプロシージャ(ProcessData)はA1セルが数値でないときに、エラーを投げます。

    If Not IsNumeric(targetCell.Value) Then
        Err.Raise 1001, "ProcessData", "A1セルの値が数値ではありません。"
    End If

エラーを投げているのは、この部分で、Err.Raiseというのがエラーを投げる専用のメソッドです。

セルの値が数字出ない場合は、エラーを投げます。

そして、メインプロシージャにはOn Error GoToを宣言しているため、エラーが起こるとエラーハンドラ(エラーを処理する部分)に処理が飛ばされます。

この2つの組合せによって、エラー処理を完了させているのです。

イメージとしては、サブプロシージャがピッチャーで、メインプロシージャがキャッチャーみたいな感じですね。

この方法を使えば、Err.Raiseと書かれているのを見るだけでエラー処理が含まれるのだなと判断が付きます。

メインプロシージャも、On Error GoToを見ただけでおおよその処理が想像できます。

ぱっと見では理解できないかもしれませんが、慣れるととても分かりやすい方法なので活用してみて下さい。

サンプルプログラムはきれいに書いたため、一旦これをコピーして、プロシージャ名などだけ差し替えて使ってもらっても大丈夫です。

エラーを投げるErr.Raiseメソッドについては、詳しくはこちらの記事を参照ください

《VBA上級者になりたい人へ》
VBA上級者を目指したい人にはパーフェクトExcel VBA一択です。
この本を読み切れば間違いなくVBA上級者になれます。

created by Rinker
技術評論社
¥3,608 (2025/04/01 14:41:38時点 Amazon調べ-詳細)
VBAが難しいと感じたら
ココナラにてVBAの作成依頼を受け付けています。
ご依頼・ご相談はこちらから

VBA

Posted by やろまい