VB6 FAQ

VB6のGoTo文とは?使い方と注意点

VB6で作られた古い業務システムのソースコードを確認していると、GoTo文が使われていることがあります。

GoTo文は、指定したラベルへ処理を移動させるための構文です。
現在の開発では多用を避けるべき書き方とされることが多いですが、VB6で作られた既存システムでは、エラー処理や終了処理で使われているケースがあります。

特にVB6では、現在の言語でよく使われるTry-Catchのような例外処理ではなく、On Error GoToを使ってエラー処理へ移動する書き方が一般的に使われてきました。

そのため、VB6システムを保守・改修する場合は、GoTo文を単純に悪いものとして見るのではなく、どの処理からどのラベルへ移動しているのか、通常処理とエラー処理が混ざっていないかを確認することが重要です。

この記事では、VB6のGoTo文の基本的な使い方、ラベルの考え方、On Error GoToによるエラー処理、既存VB6システムを改修するときの注意点について解説します。

VB6のGoTo文とは

GoTo文は、指定したラベルへ処理を移動させるための構文です。

通常、プログラムは上から下へ順番に処理が進みます。
しかし、GoTo文を使うと、途中の処理を飛ばして、指定した位置へ処理を移すことができます。

基本的には、次のような形で使います。

GoTo ラベル名

ラベル名:
    ' 移動先の処理

ラベル名の後ろには、コロンを付けます。
GoTo文を実行すると、そのラベルの位置まで処理が移動します。

たとえば、次のようなコードです。

Private Sub Command1_Click()

    Dim flg As Boolean

    flg = False

    If flg = False Then
        GoTo ErrorLabel
    End If

    MsgBox "通常処理を実行しました。"
    Exit Sub

ErrorLabel:
    MsgBox "処理できませんでした。"

End Sub

この例では、flgがFalseの場合にErrorLabelへ移動します。
そのため、「通常処理を実行しました。」は表示されず、「処理できませんでした。」が表示されます。

GoTo文は処理を直接移動できるため便利に見えますが、多用すると処理の流れが分かりにくくなります。

特に、古いVB6システムでは、複数のGoTo文やラベルが1つの処理内に混在していることがあり、改修時に注意が必要です。

GoTo文の基本構文

VB6のGoTo文は、次のように書きます。

GoTo Label1

Label1:
    ' 実行したい処理

ラベル名は任意の名前を付けることができます。
ただし、ラベルは同じプロシージャ内にある必要があります。

たとえば、Subプロシージャの中でGoToを使う場合、その移動先のラベルも同じSubプロシージャの中に必要です。

Private Sub Sample()

    GoTo SkipProcess

    MsgBox "この処理は実行されません。"

SkipProcess:
    MsgBox "ラベルの位置へ移動しました。"

End Sub

このコードでは、GoTo SkipProcessによって途中のMsgBoxを飛ばし、SkipProcessラベルの位置へ移動します。

GoTo文で別の関数や別のモジュールへ直接移動することはできません。
同じプロシージャの中で、指定したラベルへ処理を移動するための構文です。

また、ラベル名だけが書かれている行は、処理そのものではありません。
あくまでGoTo文の移動先として使われる目印です。

GoTo文の簡単な使用例

GoTo文は、条件によって処理を途中で抜けたい場合に使われることがあります。

たとえば、入力チェックでエラーがあった場合に、後続処理を実行せず終了処理へ移動するようなケースです。

Private Sub SaveData()

    If Text1.Text = "" Then
        MsgBox "名前を入力してください。"
        GoTo ExitProc
    End If

    If Text2.Text = "" Then
        MsgBox "住所を入力してください。"
        GoTo ExitProc
    End If

    ' 登録処理
    MsgBox "登録しました。"

ExitProc:
    ' 終了処理

End Sub

この例では、名前や住所が未入力の場合にExitProcへ移動します。

ただし、この程度の処理であれば、GoToを使わずにExit Subを使った方が分かりやすい場合もあります。

Private Sub SaveData()

    If Text1.Text = "" Then
        MsgBox "名前を入力してください。"
        Exit Sub
    End If

    If Text2.Text = "" Then
        MsgBox "住所を入力してください。"
        Exit Sub
    End If

    ' 登録処理
    MsgBox "登録しました。"

End Sub

このように、単純な入力チェックであれば、無理にGoToを使わない方が読みやすくなります。

GoTo文は使える構文ですが、使う場所を間違えると、どこからどこへ処理が飛ぶのか分かりにくくなります。

VB6でGoToが使われる場面

