Excel VBAでのpublic変数の使用方法についての質問

このQ&Aのポイント
  • Excel VBAで公開変数(public変数)を使用したい場合、他のプロシージャでも共通の変数を使用するために設定しますが、うまく機能しない場合があります。testmainプロシージャでiに値を代入しても、testsubプロシージャでその値が参照できない状態になります。公開変数を使用してもプロシージャが終了すれば変数はクリアされるため、他の方法を検討する必要があります。
  • 公開変数を使用する場合、プロシージャが終了すると変数はクリアされるため、他のプロシージャでも共通の変数を使用することはできません。公開変数を使用したい場合は、参照渡しや戻り値を使用するなどの方法を検討する必要があります。
  • Excel VBAでの公開変数(public変数)の使用方法についてです。公開変数を使用しても、プロシージャが終了すると変数はクリアされてしまうため、他のプロシージャでも共通の変数を使用することができません。代わりに参照渡しや戻り値を使用することで、共通の変数を利用することができます。公開変数を使用する場合、その制約に注意する必要があります。
回答を見る
  • ベストアンサー

excel/vba/public変数

excel VBAで下記のようなコードを書きました。 他のプロシージャでも共通の変数を使用したいと思っています。 その為、public変数を宣言して使用したいと設定しましたが。 うまくいきません。 testmainを実行し、iに何も入っていないことを確認しました。 その後『1』を代入し、testmainは終了します。 testsubをその後実行し、iに先ほど代入された値を確認しようとしても何も代入されていない状態です。 全プロシージャでその変数を使用したいと思っているのですが、 何か方法、もしくはこのような使用方法ではないのでしょうか? public変数を使用してもプロシージャが終了すれば変数はクリアされるのでしょうか? 構造化の方法の問題上参照渡しや、戻り値など、指定する方が複雑になっていきます。 ご指導よろしくおねがいします。 Public i As Variant Sub testmain() MsgBox test i = 1 End Sub Sub testsub() MsgBox i End Sub

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

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.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)
回答No.5

これは、かなり有名な問題だったと思います。 [VBA] Public 宣言された変数の有効期間 http://support.microsoft.com/kb/408871/ja Access では、普通に対策しておけば、あまりお目にかかりませんが Excel では頻繁に遭遇してしまいます。 対策としては、ブックを開いている間有効にしたい変数は ワーク用の非表示シートを作成し、そこに書き込むようにしています。

  • kmetu
  • ベストアンサー率41% (562/1346)
回答No.4

ちなみにpublic変数 を利用せずに値をどこかのシートの目立たないセルに書き込んでおいて利用すると言う手もあります。

  • kmetu
  • ベストアンサー率41% (562/1346)
回答No.3

testmain()を実行した後に該当ファイルを保存したりすると変数の値はリフレッシュされますがいかがでしょうか ところで MsgBox test は何を表示しようとしたのでしょうか?

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

>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)
回答No.1

testsubのmsgboxで「1」と表示されます。 testmainで、i=5とすれば、 testsubのmsgboxで「5」と表示されます。 これでいいのではないですか。 もし、うまくいかないとすれば、 このコードのせいではなさそうです。

