6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【VB6・VB】古いコードのリプレース その3 On Error ~

Last updated at Posted at 2018-11-17

※この記事は【VB6・VB】古いコードのリプレース のシリーズその3です。

#On Errorステートメントとは

VB6時代からあるエラー対処法。

最も簡単な例がこちら

VB6:hoge.vb
        On Error GoTo Err
        '処理...
        '..
Err:

最初に断っておきますが、これは今でも使えます。
けど少なくとも、今から新しく書くような用法ではないです。

なぜなら、Try-Catchがあるから。

#Try-Catchとは

VBから出来たエラー対処法。

VB:hoge.vb
       Try
        '処理...
        '..
       Catch ex As Exception
       End Try

・On Error Gotoが出来ることは殆どTry-Catchでも出来ます。
・逆にTry-Catchに出来て、On Error Gotoに出来ないことはたくさんあります。

  • Try-Catchにしか出来ないこと

  • Finallyが使える(重要)

  • エラーの詳細情報を出力できる(On ErrorにはErr.Number程度しかない)

  • GoToなんて汚い言葉を使わなくて済む

ということでTry-Catchを使わない理由がないです。
これはもうTry-Catchに置き換えるしかないですね。

#On Error -> Try-Catch 置き換え例

例1 通常の置き換え
例2 Err.Numberがあるとき
例3 Resume Next / Goto 0 がある場合

##例1 通常の置き換え

通常の置き換えはさきほどの例そのままです。

##例2 Err.Numberがあるとき

VB6:例
        On Error GoTo Err
        '処理...
        '..
Err:
    If Err.Number = 53 Then
    '特別なエラー処理..
    End If
    '普通のエラー処理..

ErrObjectの.Numberの値によって個別で何か処理をやっている場合。
この場合、そのエラーが一体何のエラーなのか調べて、そのエラーと対応するExceptionを探さないといけません。

NumberとExceptionは1:1で対応しているわけではありません。
内容を見て実際に動かして確認するしかありません。

よくErr.Numberで特殊対応しているのを見るのは↓あたりでしょうか。

.Number .Description
5 プロシージャの呼び出し、または引数が不正です。
9 インデックスが有効範囲にありません。
11 0 で除算しました。
13 型が一致しません。
53 ファイルが見つかりません。または存在しないファイルを参照しています。
75 パス名が無効です。
76 パスが見つかりません。
321 不正なファイル形式です。
31036 ファイルへの書き込み中にエラーが発生しました。
31037 ファイルの読み込み中にエラーが発生しました。

特にVB6はファイルとのやりとりがお粗末なものしかなかったので、ファイル関係のエラートラップが多いかと思います。
たとえば上のErr.Number=53「ファイルが見つかりません。または存在しないファイルを参照しています。」
の場合は、以下のような変更でいいでしょう。
(IOExceptionもあったほうが安全かも)

VB:例
        Try
            '処理..
        Catch ex As System.IO.FileNotFoundException
            '特別なエラー処理..
        Catch ex As Exception
            '普通のエラー処理..
        End Try

##例3 Resume Next / Goto 0 がある場合

Resume Nextは出たエラーを無視してそのまま次の処理へ進むため、本当に現在の設計思想からしたらメチャクチャな動きをします。
無視する範囲の終わりにOn Error Goto 0とつけるのが基本的な使用方法です。

例えば、こういうコードが書けます。

VB6:例

        '4回割り算したいと決まっているとする
        Dim iResult(3) As Integer

        'けど分子は4個とは限らないし、Nothingや0が入ってくることもあるとする
        Dim iBunshi() As Integer
        iBunshi = {Nothing, 0, 2}

        '何があろうと割り算を4回実行する...
        On Error Resume Next
        For i As Integer = 0 To 3
            iResult(i) = CInt(100 / iBunshi(i))
        Next

        On Error GoTo 0

        '次の処理...

この例の場合、0で割っても、引数の配列が足りなくとも、処理は強引に続行されます。
iResultの中身は{0,0,50,0}となります。

直すにはResume Next~Goto 0の間の中身を見て、発生しそうなエラー全てをすくい取れるような条件分岐・Catchに置き換えていかないといけません。
こんなの触りたくないのが正直なところですが仕方ありません。

直した例がこちら。

VB:例

        '4回割り算したいと決まっているとする
        Dim iResult(3) As Integer

        'けど分子は4個とは限らないし、Nothingや0が入ることもあるとする
        Dim iBunshi() As Integer
        iBunshi = {Nothing, 0, 2}

        '何があろうと割り算を4回実行する...
        For i As Integer = 0 To 3
            If iBunshi.Count <= i OrElse    '引数が足りない
               IsNothing(iBunshi(i)) OrElse 'Nothingが入っている
               iBunshi(i) = 0 Then          '0が入っている

                iResult(i) = 0 'そんな場合は0を返す
            Else
                '正しい値なら割り算を実行
                iResult(i) = CInt(100 / iBunshi(i))
            End If
        Next

        '次の処理...

今回はTry-Catchなしで置き換えられる例でしたが、もちろんTry-Catchしないと難しいような処理のこともあります。
ケースバイケースで本当に面倒です。

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?