VB6でGoToが使われる場面として多いのは、エラー処理です。

VB6では、現在の.NET系言語で使われるTry-Catchの代わりに、On Error GoToを使ってエラー発生時の処理へ移動する書き方がよく使われます。

たとえば、次のような形です。

Private Sub LoadData()

    On Error GoTo ErrHandler

    ' データ取得処理
    ' ファイル読込処理
    ' データベース接続処理

    Exit Sub

ErrHandler:
    MsgBox "エラーが発生しました。" & vbCrLf & Err.Description

End Sub

このコードでは、通常処理の途中でエラーが発生した場合、ErrHandlerラベルへ処理が移動します。

また、ファイルやデータベース接続の後始末をまとめるために、終了処理用のラベルへ移動することもあります。

Private Sub ExportCsv()

    On Error GoTo ErrHandler

    ' CSV出力処理

    GoTo ExitProc

ErrHandler:
    MsgBox "CSV出力中にエラーが発生しました。" & vbCrLf & Err.Description

ExitProc:
    ' ファイルを閉じる
    ' オブジェクトを解放する

End Sub

このように、正常終了時もエラー発生時も、最後にExitProcへ集めて後始末を行う書き方です。

既存VB6システムでは、このようなGoToの使い方が残っていることがあります。
そのため、GoTo文を見つけた場合は、単に「古い書き方だ」と判断するのではなく、エラー処理なのか、終了処理なのか、通常の分岐なのかを分けて読む必要があります。

On Error GoToによるエラー処理

VB6で特に重要なのが、On Error GoToです。

On Error GoToは、エラーが発生したときに指定したラベルへ処理を移動するための書き方です。

On Error GoTo ErrHandler

このように書くと、その後の処理でエラーが発生した場合に、ErrHandlerというラベルへ移動します。

Private Sub Sample()

    On Error GoTo ErrHandler

    Dim x As Integer
    x = 10 / 0

    MsgBox "正常終了しました。"
    Exit Sub

ErrHandler:
    MsgBox "エラー番号:" & Err.Number & vbCrLf & _
           "エラー内容:" & Err.Description

End Sub

この例では、10 / 0でエラーが発生します。
そのため、ErrHandlerへ移動し、Err.NumberやErr.Descriptionを使ってエラー内容を表示します。

ここで重要なのが、通常処理の最後にExit SubやExit Functionを書くことです。

もしExit Subがないと、正常処理が終わった後に、そのままエラー処理ラベルの中へ流れてしまうことがあります。

Private Sub BadSample()

    On Error GoTo ErrHandler

    MsgBox "正常処理です。"

ErrHandler:
    MsgBox "エラー処理です。"

End Sub

このコードでは、エラーが発生していなくても、正常処理の後にErrHandlerの処理まで実行されてしまいます。

そのため、通常処理とエラー処理を分ける場合は、エラー処理ラベルの前にExit SubやExit Functionを入れるのが基本です。

Private Sub GoodSample()

    On Error GoTo ErrHandler

    MsgBox "正常処理です。"
    Exit Sub

ErrHandler:
    MsgBox "エラー処理です。"

End Sub

既存VB6システムを確認するときは、On Error GoToのラベルだけでなく、Exit SubやExit Functionの位置も必ず確認する必要があります。

GoTo文を使うときの注意点

GoTo文の一番の注意点は、処理の流れが分かりにくくなることです。

通常のコードであれば、上から順番に読めば処理の流れを追うことができます。
しかし、GoTo文が多いコードでは、途中から別のラベルへ飛び、さらに別の場所へ移動することがあります。

たとえば、次のようなコードです。

Private Sub SampleProcess()

    If Text1.Text = "" Then GoTo InputError
    If Text2.Text = "" Then GoTo InputError

    If Check1.Value = 1 Then GoTo SpecialProcess

    GoTo NormalProcess

InputError:
    MsgBox "入力内容を確認してください。"
    GoTo ExitProc

SpecialProcess:
    MsgBox "特別処理を行います。"
    GoTo ExitProc

NormalProcess:
    MsgBox "通常処理を行います。"

ExitProc:
    MsgBox "処理を終了します。"

End Sub

このようなコードは、短い例であればまだ読めます。
しかし、実際の業務システムでは、数百行の処理の中にGoToやラベルが複数あることがあります。

その場合、どの条件でどのラベルへ飛ぶのか、どの処理が実行され、どの処理が飛ばされるのかを確認するのに時間がかかります。

また、変数の状態にも注意が必要です。

GoToで途中の処理を飛ばすと、本来セットされるはずだった変数が未設定のまま後続処理に進むことがあります。

