■エラーの可能性前回、エラー処理のひとつの例として、エラーが発生してもそれを無視して実行を続ける方法を解説しました。
ゲームの処理に限ったことではありませんが、エラーが発生してプログラムが止まってしまうことは望ましくありません。しかし、エラーが絶対に発生しないプログラムというのは、実際ほとんど無いというのが現実です。
これは、プログラムの実行される環境による影響や、ユーザーの不適切な操作など、プログラムにとっての危険因子がパソコンにはたくさんあるからです。
だとすれば、我々開発者側がやらなくてはならないこととはなんでしょうか。
それは、
エラーの発生を予測し、あらかじめ対応策を講じておくということに尽きます。こんなエラーが起きる可能性があるな、と予測できるなら、それに対して何らかの対処をしておく必要があるのです。
今回はエラー処理に関する具体的な内容を解説していきます。じっくりと取り組み、確実にひとつひとつ理解していきましょう。
■コードが実行される順序VBAでは、原則として記述されたコードが上から順番に実行されていきます。これは今更言わなくてもイメージできると思います。
しかし、VBAには『コードは上から実行』という原則を、あえて破ってしまう記述方法が用意されています。それが『
GoTo
文 』です。
GoTo
文を用いると、同じプロシージャの中であれば、どこでも好きなところにコードの実行を移行することができます。例えば次のような例を見てみましょう。
Sub GoTo_Test()
Dim L As Long
L = Int(Rnd * 10)
If L < 5 Then
GoTo 1 '①
End If
Exit Sub '②
1 '③
MsgBox "取得した乱数は5より小さい"
End Sub
このコードを実行すると、一定の確率でメッセージが表示されます。どのような仕組みになっているのか、なんとなくコードから想像がつくでしょうか。
まず、一番最初に、変数 L に乱数を取得していますね。
L = Int(Rnd * 10)
この一文によって、変数 L には、0~9までのいずれかの整数が入ります。このコードに関する詳しい説明は乱数の解説でやりましたね(
Chapter12を参照)。
そして次に、この取得した乱数の値によって、
If
文で処理が分岐します。
もしも、取得した乱数が 5 よりも小さい値だった場合には、①の部分に処理が進みます。
①には、次のように書かれています。
GoTo 1
『
GoTo
』に続けて、『 1 』と記述されています。ここで登場した『 1 』は、『
行番号 』と呼ばれます。
このように
GoTo
文に続けて行番号を指定すると、強制的に指定された行にコードの実行が移ります。今回の場合は③の部分にもやはり『 1 』と書かれていますね。この③のところにある 1 が、行番号です。
ですから、今回のコードは次のような感じで処理されます。
変数 L に乱数を取得
▼
もし変数 L の値が 5 よりも小さい値だった場合は
If
文による分岐処理で GoTo
文が実行される
▼
GoTo
文の効果で行番号 1 へコードの実行が移る
▼
行番号 1 以降のコードが実行される(メッセージを表示)
行番号をあらかじめ指定しておけば、強制的にコードの実行箇所を移行させることができるわけですね。
一見すると非常に便利な
GoTo
文ですが、注意すべきこともあります。
基本的に行番号は、それ単体でコードの実行に対して何か影響を与えることはありません。あくまでも
GoTo
文とセットで意味をなすものです。ですから、②の部分で示したように、行番号以降のコードが必要ない場合は、明示的にプロシージャを終了するなり、何かの対処をしておく必要があります。
もし仮に次のようにコードを記述してしまうと……
Sub GoTo_Test()
Dim L As Long
L = Int(Rnd * 10)
If L < 5 Then
GoTo 1
End If
1
MsgBox "取得した乱数は5より小さい"
End Sub
これだと、取得した乱数がどんな数値であっても、
絶対にメッセージが表示されます。行番号は、それ単体では何の意味も持たないのです。注意しましょう。
■行ラベル行番号の変わりに、
行ラベルを使うこともできます。
行ラベルは、行番号に比べて、人間から見たときに意味がわかりやすいです。先ほどのコードを、行ラベルを使って書き直してみます。それがこれ。
Dim L As Long
L = Int(Rnd * 10)
If L < 5 Then
GoTo JAMP
End If
Exit Sub
JAMP:
MsgBox "取得した乱数は5より小さい"
End Sub
簡単ですね。数字が文字に変わっただけです。
ただ、行ラベルを使う場合は、行ラベルの末尾にコロン『これ ⇒ : 』をつけることになっています。使い方は行番号と全く同じです。
そして、行番号を使うにしても、行ラベルを使うにしても、
GoTo
文に関して絶対に理解しておくべきことがあります。
それは、『できるだけ使うな』です。
さんざん説明するだけしといてこんなこと言うのもなんですが、行番号や行ラベルを使うと、コードのどこからでも、好きなときに好きな場所へ強制的にコードの実行を移すことができます。
これは非常に便利に思えますが、一般に、
GoTo
文はできるだけ使わないことが推奨されます。なぜなら、コードの全体像がつかみにくくなる上、デバッグが難しくなるからです。
バグが起きて修正しようとしているときに、コードの実行があっちへ行ったりこっちへ行ったりすると、いったいどこがバグの原因なのか究明が難しくなります。あとから自分でコードを見直した際にも、何をやろうとしているのかわからなくなることが出てくるでしょう。
他人がコードを見た場合にも、同様のことが起こります。そしてプログラムが大きくなればなるほど、構造を把握するのが難しくなります。十分に注意するようにしましょう。
■やっとエラー処理さて、ちょっと長くなりますが、一気に行きます。
先ほど登場した
GoTo
文は、任意の場所に、自由にコードの実行を移すことができます。ここまでは理解できましたね。
そして、なんとなくこの仕組みが、エラー処理に使えたら便利そうな気がしませんか?
エラーが発生したら、そのときだけはこっちのコードを実行させて……という具合に処理できれば、エラーが発生した場合だけに限定して、特別な処理を行うことができますね。
これを実現するために使われるのが、前回も登場した、『
On Error
』です。
On Error
は、エラーが発生したことを検知して特殊な処理を行いたいときに使います。前回の講座では、エラーが発生しても、それを無視してコードを実行させる方法を載せました。それがこれ。
On Error Resume Next
On Error
が記述された行より先では、エラーが発生すると、それを検知することができます。
そして、
On Error
と、それに続くキーワード(便宜上キーワードとしますが、正確にはステートメント)の指定の仕方によって、エラーが発生したときにどのように対処するのかを決めることができます。
『 On Error + キーワード 』 で、エラーが起きたときの対処法を決めることができる
先ほど登場した『
Resume Next
』も、キーワードのひとつです。
そして、『
Resume Next
』は、『続きをそのまま実行する』という意味なのです。
このキーワードには、他にも次のようなものがあります。
キーワード | 意味 |
On Error GoTo 行番号 | 指定された行番号へ移動 |
On Error GoTo 行ラベル | 指定された行ラベルの行へ移動 |
On Error GoTo 0 | エラーの検知をやめる |
On Error Resume Next | エラーを無視する |
GoTo
文の使い方は先ほど説明しましたよね。エラー処理に用いる場合にも全く同じ要領で使うことができます。あらかじめ行番号や行ラベルを用意しておけば、エラーが発生した場合だけ、任意の場所へコードの実行を移行することができるわけです。
例えば、次のようなコードを実行すると、約50%の確立で、エラーが発生してメッセージが出ます。
Sub Error_Test()
Dim L As Long
L = Int(Rnd * 2) '①
On Error GoTo ERROR_HANDLE
L = 10 / L '②
Exit Sub '③
ERROR_HANDLE:
MsgBox "0で割り算することはできません"
End Sub
数学のお約束ですが、0 で割り算をすることはできません。これはVBAでも同様で、もしそのような計算を行おうとするとエラーが発生します。
①の部分で、乱数を取得して変数に入れていますね。このとき、乱数の範囲は 0 か 1 のいずれかになるので、約半分の確立で、変数 L には 0 が入ります。
そして、②の部分で割り算をしようとしたとき、もしも変数 L の中身が 0 だった場合には、先ほども書いたように、0 では割り算ができないのがお約束ですからエラーが発生することになります。
今回の場合は、行ラベルを使って、エラーが起きた場合に移動するべきコードを指定しています。
そして注意点として押さえておかなくてはいけないのが、③で示しているように、エラーが発生しなかった場合には、エラー処理にコードの実行が移らないようにしておくことです。
もし
Exit Sub
を記述していなかった場合には、エラーが発生したかどうかに関わらず、絶対にメッセージが出るようになってしまいます。このようなエラーが発生しなかった場合にプロシージャを終了させる仕組みは、エラー処理における基本なので、忘れないようにしましょう。
■最後に補足先ほど、
On Error
に続くキーワードの一覧の中に、次のようなものがありましたね。
GoTo 0 …… エラーの検知をやめる
エラー処理を仕込んであるコードで、ここから先はエラーが起きるはずがない、とわかっている場合には、エラー処理を行わないようにしておきたい場合があります。
例えば、プログラムの構造上、ここまでは
On Error Resume Next
でエラーを無視しておきたいが、ある一定の箇所から先は、エラーが起きたらそれを無視してもらっては困る……、といった場合ですね。
このような場合には、
On Error GoTo 0
を使って、今までのエラー処理をリセットすることができます。このような記述が行われたあとでは、今まで有効になっていたいかなる
On Error
文も全て無効化します。
開発段階で、様々なテストを行う際には、このような記述を有効に活用することで、事前にエラーが起きていないかどうかをチェックすることができるのです。
さて、今回はかなり長くなってしまいました。いきなりたくさんの情報をぶつけられて困惑している方もいらっしゃるかもしれません。
ただ、何度も講座内で書いてますが、焦りは禁物です。ひとつひとつ確実に身につけていきましょう。
GoTo
文は、できる限りそれ単体で使うのはやめましょう。これは、コードの可読性(読みやすさ、わかりやすさ)が失われることになるからです。
ただし、エラー処理の一環として使用する分には、使い方さえ間違っていなければ問題ないでしょう。あくまでもわかりやすさを重視して考え、無駄なコードの移動が起こらないように気をつけましょう。
■格言
GoTo
文を使ってコードを移行
On Error + キーワード
で、エラーに対処使い方というより、使い道が重要です。
- 関連記事