連載
» 2007年02月15日 00時00分 公開

基礎解説 演習方式で身につけるチェック式WSH超入門:第9回 VBScriptのオブジェクトを使いこなす (2/4)

[牟田口大介(Microsoft MVP Visual Developer - Scripting),著]

Errオブジェクト……の前に、エラーの話

 VBScriptにはエラー情報を含んだオブジェクトである、Errオブジェクトが存在する。

 Errオブジェクトの解説の前に、VBScriptにおけるエラーとは何かを説明しよう。VBScriptには2種類のエラーがあって、1つは「構文エラー」である。これは、コードの記述が文法に即していない場合に発生するエラーで、例えばIf 〜 Then 〜 Elseステートメントにおいて、Thenを書き忘れた場合などに発生する。このエラーが発生するとスクリプトは実行されずにエラー・ダイアログが表示される。このエラーの対処法は、スクリプトの記述を文法に即したものに修正する以外にない。

 もう1つのエラーが「実行時エラー」である。このエラーはスクリプトを実行中に何らかの異常が発生した場合、そこで実行を停止し、エラー・ダイアログを表示させるものである。次の例をご覧いただきたい。

Option Explicit
Dim dblCalculatedNumber
dblCalculatedNumber = 1 / 0
MsgBox dblCalculatedNumber

 このスクリプトを実行すると次のようなエラー・ダイアログが表示され、スクリプトの実行が停止される。

実行時エラーの例
0で除算(割り算)しようとすると、実行時エラーが発生し、このようなエラー・ダイアログが表示される。

 ここで問題となるのはエラー・ダイアログに示されているとおり、スクリプトの3行目の記述である。dblCalculatedNumberという変数に1 / 0(1を0で割ったもの)の計算結果を代入しようとしているが、数学で定められているとおり、数値を0で割ることはできない。そのため、VBScriptでもエラーが発生するようになっている。このエラーのため、4行目のMsgBox関数は実行されない。

 このような例だと、単に問題となる場所のコードを修正すればよいが、例えば次のような例だとどうだろう。

Option Explicit
Dim dblCalculatedNumber, strDivisorNumber
strDivisorNumber = InputBox("割る数を入力してください")
dblCalculatedNumber = 1 / strDivisorNumber
MsgBox dblCalculatedNumber

 この例は、1をInputBox関数で入力した値で割った結果を表示するというスクリプトであるが、このInputBoxに0を入れた場合は先ほどと同様、実行時エラーになる。また、数値以外の文字列を入力した場合は、「型が一致しません」という実行時エラーで同様にスクリプトは停止する。この例の場合、ユーザーが何を入力するかは事前に分からないので、簡単に回避することはできない。

 このエラーに対処しようと思えば、例えば次のような書き直しが必要だろう。

Option Explicit
Dim dblCalculatedNumber, strDivisorNumber
strDivisorNumber = InputBox("割る数を入力してください")
If IsNumeric(strDivisorNumber) And strDivisorNumber <> "0" Then
    dblCalculatedNumber = 1 / strDivisorNumber
End If
MsgBox dblCalculatedNumber

 この例では、割る数が数値として評価できるかどうかをIsNumeric関数で調べ、かつ、"0"でないことをIf 〜 Then 〜 Elseステートメントで確認してから計算を実行している。

 このように想定されるエラーが発生しないように前もって対処するというのも1つの方法だが、VBScriptでは「エラーを発生させてから対処を行う」方法も用意されている。そのときに用いるのがOn Errorステートメントだ。On Errorステートメントを用いて先ほどのスクリプトを次のように書き直す。

Option Explicit
On Error Resume Next
Dim dblCalculatedNumber, strDivisorNumber
strDivisorNumber = InputBox("割る数を入力してください")
dblCalculatedNumber = 1 / strDivisorNumber
MsgBox dblCalculatedNumber

 On Error Resume Nextを記述した次の行以降でエラーが発生した場合、スクリプトを中断するのではなく、その行の次の行から実行を再開する。ここでは5行目でたとえ0で割り算を実行することになっても、エラー・ダイアログを表示しスクリプトが停止するのではなく、次の行のMsgBox関数が実行される。また、On Error Goto 0と記述することで、次の行からOn Error Resume Nextの効果が取り消される。On Errorステートメントを実際に使う際は、エラーが発生すると想定される行のみ、On Error Resume NextとOn Error Goto 0で囲うのがよい。例を次に示す。

Option Explicit
Dim dblCalculatedNumber, strDivisorNumber
strDivisorNumber = InputBox("割る数を入力してください")
On Error Resume Next
dblCalculatedNumber = 1 / strDivisorNumber
On Error Goto 0
MsgBox dblCalculatedNumber

 なお、On Errorステートメントをスクリプト・レベルで記述するとSubプロシージャ、Functionプロシージャにも作用する。SubプロシージャやFunctionプロシージャ内で記述した場合は、そのプロシージャ内でのみ作用する。

