初心者のためのExcelマクロ超入門(絶対できるVBA開発)

マクロがまったくわからない人のためにエクセルマクロやVBAについてできるだけわかりやすく書いています。Twitter:@shuhhohhey

初心者のためのExcel(エクセル)マクロVBA入門-エラー処理:On Error Goto

f:id:drumer2sh:20131007120711j:plain
前回はちょっと難しめの内容でしたが、いかがだったでしょうか・・・汗。理解できればちょっとは目からうろこ的な内容なんですよ。。。ほんとは。相変わらず文字多めでお送りしています。

マクロのエラーは大きく2種類!

さて今回はエラー処理についてです。マクロ(プログラム)には大きく分けて2種類のエラーが存在します。

  • プログラムがそもそもに動かないエラー(コンパイルエラー)
  • プログラムが動いてはいるが予期しない処理のエラー(例外)

の2種類があります。1つ1つ説明します。

コンパイルエラー


コンパイルエラーはそもそもにマクロが動きません。マクロのテストであれば、F5を押した段階でまずコンパイルエラーが検知され、エラーがあればその箇所についてエラーメッセージが出て、実行できません。つまり、そもそもにマクロが動かない状態です。例えば以下のコードはF5を押して実行してもコンパイルエラーになります。

Option Explicit

Sub test()

    Sheet1.Cells(i, j).Value = "これはテストです"

End Sub

F5を押すと下の画像のように、「変数が定義されていません」というコンパイルエラーが発生します。

f:id:drumer2sh:20131007120513p:plain

このエラーを直さない限り、マクロは実行できない。つまりプログラムが動かない。ということになります。

変数定義を強制する「Option Explicit」

ここで初めて見るものが出ましたね。「Option Explicit」という物です。プロシージャの外に書かれていますが、これは変数の定義を強制する。というオプションを付ける為に記述するコードです。これを付けると定義していない、変数についてはすべてコンパイルエラーとなります。
これを付けておくと、変数は必ず事前にDimステートメントで定義(作成)しなければいけないので、突然適当に変数を作ることができません。つまりプログラムの可読性が向上するのです。このオプションは是非つけて綺麗なコードを書くように心がけましょう。

例外エラー


さて、やっかいなのはこの例外です。プログラム上は問題ないのですが、ある特別な状況になるとエラーになってしまう物を「例外エラー」と呼んでいます。例えば、以前にやったファイルを開く処理のOpenメソッドですが、書き方はまったく問題なくても、開くファイルが存在しなければ例外エラーが発生します。
実際やってみましょう。以前のコードをそのまま使います。

Sub Sample()

    Workbooks.Open "C:\Test.xls"

End Sub

これです。もちろんコード上の文法や処理などは何も間違っていません。ですが、実際にTest.xlsが存在しない状態でこれを実行すると・・・


f:id:drumer2sh:20131007120515p:plain


このようなエラーが発生して、マクロの実行が中断してしまいます。さて、困りましたね。マクロを使う人がこれを見ても、何が起きたのか?わからないし、下手したら「壊れた!!」と思われるかもしれません。したがって、きちんと使う人が分かるようにメッセージを表示して何が起きたのかをわかってもらうようにしなければいけませんし、マクロもしっかりとその後で終了するようにしないといけません。その為に使うのが表題でも出ている「On Error Goto」です。

例外処理をするOn Error Goto


書き方から書いておきましょう。さっきのファイルを開くSampleプロシージャに以下を追加します。

Sub Sample()
On Error Goto Err

    Workbooks.Open "C:\Test.xls"

    'ちゃんとプロシージャを終了する
    Exit Sub

'エラーになった時の処理がここから始まる
Err:
    'エラーになった時の処理をここに書く
    MsgBox "ファイルが存在しません。処理を終了します。", vbOKOnly + vbExclamation, "ファイルオープンのエラー"
    
End Sub


