Lesson7 エラー処理の基礎

 スクリプトを書く上で必要不可欠になるのが、今回取り上げるエラー処理です。まずは、エラーとは何かについて、実例を挙げて説明しましょう。

MsgBox "Test

 このようなスクリプトを実行しようとすると、「Microsoft VBScript コンパイル エラー」と書かれたダイアログが表示され、終了してしまいます。これは、MsgBox関数の引数が本来 "Test" となるべきなのに、 "Test のように " を付け忘れているという、文法ミスを犯しているためです。この手のミスは結構ありがちですが、エラーメッセージに従って該当する行の修正をおこなえば問題ありません。
 If文にEnd Ifを付け忘れるなどの構文ミス、全角のスペースを入れてしまうなど文字の不正等に気をつける必要があります。

 

 では、文法的にミスはないにも関わらす、エラーが発生する例を挙げます。

Dim A,B,C
MsgBox "実行時エラーの例"
A="a"
B="b"
C=A*B
MsgBox C 

 このスクリプトは、文法的にミスはありませんが、5行目で文字型の変数Aと変数Bをかけようとしています。しかし実際は不可能なので、5行目を実行しようとした時点で、「Microsoft VBScript 実行時エラー」と書かれたダイアログが出て終了してしまいます。これもエラーとなる部分を直せば問題ありません。このスクリプトの場合、AとBという変数に数字を入れるか、*のかわりに&を使えばエラーは発生しません。

 

 このような実行時エラーのうち、簡単な修正だけでは回避できない場合もあります。

Dim R,S
R=InputBox ("半径を入力してください。","円の面積を求める")
S=3.14159*R^2
MsgBox "面積は " & S

 このスクリプトは、ユーザーが入力した半径の値から、円の面積を求めるものです。
 InputBox関数で、任意の半径の値が入力できますが、ここで数字以外の文字を入力すると、3行目で文字をかけ算しようとしてエラーになってしまいます。このエラーを回避するためには、入力された値が、数字かどうか判断するルーチンを追加しなければなりません。これにはいくつかの方法がありますが、IsNumeric関数を使うのが簡単です。IsNumeric関数は、引数として指定した値が、数値演算可能ならTrue、そうでないならFalseを返します。

Dim R,S
R=InputBox ("半径を入力してください。","円の面積を求める")
If IsNumeric(R) Then
	R=CDbl(R)
	S=3.14159*R^2
	S=CStr(S)
	MsgBox "面積は " & S
Else
	MsgBox "半径には数字を指定してください"
End If

 このようにすると、入力された値が数字でない場合は面積を計算せず、注意を表示して終了するようになります。
 なお、CDbl関数は、引数として指定した値を倍精度浮動小数点数型にして返すものです。InputBox関数の返値は文字列型の値なので、演算をする際はこのように、念のためデータ型を変換して置いた方が良いでしょう。(とくに+には、数値を足すだけでなく、文字列連結&の意味もあるので、足し算するときはこの作業が不可欠です。)
 CStr関数は引数を文字列型に変換する関数です。これはあまり必要ないかもしれませんが、念のためです。

 同様の系列として、次に挙げるスクリプトも見てください。

Dim X,R
X=InputBox ("数値を入力してください。","逆数を求める")
If IsNumeric(X) Then
	X=CDbl(X)
	If X<>0 Then
		R=1 / X
		MsgBox X & "の逆数は" & R
	Else
		MsgBox "0以外の数字を指定してください"
	End If
Else
	MsgBox "数字を指定してください"
End If

 これは入力された数字の逆数を求めるものです。与えられた値が数字かどうかを判断するのはもちろんですが、わり算を実行するときはこのように割る数が0でないかどうかを確認するルーチンも必要です。これを省くと、0を入力すると、「0で除算しました」という実行時エラーが発生してしまいます。

 

 以上で述べたように、コードに手を加えることでエラーを回避することが可能なことが多いのですが、中にはエラーの回避が不可能、あるいは回避させるのに本筋とは関係ない処理を長々と書かねばならないという事態も多々発生します。
 このようなとき、VBSではエラーの発生を止めずに、エラーが発生してから後処理をする方法が用意されています。それにはOn Error Resume NextステートメントおよびErrオブジェクトを利用します。

 On Error Resume Nextステートメントを記述した行以降でエラーが発生しても、そのエラーが発生した行で強制終了せずに、その次の行から処理を続行するようになります。上の逆数スクリプトにOn Error Resume Nextステートメントを導入すると、こうなります。

On Error Resume Next
Dim X,R
X=InputBox ("数値を入力してください。","逆数を求める")
R=1 / X
MsgBox X & "の逆数は" & R

 このようにすると、仮に文字や、0を入力しても、実行時エラーのダイアログは表示されず最後まで処理が実行されるようになります。ただし、変数Rに有効な数字が代入されないので、最後の行のMsgBoxで結果は表示されません。エラーが発生したときは別の表示をするように改良しましょう。

On Error Resume Next
Dim X,R
X=InputBox ("数値を入力してください。","逆数を求める")
R=1 / X
Select Case Err.Number
	Case 0 MsgBox X & "の逆数は" & R
	Case 11 MsgBox "0以外の数字を指定してください",,Err.Number & ":" & Err.Description
	Case 13 MsgBox "数字を指定してください",,Err.Number & ":" & Err.Description
End Select
Err.Clear

 実行時エラーの情報は、Errオブジェクトに格納されています。Errオブジェクトの主なプロパティには、

Numberプロパティ(エラー番号)、Descriptionプロパティ(エラーの内容)、Sourceプロパティ(エラーの発生元)

があります。
エラーが発生していない状態では、

Err.Number=0
Err.Description=""
Err.Source=""

という値を持っていますが、実行時エラーが発生すると、そのエラーに応じてErrオブジェクトの各プロパティの値が変わります。なので、どんなエラーが発生したかを知るには、これらのプロパティをコード中から参照するといいわけです。
 上のスクリプトでは、Err.Numberの値に応じて表示するメッセージを変更しています。またメッセージボックスのタイトルには、具体的なエラーの内容を表示するようにしています。
 VBSにどんなエラーがあり、どのNumberが割り当てられているかについてはVBSランゲージリファレンスを参照してください。

 このスクリプトの最後の行では、ErrオブジェクトのClearメソッドを用いて、Errオブジェクトの各プロパティをエラー発生前の状態に戻しています。こうすることで、エラー処理が完了することになります。
(Errオブジェクトには、任意のエラーを発生させるRaiseメソッドもあります)

 なお、On Error Resume NextステートメントをSubプロシージャやFunctionプロシージャ内で記述すると、On Error Resume Nextはそのサブルーチン中でのみ有効になり、メインルーチンでエラーが発生したときには強制終了するので注意が必要です。

 

 さて最後に、意図的にエラーを発生させることで、コードのデバッグを容易にする方法を紹介しましょう。
 コードの最初に、Option Explicitという行を入れておくと、Dimなどで宣言されていない変数を使用しようとすると、実行時エラー(Number=500)が発生してスクリプトが実行されなくなります。こうしておくと、宣言していない変数を間違って使用することで、スクリプトが思わぬ動作をする事を避けることができます。


 Lesson7ではいろいろなケースのエラー処理の方法について解説しました。エラー処理は重要な要素なので、よく概念を理解しておいてください。
 さて、Lesson1から7まででVBSの基本文法などを述べました。次回Lesson8でそのまとめをしてみたいと思います。


Home Up Back Next