制御構文とステートメントのGotoは、利用法によって毒コードとなったり薬コードになったりします。
Gotoステートメントの利用方法のエッセンスを最速で理解できるように解説します。
こんにちは、じゅんぱ店長(@junpa33)です。
エクセルVBAのコードで、Gotoステートメントは嫌われ系のグループにはいっています。
それでも、GotoがあるのでVBAコード組み立てがスムーズに、楽に、なる事も多いと言うのも事実です。
コンテンツ
Gotoステートメントの利用法を最速理解
エクセルVBAコードを組み立てる上で、Gotoステートメントほど、毒と薬を持っているものはないかもしれません。
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
サンプルコードの実行結果です。
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関数についてはこの記事を参考にできます。
- Rnd関数についてはこの記事を参考にできます。
- Offsetについてはこの記事を参考にできます。
コード実行エラーで緊急停止させないGoto
エラーが発生する要因は色々あります。
Gotoを使ったコード停止を起こさせない利用法は、「On Error Goto」として記述します。
それは、エラーを起こす可能性のあるコードの前に記述する必要があります。
例えば、先ほどの「GOTO_sample」プロシージャーを使います。
ワークシート関数「Match」はよく利用されますが、「検査値」が「検索範囲」に存在しないとエラーが返ってきます。
この関数の利用には必ず、「エラー処理コード」と1セットにして記述する必要があります。
そこで使うのが、「On Error Goto」になります。
「◎」が4つまでの場合はエラーが発生し、コード停止を回避するために「err_mess」に処理が移ります。
「◎」が5つ以上の場合は、「Exit Sub」で終了します。
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の利用法まとめ
この薬としてのGotoの利用はVBAコード組み立てでは、非常に重要なことだと思います。
毒の部分がクローズアップされがちですが、正に薬と思って使っていても、使い過ぎれば毒になってしまうということです。
自分しか管理しないコードの場合は、少々の毒でもOKじゃないかとは個人的に思いますが、どうでしょうか?
その毒を一杯食らったコードの実例は、こちら↓でご覧いただけます。
シート非表示ソフトのVBAコード Gotoでジャンプ移動エクセルVBAを独習するのに参考書は欠かせません。 参考書選びは自分に合った「相棒」にできるものを選んでいきたいです。
エクセルVBAの独習でおすすめ参考書を7冊選ぶ。良書との出会いは大切です今回の記事はここまでです。 最後までご覧いただき有難うございました。
<記事内容についての告知>
VBAコードの記述記事においては、その記述には細心の注意をしたつもりですが、掲載のVBAコードは動作を保証するものではりません。 あくまでVBAの情報の一例として掲載しています。 掲載のVBAコードのご使用は、自己責任でご判断ください。 万一データ破損等の損害が発生しても当方では責任は負いません。
アンケートでポイ活しよう!!
アンケートに答えれば答えるほど ”使える” ポイントがたまります。