MOS VBAエキスパート対策 | エラーへの対処 | MOS Excel VBAエキスパート対策です



最終更新日:2018-03-10

エラーへの対処


・On Error Goto
・On Error Resume Next
・Errorオブジェクトほか


【ここでのポイント】

公式テキストでは、文法エラーと論理エラーについて書かれていますが、
そこはベーシックの出題範囲なので、ここでは省略します。
もし、不安な部分があるようなら、デバッグの基礎 を復習しておいてください。


エラーへの対処は、極めて簡単です。
On Error Goto
On Error Resume Next
どちらかを使います。
そして、
エラー発生の理由は、Errオブジェクトのプロパティを調べるだけです。

たったこれだけです、そして、これ以外には有りません。
にもかかわらず、大項目として試験範囲に列挙されているのには理由があります。

何の対策もしてなければ、マクロ実行でエラーが発生すればマクロは停止してしまいます。

マクロが停止しては困ります。
そもそもマクロは作業を自動化するものなのに、停止してしまってはどうしようもありません。
そこで、エラーへの対処が必要になります。
そしてVBAとしての対処は、上記のとおり難しいものではありません。

本当に難しいのは、エラー発生の可能性を事前に予測することです。
これには経験が必要です。

試験対策としては、
VBAのステートメントはそれほど難しくないのでしっかり覚えることは当然として、
いろいろなエラー発生パターンを実際のVBAコードで体験しておくことです。


On Error Goto

実行時エラーが発生した時に、制御を指定の行ラベルに移動させるものです。

エラーが発生すると、行ラベルの位置に制御が移ります。

このステートメント以降、On Error GoTo 0 が無い限り、プロシージャーの終わりまで有効となります。

Sub Sample
  On Error GoTo Label01
  ・・・
  'ここでエラー発生した場合、Label01に制御が移ります
  ・・・
  Exit Sub
Label01:
  エラー時の処理
End Sub


Label01:
これが、行ラベルです。

行ラベル

ラベル名:

と書きます。

GoToの行先として指定する場所になります。


On Error Resume Next

エラーが発生しても、エラーが発生したステートメントの次のステートメントから実行を継続します。

このステートメント以降、On Error GoTo 0 が無い限り、プロシージャーの終わりまで有効となります。

実行時エラーを発生させたステートメントの直後にあるステートメント、または On Error Resume Next ステートメントを含むプロシージャから最後に呼び出しを行った直後のステートメントを使って、実行を継続します。

Dim i As Long
On Error Resume Next
i = "ABC"
If Err.Number <> 0 Then
  MsgBox Err.Description
  Err.Clear
End If


この場合、メッセージボックスには、
「型が一致しません」と表示されます。

Err.Clearでエラー情報をクリアしています。
クリアしないと、エラー情報はそのまま残っています。

次のエラーが発生したことを判断できるように、エラー処理の後でクリアするようにします。


Errorオブジェクト

Err オブジェクトは、実行時に発生したエラーに関する情報を保有しています。

Errオブジェクトのプロパティとメソッド

Err.Clear すべてのプロパティの設定値をクリアするメソッド
Err.Description エラーに関する簡単な説明
Err.HelpContext ヘルプ ファイルのトピックに対応するコンテキスト番号
Err.HelpFile ヘルプ ファイルへの絶対バス
Err.LastDllError 最後にダイナミック リンク ライブラリ (DLL) を呼び出したときのエラー コード
Err.Number エラーを指定する数値。エラーではない場合は0
Err.Source エラーの発生元のオブジェクトまたはアプリケーションの名前

Number プロパティの値でエラーの原因を判別します。

Err オブジェクトのプロパティの値には、最新のエラーだけが反映されます。

実行時にトラップ可能なエラー番号一覧と対処


On Error Goto 0

現在のプロシージャに含まれる使用可能なエラー処理ルーチンを無効にします。

その時点で有効となっている、
On Error GoTo
または
On Error Resume Next
これらのエラー処理を無効にします。


On Error の有効範囲

On Error GoTo 行ラベル

On Error Resume Next

これらは、このステートメントが実行されて以降、
On Error GoTo 0が出てくるか、
そのプロシージャが終了するまでが有効範囲となります。