Errオブジェクトを使ったエラー処理

 さて、先ほどの例ではエラーを発生させ、何もせずそのまま次の行に処理を移したが、実際はここでエラーに対して種々の処理を行う。その際に用いるのが、エラー情報を格納し、エラーに関する動作を実行可能にする、Errオブジェクトである。Errオブジェクトにはエラー情報を格納したプロパティ(Number=エラー番号、Description=説明、Source=ソース、など)を持つとともに、エラーに関する動作を行うメソッド(Clear=エラー情報の消去、Raise=エラーの発生)を持つ。Errオブジェクトはスクリプト開始時に自動的にインスタンス化されているので、特に宣言などをすることなく使用可能である。ErrオブジェクトのNumberプロパティにはエラー番号が格納されている(エラーが発生していないときは0が格納されている)。その番号によって異なる処理をさせてみよう。

Option Explicit
Dim dblCalculatedNumber, strDivisorNumber
Do
    strDivisorNumber = InputBox("割る数を入力してください")
    On Error Resume Next
    dblCalculatedNumber = 1 / strDivisorNumber
    If Err.Number = 11 Then
        '0除算エラー。
        MsgBox "0で割ることはできません。"
    ElseIf Err.Number = 13 Then
        '型不一致エラー。
        MsgBox "数値を入力してください。"
    ElseIf Err.Number = 0 Then
         'エラーが発生していない場合はループを抜ける。
        Exit Do
    Else
        'そのほかのエラーの場合。
        MsgBox "想定外のエラーです。"
    End If
    'エラー情報をクリアする。
    Err.Clear
    On Error Goto 0
Loop
MsgBox dblCalculatedNumber

 オブジェクトのプロパティにアクセスするには、オブジェクトの後に「.」(ドット)を記述し、その後にプロパティ名を書く。メソッドを呼び出す際も同様である。メソッドは戻り値を変数などに代入する際は( )を付け、それ以外のときは付けなくてよい。これはSubプロシージャと同様である。

 Err.NumberでErrオブジェクトのNumberプロパティが参照できる。ここで、If 〜 Then 〜 Elseステートメントを用い、Err.Numberの値に応じて適切な指示をユーザーに出している。エラー情報はErr.ClearのようにClearメソッドを呼び出すことでリセットされる。エラーが解消されるまではDo 〜 Loopステートメントに従いInputBoxが表示される。Err.Numberが0のとき、すなわちエラーが発生していない場合のみループを抜ける。

 Numberプロパティは変数と同様に、任意の数値を代入することもできる。例えばこのように記述できる。

Err.Number = 10

 Numberプロパティは、Errオブジェクトの「既定プロパティ(デフォルトのプロパティ)」なので、省略して記述することもできる。これは、例えば、If Err.Number = 11 ThenはIf Err = 11 Thenと記述できるということだ。WSHで扱うオブジェクトには既定プロパティが用意されていることが多い。

 なお本題から外れるが、先ほどの例のように、1つの値(ここではErr.Number)に対してIf 〜 Then 〜 ElseステートメントでElseIf節を多く使う場合は、Selectステートメントに書き換えた方がスマートである。

    Select Case Err.Number
        Case 11
            '0除算エラー。
            MsgBox "0で割ることはできません。"
        Case 13
            '型不一致エラー。
            MsgBox "数値を入力してください。"
        Case 0
            'エラーが発生していない場合はループを抜ける。
            Exit Do
        Case Else
            'そのほかのエラーの場合。
            MsgBox "想定外のエラーです。"
    End Select

 Select Case の後に評価する変数やプロパティなどの式を指定し、Caseの後に記述した値と一致したとき、その部分が実行される。1つのCaseには複数の値が指定でき、それらの値は「,」(カンマ)で区切り、「Case 1, 2」のようにする。また、どのCaseとも一致しなかった場合はCase Elseの部分が実行される。先ほどのIf 〜 Then 〜 Elseステートメントを使ったものと処理自体は同じだが、こちらの方がシンプルで見やすくなっていることがお分かりいただけると思う。

 さらにもう1つ、オブジェクトを扱ううえで便利なステートメントを覚えておこう。それはWithステートメントである。

Option Explicit
On Error Resume Next
With Err
    'エラーの生成。
    .Raise 10
    MsgBox "エラー番号:" & .Number & vbCrLf & _
           "説明:" & .Description & vbCrLf & _
           "ソース:" & .Source & vbCrLf
End With

 このスクリプトを実行すると次のようなメッセージ・ダイアログが表示される。

Withステートメントを使ったエラー処理の例
Withステートメントを利用すると、ステートメント内でオブジェクトや「.」で連結された複数のプロパティ・メソッドを省略して、短く記述できる。

 Withの後にオブジェクトを指定すると、ステートメント内でオブジェクトを省略することができる。長いオブジェクト名や、「.」で複数のプロパティ・メソッドが連結された値を参照する場合に便利である。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。