一連のプロシージャが終了したあとも変数に格納されたデータなりオブジェクトへの参照なりは保持されます。 ただし、End (End Sub でも End Function でもなく、Exit Sub でも Exit Function でもなく、End。本講座では紹介していません)で強制終了された場合はすべての変数に格納された値は破棄されます。
以下、参考までに。
Option Explicit
Dim w As Worksheet
Sub hoge()
Set w = ActiveSheet
End Sub
Sub fuga()
Debug.Print w.Range("A1").Value
End Sub
Sub piyo()
End
End Sub
受講生さんの投稿
(投稿ID: 4070)
全ての変数を「モジュールレベル変数」として宣言しちゃえば、個々のサブプロシージャでは変数を宣言しなくて良いってことですから。
ただ、変数名をキチンと把握していないと、おかしな動きをするマクロのデバックに相当苦労する(変数を1つ1つ追わないとミスに辿り着けない)ようなイメージがあります。
ところで、こびとちゃんは、どのタイミングでモジュールレベル変数を開放するのでしょうか?
小川慶一さんのコメント
(コメントID: 5629)
おはようございます。
> 全ての変数を「モジュールレベル変数」として宣言しちゃえば、個々のサブプロシージャでは変数を宣言しなくて良いってことですから。
↑
それは典型的な運用の誤りです。
モジュールレベル変数は、複数プロシージャ間での値のやりとりの必要性があるとき「だけ」使ってください。
では、どうして『全ての変数を「モジュールレベル変数」として宣言しちゃえば、個々のサブプロシージャでは変数を宣言しなくて良い』という考えはダメなのか?そのデメリットは何か?ということについては、まずは考えてみてください。
> ところで、こびとちゃんは、どのタイミングでモジュールレベル変数を開放するのでしょうか?
一連のプロシージャが終了したあとも変数に格納されたデータなりオブジェクトへの参照なりは保持されます。
ただし、End (End Sub でも End Function でもなく、Exit Sub でも Exit Function でもなく、End。本講座では紹介していません)で強制終了された場合はすべての変数に格納された値は破棄されます。
以下、参考までに。
> これは便利ですね。
> 全ての変数を「モジュールレベル変数」として宣言しちゃえば、個々のサブプロシージャでは変数を宣言しなくて良いってことですから。
> ただ、変数名をキチンと把握していないと、おかしな動きをするマクロのデバックに相当苦労する(変数を1つ1つ追わないとミスに辿り着けない)ようなイメージがあります。
> ところで、こびとちゃんは、どのタイミングでモジュールレベル変数を開放するのでしょうか?
ゲストさんのコメント
(コメントID: 5708)
では、どうして『全ての変数を「モジュールレベル変数」として宣言しちゃえば、個々のサブプロシージャでは変数を宣言しなくて良い』という考えはダメなのか?そのデメリットは何か?ということについては、まずは考えてみてください。
他の方に対する返答で申し訳ないのですが、サブプロシージャの中で変数を宣言すれば、そのサブプロシージャが終わればその変数の値はなくなりますが、「モジュールレベル変数」で宣言すると別のサブプロシージャ間で同じ変数を用いた場合、前の値を引き継ぐため不具合が生じる場合があるのではないでしょうか?
小川慶一さんのコメント
(コメントID: 5709)
>他の方に対する返答で申し訳ないのですが
いえいえ (^^
>サブプロシージャの中で変数を宣言すれば、そのサブプロシージャが終わればその変数の値はなくなりますが、「モジュールレベル変数」で宣言すると別のサブプロシージャ間で同じ変数を用いた場合、前の値を引き継ぐため不具合が生じる場合があるのではないでしょうか?
それもあります。
あとは、以下ですね。
○メンテナンス性について:
個別のプロシージャ内で宣言する変数については、そのプロシージャの都合で好きに名前をつけてよいです。名前を変える際も、そのプロシージャだけの都合で即変更できます。
その一方、モジュールレベル変数については、すべてのプロシージャでその名前を使わなくてはなりませんし、名前を変えるとしたら、その変数を使っているすべてのプロシージャ内で当該変数の変数名を変更しなくてはなりません。
○可読性について:
個別のプロシージャ内で宣言する変数については、そのプロシージャ内でしか使わないものと即断できます。
その一方、モジュールレベル変数については、そのプロシージャ内でしか使わないものなのか?複数プロシージャ間でデータ交換をするためのものなのか?ということについては、コード全体を読まないと判断できません。
↑
複数モジュールがあり、プロシージャが20も30もあったとしたら、プロシージャ内で宣言してもよかった変数をモジュールレベル変数にすることで、上述のメンテナンス性、可読性の問題がどれだけプログラマーの負担になるか?ということをイメージできるかと思います。
※イメージできなかったとしたら、それは、その人がたいした規模の、あるいは構造のプログラムを書けてないということなので、受け手側の経験不足故、この話題については納得されるのはムリです。
ある程度経験を積んでから、いつかまたこの解説を読み直してください、としか言いようがないですね。
ということで、最後にひとつ理由を追加すると
○説得力について:
個別のプロシージャ内で宣言すれば済んだはずの変数までむやみにモジュールレベル変数にしていると、優秀なプログラマーからは、「経験不足で無駄の多いイタいヤツ」とは思ってもらえますが、「デキるヤツ」とは思ってもらえません。
その結果、会社でのあなたへの評価はなかなか上がらなくなります (^^;
上司さん「○○くん、『マクロ書ける』ていうけど、優秀くんから見てどう?」
優秀くん「あー、アイツ、まーまー結果は出せてるけど、コード見るとぜんぜんヒヨっ子ですよ。しかも、アイツ、僕がそう言ってコードの不備を指摘しても理解できないレベルに勘が鈍いんです」
上司さん「ふーん、優秀くんが言うんならそうだろうなー。じゃ、評価はたいしてしてあげなくてもいいな。あと、『デキるヤツだけ集めたい』て本部長が言っているプロジェクトがあるんだけど、○○くんを推薦するのはやめとこっと」
と、そんな会話があなたの知らないところでなされます (^^;
> 10367 の小川様の回答について
>
> では、どうして『全ての変数を「モジュールレベル変数」として宣言しちゃえば、個々のサブプロシージャでは変数を宣言しなくて良い』という考えはダメなのか?そのデメリットは何か?ということについては、まずは考えてみてください。
>
> 他の方に対する返答で申し訳ないのですが、サブプロシージャの中で変数を宣言すれば、そのサブプロシージャが終わればその変数の値はなくなりますが、「モジュールレベル変数」で宣言すると別のサブプロシージャ間で同じ変数を用いた場合、前の値を引き継ぐため不具合が生じる場合があるのではないでしょうか?
わかやまさんのコメント
(コメントID: 5710)
まだまだひよっこですが、お返事の内容はイメージできたように感じています。まだ仕事にいかしきれていないですが、このまま学習を続けて、みんなの仕事の負担(自分の仕事も)を減らせるようなプログラムをかけるまでがんばりたいです。
小川慶一さんのコメント
(コメントID: 5711)
もっと数を増やすとわかるかな。
より極端な例を出してみます。たとえば、以下の状態のプログラムをリライトするよう人から要求されたとしたら、どうでしょう。
○サブプロシージャが125個ある
○モジュールレベル変数が225個ある
○それぞれのモジュールレベル変数が、以下のどれなのか、コメントは一切ないので判別つかない
・複数プロシージャ間でデータ交換するために使われている
・単に、都度都度プロシージャ内で宣言するのが面倒なので、モジュールレベル変数にしているだけ
そして、変数名が自分のネーミングルールと比して気に入らないので、変更したい。
「影響箇所の調査をしなければならない」と思うだけで、頭クラクラしませんか?
> 小川様
>
> まだまだひよっこですが、お返事の内容はイメージできたように感じています。まだ仕事にいかしきれていないですが、このまま学習を続けて、みんなの仕事の負担(自分の仕事も)を減らせるようなプログラムをかけるまでがんばりたいです。