On Errorが有効な状態別のプロシージャをCallし、
呼び出されたプロシージャ内でOn Error対応されていないエラーが発生した場合は、
呼び出されたプロシージャはその場で終了します。
呼び出し元のプロシージャに戻ってからは、On Errorの指定に従い動作します。

文章では理解しづらいので、以下のサンプルで確認してください。

Sub test1()
  On Error GoTo Err_Exit
  Call test2 'この中でエラー発生しても、On Error Go Toは有効
  MsgBox "正常終了"
  Exit Sub
Err_Exit:
  MsgBox "異常終了" & vbLf & Err.Description
End Sub

Sub test2()
  Dim i As Long
  On Error Resume Next
  i = "A" 'このエラーは無視
  On Error GoTo 0
  i = 0
  i = i / i 'ここでエラー発生→プロシージャを抜けます
  i = 1 'これは実行されません
End Sub

上記の「test1」の実行結果は、



本来のエラー対応

エラー発生した時のエラー処理を記述する前に、
そもそもエラーが発生しないようにすることが本来のエラー対応です。

ブックの存在確認
Sub sample1()
  Dim sBook As String
  sBook = InputBox("ブック名を入力してください。")
  Workbooks.Open ThisWorkbook.Path & "\" & sBook
End Sub

存在しないブックを開いたときはエラーとなります。



このエラーへの対応は、以下のようにします。

Sub sample2()
  Dim sBook As String
  On Error GoTo Err01
  sBook = InputBox("ブック名を入力してください。")
  Workbooks.Open ThisWorkbook.Path & "\" & sBook
  MsgBox sBook & "を開きました。"
  Exit Sub
Err01:
  MsgBox sBook & "は存在しません。"
End Sub
Sub sample3()
  Dim sBook As String
  On Error Resume Next
  sBook = InputBox("ブック名を入力してください。")
  Workbooks.Open ThisWorkbook.Path & "\" & sBook
  If Err.Number = 0 Then
    MsgBox sBook & "を開きました。"
  Else
    MsgBox sBook & "は存在しません。"
  End If
End Sub

上記の2つのVBAは、どちらも同じことをしています。
On Error GoToとOn Error Resume Nextの違いだけです。

これらは、ブックをOpenしてエラー発生したらメッセージを出しています。

しかし、そもそも存在しないブックを開こうとしていることが間違いです。
ブックOpenの前に、そのファイルが存在するかどうかのチェックをするべきです。

