Gotoステートメントでコードをジャンプ!毒と薬の2面性

VBAGotoeyecatch001

制御構文とステートメントのGotoは、利用法によって毒コードとなったり薬コードになったりします。

Gotoステートメントの利用方法のエッセンスを最速で理解できるように解説します。

こんにちは、じゅんぱ店長(@junpa33)です。

エクセルVBAのコードで、Gotoステートメントは嫌われ系のグループにはいっています。

それでも、GotoがあるのでVBAコード組み立てがスムーズに、楽に、なる事も多いと言うのも事実です。

Gotoステートメントの利用法を最速理解

VBAGotosamplep009

エクセルVBAコードを組み立てる上で、Gotoステートメントほど、毒と薬を持っているものはないかもしれません。

サンプルコード
VBA
Option Explicit

Sub GOTO_Sample()
    Dim N, x, Z, y As Integer
        Z = 0
'一桁の乱数を発生
        N = Int(Rnd * 10)
        For x = 1 To N
            Range("A" & x).Offset(, x - 1).Value = "◎"
'5回目のループの時にセル表示を変更する
            If x = 5 Then
                Range("A" & x).Offset(, x - 1).Value = "×"
                Z = 1
'強制的にstep1にジャンプ
                GoTo step1
            End If
step2:
        Next x
step1:
        If Z = 1 Then
            For y = 2 To 4
                  Range("A" & x).Offset(y - 1, x - y).Value = "×"
            Next y
            Z = 0
'強制的にstep2にジャンプ、元のループに戻す
            GoTo step2
        End If
End Sub

毒コード(デメリット)

多用するとコードの可読性も悪くなり、バグの発生や発見についても非常に支障が出てくることになります。

確かに、バグの発生場所が発見しずらくなるというのは困ったものです。

サンプルコードでもお分かりのように、

頭の中でコードの進行を追いかけるのも結構大変です。

        For x = 1 To N
            Range("A" & x).Offset(, x - 1).Value = "◎"
'5回目のループの時にセル表示を変更する
            If x = 5 Then
                Range("A" & x).Offset(, x - 1).Value = "×"
                Z = 1
'強制的にstep1にジャンプ
                GoTo step1
            End If
step2:
        Next x
step1:
        If Z = 1 Then
            For y = 2 To 4
                  Range("A" & x).Offset(y - 1, x - y).Value = "×"
            Next y
            Z = 0
'強制的にstep2にジャンプ、元のループに戻す
            GoTo step2

「元のループ途中で飛び出して別のループに入って処理後また元のループに戻る。」

チョット変態的なコード進行です。こういった流れは可読性が著しく悪いです。

これが、いわゆる毒コードです。

薬コード(メリット)

一方、

ループ処理の中で、一度そこから抜け出し別処理をする。

そのループの中にあって、If条件文で別処理を行う事は可能な場合でも、ループ内での記述内容が長く大きくなり過ぎ、可読性が悪くなるといった場合。

その別処理を行う部分を、後々に変更する可能性がある時に、その別処理のコード記述を抜き出して見やすくしたい場合など。

もちろんそれに対しては、Functionプロシージャー、部品化プロシージャー、ユーザー定義関数などの対策方法もあります。

あるいはその他、コードの実行時にエラーで停止してしまう可能性があるコード組み立ての場合。

エラーメッセージでの緊急停止を回避するための対策として利用できます。

これは薬コードと言える使い方です。

ループを抜けてラベルへ飛ぶGoto

サンプルコードの実行結果です。

VBAGotosample002a

For~Next文で実行の範囲を乱数を発生させてランダムに可変させています。

もし5回目の実行があれば、「◎」表示を「✖」にしてラベル「step1」に飛びます。(ループを抜け出します。)ここで変数「Z」に「1」を代入します。

step1では、ループ内とは異なることを実行します。実行後に変数「Z」に「0」を代入します。「step2」に飛びます。