たとえば、合計金額、得意先コード、処理区分、帳票番号、ファイル名などが、GoToによって設定されないまま使われる可能性があります。

そのため、GoTo文を含むコードを改修するときは、ラベルへ移動する前後で、どの変数がどの状態になっているかを確認する必要があります。

GoTo文を避けた方がよいケース

新しくコードを書く場合、GoTo文はできるだけ避けた方がよい場面が多いです。

特に、If文やSelect Case文で自然に書ける処理であれば、GoToを使う必要はありません。

たとえば、処理区分によって分岐する場合は、Select Caseで整理できます。

Select Case syoriKubun
    Case "1"
        Call TourokuSyori

    Case "2"
        Call KoushinSyori

    Case "3"
        Call SakujoSyori

    Case Else
        MsgBox "処理区分が不正です。"
End Select

また、条件によって処理を抜けたいだけであれば、Exit SubやExit Functionを使った方が分かりやすい場合があります。

If Text1.Text = "" Then
    MsgBox "入力してください。"
    Exit Sub
End If

処理が長くなっている場合は、GoToで飛ばすのではなく、処理を別のSubやFunctionに分ける方が保守しやすくなります。

たとえば、入力チェック、登録処理、帳票出力、終了処理を1つのSubにすべて書くのではなく、それぞれの処理を分けます。

Private Sub ExecuteProcess()

    If CheckInput() = False Then
        Exit Sub
    End If

    Call SaveData
    Call PrintReport

End Sub

このように整理すると、処理の流れが読みやすくなります。

特に業務システムでは、後から改修する人がソースコードを読むことになります。
そのとき、GoToであちこちに処理が飛ぶコードは、修正ミスの原因になりやすくなります。

GoTo文があっても許容されるケース

GoTo文は多用を避けるべきですが、既存VB6システムでは、すぐに削除しない方がよい場合もあります。

特に、エラー処理でOn Error GoToが使われている場合です。

VB6では、エラー処理の仕組みとしてOn Error GoToが使われることが多いため、それ自体を無理に消す必要はありません。

また、終了処理や後始末を1か所にまとめている場合もあります。

たとえば、ファイルを開いた後に必ず閉じる、データベース接続を解放する、画面の状態を戻すといった処理です。

Private Sub ReadFile()

    On Error GoTo ErrHandler

    Open "C:\data.txt" For Input As #1

    ' ファイル読込処理

    GoTo ExitProc

ErrHandler:
    MsgBox "ファイル読込でエラーが発生しました。"

ExitProc:
    Close #1

End Sub

このようなコードでは、正常終了時もエラー発生時もExitProcへ集めて、ファイルを閉じるようにしています。

もちろん、書き方として整理できる余地はあります。
しかし、既存システムで長年動いている処理を不用意に変更すると、別の不具合を起こすことがあります。

そのため、GoTo文を見つけたからといって、すぐに削除するのではなく、まず何のために使われているのかを確認することが大切です。

既存VB6システムでGoToを読むときの確認ポイント

既存VB6システムでGoTo文を読むときは、まずラベルを探します。

GoToの後ろに書かれているラベル名が、同じプロシージャ内のどこにあるかを確認します。

次に、そのラベルへどこから飛んでくるのかを確認します。

1つのラベルに対して、複数のGoTo文が向いている場合があります。
その場合、どの条件でそのラベルへ移動するのかを整理する必要があります。

また、ラベルに移動する前後の変数の状態を確認します。

たとえば、次のような情報です。

処理区分はセットされているか。
得意先コードや商品コードは取得済みか。
データベース接続は開いているか。
ファイルは開いたままか。
帳票オブジェクトは作成済みか。
エラー番号やエラー内容は参照されているか。

Exit SubやExit Functionの位置も重要です。

通常処理が終わった後に、誤ってエラー処理へ流れていないか。
エラー処理の後に、さらに通常処理へ戻っていないか。
途中終了すべきところで後続処理が動いていないか。

こうした点を確認しないまま修正すると、画面上は動いているように見えても、登録処理、帳票出力、CSV出力、後処理などに影響が出ることがあります。

GoToを含むコードを改修するときの注意点

GoToを含むコードを改修する場合は、最初に処理の流れを整理することが重要です。

ソースコードを見ながら、通常処理、エラー処理、終了処理、途中分岐を分けて確認します。

可能であれば、簡単なメモや図にして整理すると安全です。

たとえば、次のように整理します。

