- ベストアンサー
Excel VBAでのpublic変数の使用方法についての質問
- Excel VBAで公開変数(public変数)を使用したい場合、他のプロシージャでも共通の変数を使用するために設定しますが、うまく機能しない場合があります。testmainプロシージャでiに値を代入しても、testsubプロシージャでその値が参照できない状態になります。公開変数を使用してもプロシージャが終了すれば変数はクリアされるため、他の方法を検討する必要があります。
- 公開変数を使用する場合、プロシージャが終了すると変数はクリアされるため、他のプロシージャでも共通の変数を使用することはできません。公開変数を使用したい場合は、参照渡しや戻り値を使用するなどの方法を検討する必要があります。
- Excel VBAでの公開変数(public変数)の使用方法についてです。公開変数を使用しても、プロシージャが終了すると変数はクリアされてしまうため、他のプロシージャでも共通の変数を使用することができません。代わりに参照渡しや戻り値を使用することで、共通の変数を利用することができます。公開変数を使用する場合、その制約に注意する必要があります。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
質問者さんの話から少し離れて、専門的になってしまうのですが、 #5さんの引用先の Microsoft サポートの中「 Public 宣言された変数の有効期間」の 「モジュールの編集、プロジェクトの構造の変更、コンパイルエラーの発生、参照設定の変更、デザインモードへの切り替え、コントロールを削除して [元に戻す] を実行するなどのタイミングで変数が破棄される場合があります。」 これ話自体はごもっともというか、実務的にはあまり意味がありません。一般的に問題になるのは、コンパイルエラーじゃなくて、たぶん、Runtime Error やEndメソッドです。 Rumtime Error は、On Error Goto ErrHandler 等のエラートラップで回避できますが、しかし、End メソッドは使えません。 要するに、Sub ---> End Sub や Function ---> End Function という括りを終えないと、モジュールレベル変数やPublic 変数が飛んでしまうわけです。だから、End メソッドが使えません。 以下は、二回以上繰り返します。End をコメント・ブロックしたりしなかったりして、違いを比べてみるとよいです。 Dim i As Variant Sub Main2R() If i = "" Then SubTest2 End If MsgBox i End '←End メソッドがあると、変数が確保できません。 End Sub Sub SubTest2() i = 1 MsgBox "Let " & i End Sub 変数というものは、代入された値であって、その都度変化するものですから、ひとつのルーチンの中で確保されればよいはずです。それ以上のスパンを考えないほうが良いのかもしれません。参照渡してもよいのですが、例えば、プロシージャからUserForm に渡す場合などは、Public変数のほうが楽なのです。 定数なら、Public Const にすればよいのであって、わざわざ、変数に置く必要はないです。変化するもので固定的に置きたいなら、格好は悪いですが、私は、CustomPropertiesに置いたり、iniファイルに置いたり、秘匿性のものなら、レジストリに置いたりします。まだ、一般の人には分からない場所もあります。人によっては、PERSOANAL.XLS(b)の非表示のシートに置いているようですが、PERSONAL.XLS(b)は、脆弱性があるのでお勧めしません。MSでも、アドインの中のシートひとつを書き込みはしないものの値を置いているものもあるようです。(書き込みはしないはずです。書き込みをすると、デジタル署名が壊れるはずです)なお、私は、シートや非表示シートを使うことは滅多にしません。あくまでも、VBAはVBAの領域の中で処理しようとします。Excelは、他のOfficeと違って、標準モジュールを使い、そのモジュールとそのプロシージャは、分離して使うことがあるから、グローバル変数を多用するのだと思います。
その他の回答 (5)
- bonaron
- ベストアンサー率64% (482/745)
これは、かなり有名な問題だったと思います。 [VBA] Public 宣言された変数の有効期間 http://support.microsoft.com/kb/408871/ja Access では、普通に対策しておけば、あまりお目にかかりませんが Excel では頻繁に遭遇してしまいます。 対策としては、ブックを開いている間有効にしたい変数は ワーク用の非表示シートを作成し、そこに書き込むようにしています。
- kmetu
- ベストアンサー率41% (562/1346)
ちなみにpublic変数 を利用せずに値をどこかのシートの目立たないセルに書き込んでおいて利用すると言う手もあります。
- kmetu
- ベストアンサー率41% (562/1346)
testmain()を実行した後に該当ファイルを保存したりすると変数の値はリフレッシュされますがいかがでしょうか ところで MsgBox test は何を表示しようとしたのでしょうか?
- Wendy02
- ベストアンサー率57% (3570/6232)
>public変数を使用してもプロシージャが終了すれば変数はクリアされるのでしょうか? >構造化の方法の問題上参照渡しや、戻り値など、指定する方が複雑になっていきます。 Public ステートメントは基礎レベルですから、ここでつまずいてしまうと、その先の組み立ては難しいかと思います。 サンプルコードとしては、VBAの試験では以下のような内容が出てきます。 標準モジュールで、Public ステートメントは、主に明示的に入れるわけです。 Dim i As Variant Sub Main1() MsgBox i '(1) SubTest1 MsgBox i '(2) End Sub Sub SubTest1() i = 1 End Sub 'では、上のコードを具体的に使えるようなコードにする場合は、 'すでに変数を宣言されているとします。 Sub Main2() If i = "" Then SubTest2 End If MsgBox i End Sub Sub SubTest2() i = 1 End Sub >public変数を使用してもプロシージャが終了すれば変数はクリアされるのでしょうか? そういうことはないけれども、エラーなどが発生したりすると、モジュールレベルやグローバルの変数等は抜けることがあるので、実際のコードでは、上記のMain2()のように常に抜けを確認しなくては使い物にはなりません。 意外に厄介なコードになります。これを確実にするなら、Class を利用することになりますが、VBA等では、読みにくくなるかもしれません。 参照渡しのほうが確実ですが、それは、内容にもよります。
- okormazd
- ベストアンサー率50% (1224/2412)
testsubのmsgboxで「1」と表示されます。 testmainで、i=5とすれば、 testsubのmsgboxで「5」と表示されます。 これでいいのではないですか。 もし、うまくいかないとすれば、 このコードのせいではなさそうです。