Sub sample4()
  Dim sBook As String
  On Error Resume Next
  sBook = InputBox("ブック名を入力してください。")
  If Dir(ThisWorkbook.Path & "\" & sBook) = "" Then
    MsgBox sBook & "は存在しません。"
  Else
    Workbooks.Open ThisWorkbook.Path & "\" & sBook
    MsgBox sBook & "を開きました。"
  End If
End Sub

Dir関数で、ファイルが存在するか確認し、
存在する場合のみブックOpenしています。

シートの存在確認
Sub sample5()
  Dim sSheet As String
  sSheet = InputBox("シート名を入力してください。")
  Worksheets(sSheet).Select
End Sub

存在しないシートを選択したときはエラーとなります。



このエラーへの対応は、以下のようにします。

Sub sample6()
  Dim sSheet As String
  On Error GoTo Err01
  sSheet = InputBox("シート名を入力してください。")
  Worksheets(sSheet).Select
  MsgBox sSheet & "を選択しました"
  Exit Sub
Err01:
  MsgBox sSheet & "は存在しません。"
End Sub
Sub sample7()
  Dim sSheet As String
  On Error Resume Next
  sSheet = InputBox("シート名を入力してください。")
  Worksheets(sSheet).Select
  If Err.Number = 0 Then
    MsgBox sSheet & "を選択しました"
  Else
    MsgBox sSheet & "は存在しません"
  End If
End Sub

上記の2つのVBAは、どちらも同じことをしています。
On Error GoToとOn Error Resume Nextの違いだけです。

これらは、シートを選択してエラー発生したらメッセージを出しています。

しかし、そもそも存在しないシートを選択していることが間違いです。
シート選択の前に、そのシートが存在するかどうかのチェックをするべきです。

Sub sample8()
  Dim sSheet As String
  Dim sht As Worksheet
  Dim flg As Boolean
  On Error Resume Next
  sSheet = InputBox("シート名を入力してください。")
  flg = False
  For Each sht In Worksheets
    If LCase(sht.Name) = LCase(sSheet) Then
      flg = True
      Exit For
    End If
  Next
  If flg = True Then
    Worksheets(sSheet).Select
    MsgBox sSheet & "を選択しました"
  Else
    MsgBox sSheet & "は存在しません"
  End If
End Sub

For Eachで、ワークシート コレクションを処理しています。
指定のシート名があれば、flgにTrueを入れています。
flgはBoolean変数で、TrueかFalseだけが入るデター型です。

シート名は大文字小文字を区別しないので、
判定時にLCaseで小文字に統一してから判定しています。

シートが存在した場合(flg=True)のみシートを選択するようにしています。

※試験対策としては、これくらいのVBAがすんなり読めるようになっておきましょう。

演算エラー対応の演習
Sub sample11()
  Dim i
  Dim j As Integer
  i = InputBox("データを入力してください")
  j = i + 100
  MsgBox j
  j = 10000 / i
  MsgBox j
End Sub

このマクロを実行した時、
入力した値によっては、以下のエラーが発生します。


計算できない文字列を計算したり、
数値のデータ型変数に文字列を入れた時はエラーとなります。



0で割り算した時はエラーとなります。



データ型の範囲外の数値(Integerに40000等)を入れた時はエラーとなります。




演習として、以下に取り組んでみましょう。

このマクロを、
On Errorでエラー対応してみましょう。
そして、
On Errorを使わずに、エラー発生しないように対応してみしょう。
数値かどうかの判定は、IsNumeric関数を使います。

このエラー対応のVBAが書けることは、スタンダード合格としては最低限のレベルになります。
もし、これが書けないようであれば、もう一度最初から学び直してください。


【業務改善の実務】

VBAコードを見たとき、
エラー対応を考えて書かれているかどうかは直ぐに分かります。
そして、
どのように対応しているかを見れば、その人のVBAスキルがはかれます。
まさに、VBA上級者としては腕の見せ所でもあります。

しかし、
むやみやたらにエラー対応すれば良いというものではありません。
例えば、
シートを扱う時に、毎回シートの存在チェックをする必要があるかという事です。
シートを削除したらマクロが動かなくなることは、誰でもわかることです。
もし、それさえ分からない人が使うブックなら、ブックを保護しておくべきなのです。
従って、本来あるべきシートが存在しているかのチェックをすることの是非は考えるべきです。

Excelでシステムを作る場合は、使用者に最低限のExcel知識を教えるべきであり、
決まりを守って使う事を前提として、マクロ作成することがトータルコストの削減になります。


【本サイト内の関連ページ】





同じテーマ「MOS VBAエキスパート対策」の記事

プロシージャ
イベント
ステートメント(スタンダード)
関数
APIとOLEオートメーション
変数と配列
レジストリの操作
ファイルの操作
ユーザーフォームとメニューの操作
VBAスタンダード試験対策まとめ

新着記事 ・・・新着記事一覧を見る

VBAを定型文で覚えよう|ExcelマクロVBA技術解説(3月26日)
VBAスタンダード試験対策まとめ|MOS VBAエキスパート対策(3月16日)
ユーザーフォームとメニューの操作|MOS VBAエキスパート対策(3月14日)
ファイルの操作|MOS VBAエキスパート対策(3月14日)
ユーザーフォームの各種イベント|Excelユーザーフォーム(3月13日)
レジストリの操作|MOS VBAエキスパート対策(3月12日)
変数と配列|MOS VBAエキスパート対策(3月12日)
Colorプロパティの設定値一覧|VBA技術解説(3月12日)
APIとOLEオートメーション|MOS VBAエキスパート対策(3月11日)
エラーへの対処|MOS VBAエキスパート対策(3月10日)

アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.変数とデータ型(Dim)|ExcelマクロVBA入門
3.マクロって何?VBAって何?|ExcelマクロVBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
6.RangeとCellsの使い方|ExcelマクロVBA入門
7.とにかく書いて見よう(Sub,End Sub)|VBA入門
8.ひらがな⇔カタカナの変換|エクセル基本操作
9.まずはマクロVBAを使う準備|ExcelマクロVBA入門
10.繰り返し処理(For Next)|ExcelマクロVBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
なお、掲載のVBAコードは自己責任で使ってください。万一データ破損等の損害が発生しても責任は負いません。





このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。

本文下部へ

↑ PAGE TOP