関連するQ&A

  • access vbaで、変数を含んだプロシージャ

    access vbaで、変数を含んだプロシージャを実行したい。 【やりたい事】 下記の矢印の部分で「msg1」「msg2」「msg3」を実行したい。 Public Sub test() For i = 1 To 3 msg & i ←ここを、どのように記述すればいいのでしょうか? Next End Sub Public Sub msg1() MsgBox "ok1" End Sub Public Sub msg2() MsgBox "ok2" End Sub PublicSub msg3() MsgBox "ok3" End Sub よろしくお願いします。

  • 再度,ExcelVBA,public変数が消える

    大変申し訳ありません。一度、この件で質問し、その回答を締め切ったばかりなのですが、やはりもう少し知りたくて質問させていただきます。 ある方の回答への補足で、以下のマクロを具体例としてあげました。ただし、以下のマクロは、時にはpublic変数が消えてしまいますが、しかし、消えないこともあります。 消える理由として、 回答していただいたものから考えて、 1.End Sub を通っていないままに終了しているから 2.不完全なマクロ 3.きちんと作られたマクロの流れ(ルーチン)ではない流れがある 4.「Public 変数は、標準モジュールを経由して、ローカルのUserForm に供給、しかし、それを戻すということはしない。つまり、a.ローカルで発生した値 →標準モジュールのPublic 変数 →UserFormのローカルのプロシージャ b.標準モジュールのPublic 変数 → UserFormのローカルのプロシージャ   ※ただし、起動時の一回きり、それ以上の持ち回しはしない。逆もしない。」この件に関して、以下のマクロに問題がある。 この様なことを考えました。 4.の場合、testMainからtest1.showを呼び出し、a=10とするが、このaの値は、testMainには戻らない(戻らないことがある)のでしょうか、あるいは、testMainのend sub の後は値が保障されないのでしょうか。 あるいは、 Worksheet_SelectionChange でend sub で終わっているので、それ以降は値が保持されないのでしょうか。 あるいは、どこかに欠陥のあるマクロなのでしょうか。 http://okwave.jp/qa/q6420530.html への回答のno.6の例のマクロでendをコメントにするかしないかで、endをコメントにした場合はend subで終わった後、値が保持されています。このこととも合わせて考えると、どこに問題があるのか、どのような問題があるのか、よく分からなくなってしまいます。 よろしくお願いします。 標準モジュールにーーーーーーーーーーーーーーーーー Option Explicit Public a As String Sub ini() MsgBox "初期化します" a = "5" End Sub Sub testMain() If a = "" Then ini MsgBox a test1.Show End Sub test1 というフォームのモジュールにーーーーーーーーーーーーーー (このフォームに コマンドボタンがあります。) Private Sub CommandButton1_Click() a = "10" Unload Me End Sub シートのモジュールにーーーーーーーーーーーーーーーーー Option Explicit Private Sub Worksheet_SelectionChange(ByVal Target As Range) testMain End Sub

  • プロシージャーの外で宣言した変数の値の破棄の仕

    プロシージャーの外で宣言した変数の値の破棄の仕方について教えてください。 ++++++++++++++++++ Dim i As Long Sub test() i = i + 10 MsgBox i End Sub ++++++++++++++++++ を実行すると、どんどん値が増えていきますが、 回避するには、 ++++++++++++++++++ Dim i As Long Sub test() i = i + 10 MsgBox i i = 0 End Sub ++++++++++++++++++ とするしかないのでしょうか? ++++++++++++++++++ Dim i As Long Sub test() i = i + 10 MsgBox i Set i = Nothing End Sub ++++++++++++++++++ としたら、エラーになりました。

  • Excel2003 VBA 変数のスコープについて

    お世話になります。 Excel VBAで、Application.Run "Book1!Test"によって、他ブックのプロシージャを実行することができますが、その「他ブックのプロシージャ」で使用した変数を、Application.Run "Book1!Test"終了後も、使用できるような変数宣言の仕方(スコープ)はあるのでしょうか。 よろしくお願いします。

  • 〔EXCEL:VBA〕切捨ての関数は?

    初歩的な質問で申しわけありません。 例えば、ある計算結果を「変数:x」に格納して、この「x」の値を切り捨てるにはどのような記述になりますでしょうか?簡単なプロシージャで教えてください。 ------------------------ Sub 切捨て計算() x = 100 / 3 〔変数:xの切捨て〕 MsgBox "変数xは:" & x End Sub ------------------------- 〔 〕内を教えてください。

  • VBAのプロシージャのことで

    TEST1のプロシージャ内に使用している readfileという変数の中にテストという文字列を代入し、 文字列が代入された状態で Callによって別のプロシージャを読みにいったとき TEST(変数)に入った文字列ごと持っていくには どの様に記述すればよいかどなたか教えていただけませんでしょうか・・・。。 ----------------------------------------------------------- Sub TEST () Dim readfile As String readfile = "テスト" Call TEST2 End Sub ----------------------------------------------------------- Sub TEST2() readfile ←テストという文字列をTESTプロシージャから持ってきたい End Sub ----------------------------------------------------------- 単純に書いてみたコードですが、この様なことは可能なのでしょうか? すいませんがいただけないでしょうか><;

  • ExcelVBA Static変数の初期化

    Static変数はファイルを一旦終了しないと0にリセットできないのでしょうか? 出来ないとすればStatic変数に代わりそういうことができる方法はありますか?(セルに番号を代入するのは無しで) Sub 番号てすと() Static g As Integer MsgBox "今のG= " & g g = g + 1 MsgBox "次のG= " & g End Sub

  • VBAのプロシージャーと変数の名前の区別について

    VBAの初心者です。教えてください。 Sub ex() Dim a As Integer Dim b As Integer a = 2 a a, b MsgBox b End Sub Sub a(a As Integer, b As Integer) b = a End Sub 上記のプログラムを実行するとうまくいきません。VBAのプロシージャーと変数って同じ名前を使うとだめなのですか?教えてください。

  • グローバル変数などについて

    Option Explicit Dim str1 As String '・・・(1) Sub テスト() Dim str2 As String '・・・(2) str1 = "テスト1" str2 = "テスト2" MsgBox str1 MsgBox str2 End Sub (1)はグローバル変数と言うとの事ですが (2)は何変数と言うのでしょうか? ローカル変数ですか? また、(1)がdimではなく、 Public str1 As String となった場合でも、 プロシージャーの外にあれば、グローバル変数と言うのでしょうか?

  • 静的変数の現在溜まってる値を知る方法

    Sub 静的変数() Static x As Long x = x + 10 MsgBox x End Sub このプロシージャーを実行するとXの値がどんどん加算されていきますが マクロを実行してない時にxの値を取得する方法はありますか? スッテプインやウォッチウインドウで確認すれば、マクロ実行中にxの値を確認できますが マクロを実行してない時に調べる方法があれば教えてください。 ちなみにウォッチウインドウで見てみると 値は<対象範囲外> 型はEmptyとなります。 (もしマクロを実行してなきゃわからないというのであればそれでも大丈夫です)

専門家に質問してみよう