• ベストアンサー

VBA 変数の受け渡し

エクセルVBAで標準モジュール内でインプットボックスに入力した変数をユーザーフォームに受け渡してユーザーフォーム内のリストボックスに表示させる場合どのように変数の受け渡しを行えばよいか教えてください。 現在は、一度ワークシートの任意のセルに値を書き出し、その後ユーザーフォームのイニシャライズで先ほどのセルから値を受け取るようにしています。 標準モジュールではインプットボックス入力後「UserForm1.Show」でユーザーフォームの立ち上げを行っています。

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

  • ベストアンサー
  • imogasi
  • ベストアンサー率27% (4737/17069)
回答No.1

質問の標題が大上段にかぶった表現なんだが、下記が参考になれば。 ーー 標準モジュールに Sub test02() Dim x(10) j = j + 1 '-- Do x(j) = InputBox("リスト項目") If x(j) = "" Then Exit Do j = j + 1 Loop '-- UserForm1.ListBox1.List = x UserForm1.Show End Sub 空でENTERで入力は終りの仕組み。 UserForm1にリストボックスを1つ貼り付け。 Userform1の「コードの表示」で Private Sub ListBox1_Click() Static i i = i + 1 'MsgBox ListBox1.ListIndex 'MsgBox ListBox1.List(ListBox1.ListIndex) Worksheets("Sheet1").Cells(i, "A") = ListBox1.List(ListBox1.ListIndex) End Sub リストボックスのアイテムをクリックするごとに、シートのA列の A1セル->A2->A3・・に選択したアイテムを順次入力。 (この部分は、質問には何も言及してないが、この目的ぐらい書くべきでは) 初めのj=j+1はjを初期化して1にする方策。言語によっては初期化してないjに加算できるかえ、となると思うが、VBAでは私の経験では、通るようだ。 配列に貯めた文字列を、1行でリストボックスのAddItemできたのが、すっきりできた。 目的によっては、エクセルの標準では、入力規則のリストなどを使う方策が別にあるが、それではできないのかな。 UserFormを使う方法は、むつかしい面もある。 理論的な仕組みの解説本は(ユーザーフォームと題名になっている市販本は数本しかなく、他は、VBAの解説の1章でしかなく、WEB記事にも見つけにくい。手探り派の小生の上記には、不完全なケースもあるかもしれないので、よくテストして、考えて参考にするとか、使ってください。

homma
質問者

お礼

imogasi様 お礼メールが遅くなり申し訳ありませんでした。 大変参考になりました。

その他の回答 (1)

回答No.2

こんにちは。 "変数の受け渡し"については、後述しますが、 そのことが主題なのか、とか、ちょっと判断付かない点もあるので、 3例でお応えしますが、まずは、 変数を介さないで直接リストを追加する方法から。 (以下、InputBox()をループさせるのはこちらで用意した仮の設定です) ' ' // 標準モジュール Sub AddListItem() Dim s As String   Load UserForm1 ' 省略可   Do     s = InputBox("")     If s = "" Then Exit Do     UserForm1.ListBox1.AddItem s   Loop   UserForm1.Show End Sub ' ' // 後々のことも考えて、少し補足しておきます。 > ユーザーフォームの立ち上げ 意味するのは、  Load UserForm1 のようなユーザーフォームを読込む記述で、これは省略可能です。 直後に、ユーザーフォーム側で  Private Sub UserForm_Initialize() イベントが発行されます。 続いて  UserForm1.Show という記述でユーザーフォームを表示します。 表示実行時中の最初のタイミングで、 ユーザーフォーム側で  Private Sub UserForm_Activate() イベントが発行されます。 ユーザーフォーム読込みから表示までの流れは、 どう書いても変わることはありません。 ただ、読み込み処理の命令を省略して、 直接.Showさせる記述が一般には多い、ということです。  UserForm1.Hide で非表示にしたり、  UserForm1.Show で再表示したりいて、 いよいよユーザーフォームを使わない、となったら、  Unload UserForm1 とするのが本来の使い方です。 何が言いたいかというと、 ユーザーフォームを読み込む時(_Initialize)には、 UserformをUnLoadする(×ボタン等で閉じる)まで不変となる ユーザーフォームのデザイン上の属性などを設定します。 表示する時に設定する必要があると思われるものは  Activate()イベントに書いておいた方が、後々困ることが減らせるかな、と。 もうひとつ、 どうせ標準モジュールのプロシージャから、.Showさせるのなら、その直前に、 標準モジュール側で、直接リストを設定するようにした方が、 結果的に扱い(管理・再編集し)易いプロジェクトになることが多いと思います。 > インプットボックスに入力した変数 がどのようなものか判りませんから、配列だった場合を次に。 ' ' // 標準モジュール Sub LetAry2ListA() Dim aryList() Dim s As String Dim cn As Long   Do     s = InputBox("")     If s = "" Then Exit Do     ReDim Preserve aryList(cn)     aryList(cn) = s     cn = cn + 1   Loop   Load UserForm1 ' 省略可   UserForm1.ListBox1.List = aryList()   UserForm1.Show End Sub ' ' // 最後に、 ご要望の"変数の受け渡し"ですが、これにも幾つかありますが、 ほぼ常識的な方法としては、Publicで宣言した変数を扱います。 Publicで宣言した変数は、 記入したVBProject全体で プロジェクトが終了するまで常に すべてのモジュールで共有される変数となります。 実際は受け渡しというより、共有ですね。 各プロシージャの実行が終了しても、 値を保持していますから、付け足し・加工しながら使えたり、 有利に使える場面も多いですが、反面、 きちんと初期化してないと、もとの値が保持されているせいで、 意図しない結果になることもあるので注意して下さい。 ' ' // 標準モジュール Public aryList() ' ←◆必ず標準モジュールの先頭、宣言部に書きます。 Sub LetAry2List() Dim s As String Dim cn As Long   ReDim aryList(0) ' 初期化   Do     s = InputBox("")     If s = "" Then Exit Do     ReDim Preserve aryList(cn)     aryList(cn) = s     cn = cn + 1   Loop   UserForm1.Show End Sub ' ' // ' ' // Userformモジュール Private Sub UserForm_Activate()   Me.ListBox1.List = aryList() End Sub ' ' // さしあたり、3例でお応えしました。 使われる頻度の高い方法にはなっているかと思います。 尚、もしも、ですが、 上記ではご質問の趣旨から逸れていて、もしかして実は、 ユーザーフォームモジュール記載のプロシージャに 標準モジュールのプロシージャ内の変数を 引数として渡したい、というような趣旨でしたら、 それはそれで別にお話できることもあるかも知れませんが、 汎用的な説明は難しくなるので、 必然性のある具体例を提示して頂ければ、再考してみます。 以上、ご参考まで。

homma
質問者

お礼

realbeatin様 お礼メールが遅くなり申し訳ありませんでした。 大変参考になりました。