最初に入力チェックを行う。
入力エラーの場合はInputErrorへ移動する。
登録処理でエラーが発生した場合はErrHandlerへ移動する。
正常終了時はExitProcへ移動する。
ExitProcでファイルやDB接続を閉じる。

このように整理すると、どのラベルが何の役割を持っているかが分かりやすくなります。

改修時に特に注意したいのは、途中でスキップされる処理です。

GoToによって処理が飛ぶ場合、本来実行されるはずだった初期化処理、変数設定、ファイルクローズ、DB切断、画面更新などが実行されないことがあります。

また、後処理が必ず実行されるかも確認します。

ファイルを開いたままにする、DB接続を閉じない、トランザクションを終了しないといった問題は、後から原因を追いにくくなります。

既存システムでは、GoToを含むコードが長年運用されていることがあります。
動いている処理を大きく書き換える場合は、修正前後で同じ結果になるかを確認するテストが必要です。

GoTo文を整理する方法

GoTo文が多くて読みづらい場合は、少しずつ整理できるかを検討します。

まず、単純な入力チェックであれば、Exit SubやExit Functionに置き換えられることがあります。

If Text1.Text = "" Then
    MsgBox "得意先を入力してください。"
    Exit Sub
End If

処理区分による分岐であれば、Select Caseに整理できる場合があります。

Select Case syoriKubun
    Case "A"
        Call SyoriA

    Case "B"
        Call SyoriB

    Case "C"
        Call SyoriC

    Case Else
        MsgBox "処理区分が不正です。"
End Select

同じ処理が複数のラベルに分散している場合は、共通処理として別プロシージャに分けられることがあります。

Private Sub CloseObjects()
    ' ファイルやDB接続の終了処理
End Sub

ただし、既存VB6システムでは、表面上は同じ処理に見えても、実際には少しずつ違う処理が書かれていることがあります。

そのため、単純に「GoToをなくす」という方針で一気に書き換えるのは危険です。

まずは、ラベルの役割を整理し、通常処理、エラー処理、終了処理を分けて読むことが大切です。
そのうえで、影響が小さい部分から整理する方が安全です。

VB6からVB.NETへ移行する場合のGoToの扱い

VB6からVB.NETへ移行する場合、GoTo文の扱いにも注意が必要です。

VB.NETにもGoToに相当する考え方はありますが、既存VB6システムのGoToをそのまま残すのがよいとは限りません。

特に、On Error GoToによるエラー処理は、VB.NETではTry-Catchに置き換えることが多くなります。

VB6のエラー処理では、エラーが発生したら指定ラベルへ移動し、Err.NumberやErr.Descriptionを確認する流れになります。

一方、VB.NETでは、Tryブロック内で処理を実行し、Catchブロックでエラーを受ける形が一般的です。

移行時には、単純に文法を置き換えるだけではなく、エラーが発生した場合に何をしたいのかを確認する必要があります。

たとえば、次のような点です。

エラー時に画面へメッセージを出すだけでよいのか。
ログを残す必要があるのか。
ファイルやDB接続の後始末が必要か。
処理を中断するのか、続行するのか。
利用者に再入力させるのか。

また、業務ロジックの中にGoToが多く使われている場合は、移行前に処理の流れを整理する必要があります。

古いコードをそのまま新しい環境へ移すだけでは、読みづらさや保守しづらさもそのまま残ります。

VB.NETへの移行では、GoTo文そのものよりも、そのGoToが表している処理の意味を確認することが重要です。

まとめ

VB6のGoTo文は、指定したラベルへ処理を移動させるための構文です。

VB6では、通常の処理分岐だけでなく、On Error GoToによるエラー処理でもよく使われます。特に古い業務システムでは、エラー処理、終了処理、後始末処理のためにGoToやラベルが使われていることがあります。

ただし、GoTo文を多用すると、処理の流れが分かりにくくなります。どこからどのラベルへ飛ぶのか、途中でスキップされる処理はないか、変数やファイル、データベース接続の状態がどう変わるかを確認しなければなりません。

新しくコードを書く場合は、If文、Select Case、Exit Sub、Exit Function、別プロシージャへの分割などで整理できるかを検討した方がよいでしょう。

一方で、既存VB6システムでは、GoTo文を無理に削除すると動作が変わることがあります。
まずはGoToの移動先、ラベルの役割、通常処理とエラー処理の流れを確認することが大切です。

VB6システムの改修やVB.NETへの移行を行う場合は、GoTo文を単なる古い構文として見るのではなく、そこに含まれているエラー処理や業務上の分岐を丁寧に読み解く必要があります。

システム開発・ホームページ制作会社|株式会社システムキューブ