質問: excelのvba。public変数の値が消える vbaについて。excelの2003や2007を使っています。標準モジュールで public 変数を定義しました。 ユーザーformを使い、パブリック変数に値を入れたり変更し、標準モジュールに戻ったとき、そのpabulic変数が resetされてしまっている事があります。全く同じマクロで、この現象が起こることと、起こらないことがあります。excelの2003でも2007でも、同じ現象が起こります。簡単なマクロで再現性のある具体的なものを示したいと思い、試しましたが、できませんでした。簡単なマクロでは、きちんとパブリック変数は保持されています。問題のあるマクロはかなり長いものなので、とても示せません。問題がどこにあるのかわかりません。このマクロで不都合があるという具体的なマクロを示すことができない状態での質問で、申し訳ありません。 また、このようなプログラミングをしていて思ったのですが、ユーザーフォームに対してユーザーが任意の引数を渡す方法あるいは、ユーザーフォームから引数を受け取る方法はあるのですか?今は、pubulic変数を用いたり、具体的なセルに値を代入したりしていますが、どう考えてもそれはエレガントではないし、汎用性もないと思います。引数で引き渡すのが一番綺麗でいいとは思うのですが、それが可能かどうかわかりません。
回答: idは違うけれども、同じ内容の質問のようですね。 http://oshiete.goo.ne.jp/qa/6420530.html 具体的にこんなことをしています、ということをおっしゃれば、話は変わるかとも思います。 今のままでは、いくら説明しても、たぶん納得いかないだろうと思います。 最初に、#3の方のmsのサポートの文章で、 >[vba] public 宣言された変数の有効期間 この内容、ご質問者さんは、意味を誤解しているようです。 「ほとんどの場合、プロシージャ終了後も値は保持されますが、 ......public 変数がアプリケーション終了時まで有効であること を期待する vba マクロの実装は、推奨されません。」 どうして、保持した変数がなくなってしまうか、いろんな理由はあっても、完成したマクロでは、原因はひとつで、end sub を通っていないままに終了しているからです。 「ある office ドキュメントが vba のマクロを含む場合、...... public 変数 の値が有効である期間は、あるプロシージャの実行を開始 し、そのプロシージャが "end sub" で終了するまでの間のみです。」 この文章は間違いです。その話のままだったら、public 変数など意味がなくなってしまいます。値だって確保しているし、変数は動的です。しかし、実務上、構造化マクロで、きちんと作られたマクロの流れ(ルーチン)が通る間だけだと思ってよいです。 >ユーザーformを使い、パブリック変数に値を入れたり変更し、標準モジュールに戻ったとき、そのpabulic変数が resetされてしまっている事があります。 public 変数が、リセットされるというのは、マイクロソフトの文章は間違いに近いです。これは、極論すると、不完全なマクロだということです。しかし、本当に完全なコードを提供出来るかというのは、それは誰も自信などありません。だから、そういう方法を避けるわけです。 public 変数は、標準モジュールを経由して、ローカルのuserform に供給を受けるけれども、それを戻すということはしないのです。 図式化するとこうなります。 ・ローカルで発生した値 →標準モジュールのpublic 変数 →userformのローカルのプロシージャ ・標準モジュールのpublic 変数 → userformのローカルのプロシージャ ※ただし、起動時の一回きり、それ以上の持ち回しはしない。逆もしない。 「ユーザーフォームに対してユーザーが任意の引数を渡す方法 ユーザーフォームから引数を受け取る方法はあるのですか?」 出来ないわけではありませんが、これらは、変数で渡すということはしないということです。 >ただ、ユーザーフォーム aus 全体で参照し値を変更できる 変数a のようなものを、使えたらいいなあ、と思い、 理屈では、一旦、標準モジュールのpublic 変数に送っておいて、そこから他のプロシージャ等に送ればと思いますでしょうが、それはしないということです。ルーチンが別だからです。 私の基本的な設計の考え方を示しておくと、userform自身とか、その中にあるものは、oleオブジェクトのインスタンスです。つまり、モノ(オブジェクト)がある限りは、値は確保しているのです。だから、userformが残っている以上は、変数ではなくて、モノから、値を取得するのです。そのためには、userform はmodalモードを、offにしておくのが良いわけです。 例えば、userform1.textbox1.value とかで取れるわけです。 これは、システム設計の話で、それを見れば分かっていただけます。非表示のワークシートのセルに書くような話は、それは状況(渡す変数の数)によります。ただ、わざわざワークシートのセルに代入する必要はないということです。そのような方法はシステム設計では全体にリスクを高くするので賛成出来ないです。 私の失敗の経験から、public 変数については、ひとつのルーチン以上に用いないことです。また、動的には用いないことです。一回きりの静的な変数として使うべきです。静的といっても、static 変数の意味ではなく、文字通り変数を変化させないということです。ただし、時間の間隔やカウントなどの単純なものは別です。 public 変数が空かどうかチェックする方法も考えられますが、意味がありませんから、それなら、参照渡しにすればよいのです。