こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

ExcelのマクロでのExit Subの役割とは

久しぶりに Excel のマクロについて
質問させていただきます。
実際に作ったマクロはとても長いのですが
問題となった部分を簡潔にまとめて記載します。

Sub test()
Range("A1") = 0
入力 = Application.InputBox("入力")
If 入力 = "a" Then
Call test
End If
Call test2
End Sub

Sub test2()
Range("A1") = Range("A1") + 1
End Sub

これにより
「a」を入力している限りは先へ進めず
「a」以外を入力したところで
セルA1に「1」と表示させるつもりでした。
しかし実際には
「a」を入力した回数プラス1が
セルA1に表示されてしまいます。

仕方がないので

Call test

の後に

Exit Sub

と入力したところ、希望通り
セルA1には「1」と表示されました。
Exit Sub
を入力しなくても
何度も test() に戻るだけで
Range("A1")
に影響するのは、最後の
Call test2
による1回だけと思うのですが
なぜこのような結果になるのでしょうか。

今回もマクロについては
まだまだ素人だと痛感しているところです。
回答をよろしくお願いいたします。

投稿日時 - 2019-06-26 20:57:18

QNo.9629426

暇なときに回答ください

質問者が選んだベストアンサー

>何度も test() に戻るだけで
ではなく、test()から、test()を呼び出すと、コンピュータ上では、同じコードのtest()ではあるのですが、別のtest()ととして呼び出すのです。
これを再帰呼び出しといいます。
なので、なんどもtest2()が呼び出されてしまうのです。

投稿日時 - 2019-06-26 21:18:39

お礼

早速のご回答
ありがとうございました。
大変分かりやすく
説明していただきました。
おかげさまで
とてもすっきりしました。

「再帰呼び出し」という言葉
これからしっかり勉強したいと思います。

何かありましたら
そのときはまた
ぜひよろしくお願いいたします。

投稿日時 - 2019-06-26 21:46:39

ANo.1

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

すでにANo.1さんの「再帰呼び出しをしてしまっている」というので正解なんですが、別の説明をしてみます。

「『call test』と書けば、制御が先頭に移る」と考えたのでしょうけど、call文を使ってしまったために、副作用が生じています。

単に命令実行位置を変えたければ、GoTo文を使うべきだったでしょう。
サブルーチンの頭に「test_top:」とラベルを書いておき、「call test」ではなく「GoTo test_top」と書けば、お望みの動作になったかと思います。

--

ではサブルーチン呼び出しではなぜうまく行かないか?

サブルーチンを呼び出すってことは、呼び出す元の位置に、サブルーチン内容を丸々コピペするのと同じですよね。

つまり、サブルーチンtest内で「call test」と書いたなら、そこにまたtestサブルーチン全体をコピペしたことになってしまいます。

callによって単に制御が頭にもどったのではありません、サブルーチン呼び出しが一段深くなった上で、新たにtestサブルーチンの先頭から実行しているんです。
停止条件が満たされない限り、何重にもtestが呼び出される、すなわちtestサブルーチンのコピペが行われる、プログラムになってしまっているのですね。

停止条件が成立すれば、test2を呼び出しサブルーチン呼び出しは一段階終了、元の呼び出しcall文の次から実行を再開します。
一度停止条件が成立すれば、これまで何重にもたまったcallが解消されていき、その度にtest2が呼び出されます。

なので、最終結果として、ご質問にかかれた動作をしてしまいました。

--

このように、サブルーチン内から自分自身を呼び出すことを「再帰呼び出し」といい、プログラミング手法のひとつです。

使える場面では便利な手法です。
例えば、HDDの全フォルダ、全段階に渡って特定ファイルを調べる、とか。

今回は使うべき場面ではなかったのではないでしょうか?

投稿日時 - 2019-06-26 22:18:04

あなたにオススメの質問