「On Error Goto 処理ラベル名」は何か例外(エラー)が発生したら処理ラベル名の処理へジャンプ!しなさい。という意味になります。プログラムのGotoは指定した処理へ強制的に移動します。したがってこの場合だと、指定したファイルがない場合は指定した「Err」というラベル以下の処理へジャンプする分けですね。ラベルの名前はなんでもいいですが、On Error Gotoで指定したものと実際に飛ぶ先が同じである必要があります。(当たり前か・・・)
さて、Errラベル以下にはエラーの原因をメッセージ表示して処理を終えています。MsgBoxメソッドは頻繁に利用するので使い方をよくヘルプで確認しておきましょう。ちょっとだけ解説すると、

  • 引数1:表示したいメッセージを入れる
  • 引数2:メッセージボックスのボタンの種類を設定
  • 引数3:メッセージボックスのタイトルを入れる

引数の2番目は例の場合だとOKボタンだけで、警告マークを表示するという意味になります。
vbOkOnlyや、vbExclamationはマクロで初めから定義されている定数です。VBEを使っていれば補完機能で出てきます。ヘルプにも説明があるので確認しましょう。また今回は戻り値を必要としないので上記のような書き方になっています。

実際に実行すると・・・

f:id:drumer2sh:20131007120512p:plain

わかりやすいメッセージが表示されました。これなら、マクロを使う人にもわかりやすいですね。これが例外処理と呼ばれるもので、マクロを組む上でよく忘れがちなんですが「絶対に避けてはいけない」ところです。

エラー処理の重要性


エラー処理はマクロを作成する上では絶対に避けては通れない所です。何が起こったのか?どういうエラーなのか?こういったことをきちんとしないと使う側は混乱しますし、何より「不完全なプログラム」と言わざるを得ません。プログラムはきちんと想定通りに動きべきであって想定外でも想定通りの処理が記述され、処理が終了しなければいけないのです。

なので、どんな例外でもきちんとキャッチするためにOn Error Gotoはプロシージャの最初に書かれているわけです。別にどこに書いてもいいのですが書いた以前の処理で何かあってもそれは検知されません。

はい、みなさん思いましたね。


「うぁ、、めんどくせ」


と。。。そうなんです。エラー処理ってめんどくさいんです。正直忘れてしまう気持ちもよくわかります。よくわかりますが、しかし!絶対に落とせないんです。皆さんもゲームをしてて、突然何かエラーが起きて終了したら「は?」となるでしょ?マクロも同じです。やっぱりマクロを組む以上は、原因不明で落ちる!なんてことはあってはいけないんです。(まぁ実際には結構あるんですが、その場合はシステムエラーって便利な言葉ありますw)
ですから、エラー処理はしっかりと身につけましょう。

ちゃんと終了したければExit Subを忘れずに


実は地味に追加しているコードがあります。それが「Exit Sub」です。プロシージャを終了するコードです。これがないと、どうなるかというと・・・普通にファイルをオープンした後に、Errラベル以下のコードが実行されてしまいます。ちゃんと正常に動いたのにエラーの処理が動いてしまうのは困りますので、Errラベルの前には必ず「Exit Sub」や「End Sub」と言った処理を終了するメソッドを記述しましょう。

エラー処理をしても処理を続けたいんだけど・・・


そういう場合はエラー処理の最後に「Resume Next」文を追加しておきます。

'エラーになった時の処理がここから始まる
Err:
    'エラーになった時の処理をここに書く
    MsgBox "ファイルが存在しません。処理を終了します。", vbOKOnly + vbExclamation, "ファイルオープンのエラー"
    Resume Next    '→これで、エラーが起きた命令文の次からまた実行が始まる。
End Sub

こうすることでエラー処理を実行した後で、エラーの起きた箇所、今回ならOpenメソッドですが、その次の命令文から再度実行が始まります。
ですが、基本的にエラー処理の後は中断が基本だと考えます。この場合ならResume Next文に頼らずにIf文で検証し、メッセージを表示してそれからそのまま次の処理へ移った方がプログラムとして読みやすいですし、プログラムの本来の性質「上から順に実行する」という原則に沿った書き方になります。
Resume Nextを使うと、一旦処理が別のところへ飛んで、また戻ってきて・・・とプログラムが追いにくくなります。
できるだけ使わないようにマクロを組めるように頑張りましょう!


今日はここまで。

かしこ