step2でループ内に戻ります。

普通に多いコードの組み方では、ラベル(今回の場合だと「step1」)の記述の前に「Exit Sub」を記述して、

If~Goto条件で飛ばされていないケースは、ラベルの直前でプロシージャーを抜け出す(終了する)のがメジャーな設定です。

けれどもこの方法だと、一度Gotoを使用したらその条件に当たらないものは「End Sub」まで進めないことになります。

そこで、「Z という変数」を使って、”Gotoしたケース” と ”スルーしたケース” に区分けして、

step1のコード実行もIf条件文で ”スルー” させるようにしています。

これで「End Sub」まで進めるようになります。

参考記事

  • Int関数についてはこの記事を参考にできます。
vbaintfixeyecatch Int・Fix・Abs・Sign関数で数値の整数部分を完全分離
  • Rnd関数についてはこの記事を参考にできます。
vbarndeyecatch Rnd関数で乱数を取得。デフォルトでは使えない戻り値の加工
  • Offsetについてはこの記事を参考にできます。
vbaoffseteyecatch Offsetプロパティは指定範囲を移動させる

コード実行エラーで緊急停止させないGoto

エラーが発生する要因は色々あります。

Gotoを使ったコード停止を起こさせない利用法は、「On Error Goto」として記述します。

それは、エラーを起こす可能性のあるコードの前に記述する必要があります。

VBAGotosample005a

例えば、先ほどの「GOTO_sample」プロシージャーを使います。

ワークシート関数「Match」はよく利用されますが、「検査値」が「検索範囲」に存在しないとエラーが返ってきます。

この関数の利用には必ず、「エラー処理コード」と1セットにして記述する必要があります。

そこで使うのが、「On Error Goto」になります。

VBAGotosample008

「◎」が4つまでの場合はエラーが発生し、コード停止を回避するために「err_mess」に処理が移ります。

「◎」が5つ以上の場合は、「Exit Sub」で終了します。

VBAGotosample006a
VBA
Sub OnEroorGoto_Sample()
    Dim RR As Variant
        Call Module1.GOTO_Sample
            On Error GoTo err_mess
            RR = WorksheetFunction.Match("×", Range("B1:B9"), 0)
            Range("A" & RR).Value = RR
            Exit Sub
err_mess:
            MsgBox "「×」の表示はありません。"
End Sub

Gotoの利用法まとめ

VBAGotosamplep010

この薬としてのGotoの利用はVBAコード組み立てでは、非常に重要なことだと思います。

毒の部分がクローズアップされがちですが、正に薬と思って使っていても、使い過ぎれば毒になってしまうということです。

自分しか管理しないコードの場合は、少々の毒でもOKじゃないかとは個人的に思いますが、どうでしょうか?

その毒を一杯食らったコードの実例は、こちら↓でご覧いただけます。

sheethiddeneyecatch003 シート非表示ソフトのVBAコード Gotoでジャンプ移動

エクセルVBAを独習するのに参考書は欠かせません。 参考書選びは自分に合った「相棒」にできるものを選んでいきたいです。

vbastudyeyecatch2 エクセルVBAの独習でおすすめ参考書を7冊選ぶ。良書との出会いは大切です

今回の記事はここまでです。   最後までご覧いただき有難うございました。

エクセルVBA最速理解で必要な知識を集めよう!

エクセルVBA業務ツールで日常の業務改善を行いましょう。

VBAコードの記述記事においては、その記述には細心の注意をしたつもりですが、掲載のVBAコードは動作を保証するものではりません。 あくまでVBAの情報の一例として掲載しています。 掲載のVBAコードのご使用は、自己責任でご判断ください。 万一データ破損等の損害が発生しても当方では責任は負いません。

アンケートでポイ活しよう!!

アンケートに答えれば答えるほど ”使える” ポイントがたまります。

NTTコム サーチ

af_banner01

Dstyle web

dstyleweb_logo
dstyle_320x50-min