ExcelVBAで複数のUserFormの内容を保持する方法

このQ&Aのポイント
  • ExcelVBAで数十個の同じUserFormを動かす方法について説明します。
  • UserFormの中身がチェックボックスであり、各コマンドボタンから同じUserFormを呼ぶ場合に、UserFormの内容を保持する方法を教えます。
  • UserFormを複数作らずに、チェックした項目を再度表示させる方法について解説します。
回答を見る
  • ベストアンサー

ユーザーフォームのインスタンス

こんにちは。 早速質問させていただきます。 ExcelVBAでプログラムを組んでいて、 そのExcelシート上に同じUserFormを動かすためのコマンドボタンが 数十個あります。 ちなみに、UserFormの中身はチェックボックスです。 数十個のコマンドボタンそれぞれを押下後、 UserFormでチェックした項目を再度表示させたいのですが、 それぞれのコマンドボタンから同じUserFormを呼んでいるため、 UserForm.Hide では、他のコマンドボタンでチェックした内容が 出力されてしまいます。 どのようにしたら、UserFormを複数作らずに UserFormの内容を保持できるでしょうか。 回答よろしくお願いします。

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

  • ベストアンサー
  • takkunnet
  • ベストアンサー率74% (32/43)
回答No.5

こんな感じでいかがでしょうか。 【実装方法】 1.まず、Moduleの定義を以下のように変更 <現在> Public frmForm1 As New UserForm1 Public frmForm2 As New UserForm1 Public frmForm3 As New UserForm1 <変更後> Public frmForm() As UserForm1 'UserForm1用動的配列 Public Const MAX_FORMS As Long = 5 'UserForm1の最大使用数 2.Moduleに次のプロシージャを追加 'フォーム配列の初期化を行う Public Sub InitForm() Dim i As Long 'エラーが発生したら初期化処理を実行 On Error GoTo InitProcess 'frmFormの最大添え字が取得できたら既に初期済みと判断 'できるため、取得できるかどうかやってみる。 '初期化していない場合はエラーが発生するので初期化処理 'を実行する i = UBound(frmForm) '処理を抜ける Exit Sub InitProcess: '配列の初期化 ReDim frmForm(1 To MAX_FORMS) 'フォームのインスタンス作成 For i = 1 To MAX_FORMS Set frmForm(i) = New UserForm1 Next End Sub 3.2のプロシージャ「InitForm」をボタン押下時の処理に追加する。 また、使用する変数を「frmForm1」から「frmForm(1)」に変更する。 <現在> frmForm1.Show <変更後> Call InitForm() frmForm(1).Show 多少複雑になりますが、上記対応でループ化が可能です。

marimo-
質問者

お礼

ありがとうございます。できました!!! こんなに細かく教えていただけるとは思いませんでした。 今はただコピペしてループできた事が確認出来ただけなので、 コードをじっくり読み直して理解したいと思います。 本当にありがとうございました。

その他の回答 (4)

  • takkunnet
  • ベストアンサー率74% (32/43)
回答No.4

エラー内容についてですが、 UserForm1という「プライベートオブジェクトモジュール(外部アクセス不可能なオブジェクト=フォームなど)」をSheet1という「パブリックオブジェクト モジュール(外部アクセス可能なオブジェクト=シートなどのこと)」のなかで「Public(パブリック=外部アクセス可能)」にすることができないという意味です。 つまり、要約すると、「Sheet1の中でUserForm1をPublic宣言してはいけません」となります。 これを解消するためには「Public」を「Private」に変更すれば問題ありません。 注意書きが足りなくて混乱させてしまい申し訳ありません。

marimo-
質問者

お礼

いえいえ。とんでもございません。 とてもわかりやすくて 勉強になりました。 できれば#3補足質問宜しくお願いします。

  • takkunnet
  • ベストアンサー率74% (32/43)
回答No.3

Moduleへの入力が妥当だと思うので以下のようにしてみてください。 VBEのメニューより 「挿入」-「標準モジュール」 を選択 ※ここで追加された「Module1」というやつが通常「Module」と呼ばれるものです。ちなみに、marimo-さんが作成した「UserForm1」が「Form」といわれるやつです。 追加された「Module」の中に「Option Explicit」があればその下に Public frmForm1 As New UserForm1 Public frmForm2 As New UserForm1 Public frmForm3 As New UserForm1 を入力します。 ※無い場合はそのまま先頭から記入します。

marimo-
質問者

補足

ありがとうございます。 フォームを別インスタンスで開くことが出来ました。 もう一つ質問してもよろしいでしょうか。 UserFormが5つ(UserForm1~UserForm5)ありまして、 それぞれ5つ別インスタンスで開きたいのですが、 何かよい方法あるでしょうか。 Moduleの中で Public frmForm1 As New UserForm1 Public frmForm2 As New UserForm1 Public frmForm3 As New UserForm1 Public frmForm4 As New UserForm1 Public frmForm5 As New UserForm1 ×5 するのは、汚すぎるんで・・・ For I = 1 To 5 Next かなんかでループできたら…とおもっているのですが。

  • takkunnet
  • ベストアンサー率74% (32/43)
回答No.2

変数に値を退避し、それを初期化時に設定してやるのがわかりやすい方法だと思います。 ただ、他の方法でも可能です。 具体的には以下の方法で実装します。 (オブジェクト指向の考えが必要になります) 【実装方法】 ※UserForm1 を作成しそれを 3つ 使用したい場合 ※ModuleやSheetなどForm以外で変数を定義します。 Public frmForm1 As New UserForm1 Public frmForm2 As New UserForm1 Public frmForm3 As New UserForm1 ※ボタンを押下したときに以下の処理を実行します。 【ボタン1】 frmForm1.Show 【ボタン2】 frmForm2.Show 【ボタン3】 frmForm3.Show その後、それらのフォームの値を使用するときに frmForm1.CheckBox1.Value などとして値を取得します。 「UserForm1」ではなく「frmForm1」を使用するように注意する必要があります。

marimo-
質問者

補足

>※ModuleやSheetなどForm以外で変数を定義します。 どこで定義したらよいのかいまいちわかりません。 Sheet1のOption Explocitの下にpublic form1 As New UserForm1と 追加したところ以下のエラーが表示されます。 コンパイルエラー: プライベートオブジェクトモジュールを、パブリックオブジェクト モジュール内で、パブリックプロシージャの引数または戻り値、 パブリックデータメンバ、またはパブリックのユーザ定義型の フィールドとして、使用する事は出来ません。 どういう意味かさっぱりわかりません。 ご教授願います。

  • hana-hana3
  • ベストアンサー率31% (4940/15541)
回答No.1

>Excelシート上に同じUserFormを動かすためのコマンドボタンが数十個あります。 このような事をする意味がわかりませんが・・・ チェックの有無をはっきりさせたいなら、こちらにチェックボックスを置くべきかと思います。 また、ボタンの表示(文字)を変更するのも一つの方法かと思います。 状態を記憶させたいなら、標準フォームにグローバル変数(Public 宣言)を置いて、個々の変数に1対1にするとか、配列変数に状態を格納すると良いでしょう。

関連するQ&A

  • ExcelVBAのユーザーフォームについて

    ExcelVBAのユーザーフォームについて ExcelVBAをゼロから独学で学んでる超初心者です。 ExcelVBAでデータベースを作っています。sheet1に配置してあるコマンドボタンでuserform1を開きそこに配置してあるlistbox1を選択するとuserform2~Xが開く設定にしています。 listbox1の内容はsheet2のデータのタイトルA~X(2列目~X列目)を読みに行っています。 userform2~Xの内容はsheet2のデータのタイトルA~Xのの内容を個別に作成しています。 流れはタイトルA(userform1-listbox1(1列目))を選択するとタイトルAの内容を表示(userform2)するというものです。userform2~Xはsheet2の上から順番に作っています。 sheet2の2列目の内容(タイトルA)→userform2 sheet2の3列目の内容(タイトルB)→userform3 という感じです。この状態だと問題なく開いていくのですが。このデータベースは後からタイトルをどんどん増やしていきます。そして、増やすたびにあいうえお順に並び替えをします。 そうすることによってタイトルと内容が合わなくなっていきます。例えば、 sheet2の2列目の内容が5列目(タイトルD)の内容に変更 sheet2の3列目の内容が2列目(タイトルA)の内容に変更 みたいな感じでバラバラになってしまいます。 流れがタイトルD(userform1-listbox1(1列目))を選択→タイトルA(userform2)を表示となってしまいます。 並び替えを行ってもタイトルとuserformがセットになる タイトルD(userform1-listbox1(1列目))を選択→タイトルD(userform4)を表示 となる様にするにはどうしたらよいのでしょうか? へたくそな説明でわかりにくかもしれないですが一生懸命書き込みました。 宜しくお願い致します。

  • ExcelVBAのユーザーフォームのリンクについて

    ExcelVBAのユーザーフォームのリンクについて 以前質問(5991009)したのですが内容が間違えていたので訂正して再度質問します。  ExcelVBAをゼロから独学で学んでる超初心者です。 ExcelVBAでデータベースを作っています。sheet1に配置してあるコマンドボタンでuserform1を開きそこに配置してあるlistbox1を選択するとuserform2~Xが開く設定にしています。 listbox1の内容はsheet2のデータのタイトルA~X(2行目~X行目)を読みに行っています。 userform2~Xの内容はsheet2のデータのタイトルA~Xのの内容を個別に作成しています。 流れはタイトルA(userform1-listbox1(1行目))を選択するとタイトルAの内容を表示(userform2)するというものです。userform2~Xはsheet2の上から順番に作っています。 sheet2の2行目の内容(タイトルA)→userform2 sheet2の3行目の内容(タイトルB)→userform3 という感じです。この状態だと問題なく開いていくのですが。このデータベースは後からタイトルをどんどん増やしていきます。そして、増やすたびにあいうえお順に並び替えをします。 そうすることによってタイトルと内容が合わなくなっていきます。例えば、 sheet2の2行目の内容が5行目(タイトルD)の内容に変更 sheet2の3行目の内容が2行目(タイトルA)の内容に変更 みたいな感じでバラバラになってしまいます。 流れがタイトルD(userform1-listbox1(1行目))を選択→タイトルA(userform2)を表示となってしまいます。 並び替えを行ってもタイトルとuserformがリンクする。 タイトルD(userform1-listbox1(1行目))を選択→タイトルD(userform4)を表示 となる様にするにはどうしたらよいのでしょうか? それともデータベースの考え方が根本的に違うのでしょうか。 へたくそな説明でわかりにくかもしれないですが一生懸命書き込みました。 宜しくお願い致します。

  • 複数のユーザーフォームをコマンドボタンにて表示・非表示させるには

    VBA勉強中のものです。 複数のユーザーフォームをコマンドボタンを使用して画面への表示切替を考えております。 例)ユーザーフォーム1,ユーザーフォーム2,ユーザーフォーム3のそれぞれにコマンドボタン1,コマンドボタン2,コマンドボタン3を作成し、   コマンドボタン1→ユーザーフォーム1を表示   コマンドボタン2→ユーザーフォーム2を表示   コマンドボタン3→ユーザーフォーム3を表示 とするようなことを考えおります。  そこで、下記のようにコードを作成したのでですが,一度表示させたユーザーフォームを再度表示させようとコマンドボタンをクリックしたら、「フォームはすでに表示させているのでモーダル表示はできません」とエラーがでてしまいます。   どなたか、どのようにしたらいいかご教授ねがいます。 サンプルコード) --------------------------------------------------- 'UserForm1のコード Private Sub CommandButton2_Click() Call UserForm2_show UserForm1.Hide End Sub Private Sub CommandButton3_Click() Call UserForm3_show UserForm1.Hide End Sub ---------------------------------------------------- 'UserForm2のコード Private Sub CommandButton1_Click() Call UserForm1_show UserForm2.Hide End Sub Private Sub CommandButton3_Click() Call UserForm3_show UserForm2.Hide End Sub ------------------------------------------------------- 'UserForm3のコード Private Sub CommandButton1_Click() Call UserForm1_show UserForm3.Hide End Sub Private Sub CommandButton2_Click() Call UserForm2_show UserForm3.Hide End Sub ------------------------------------------------------------ '標準モジュール コード Sub UserForm1_show() UserForm1.Show End Sub Sub UserForm2_show() UserForm2.Show End Sub Sub UserForm3_show() UserForm3.Show End Sub

  • ご教授願います。

    エクセルのVBAを多少勉強致しましたが、行き詰っていますのでどなたかご教授願います。 エクセルにコマンドボタンを二つ作成 最初のコマンドボタンをクリックするとコンボボックスが現れます。 コンボボックスには1~4があります。 1はシート1""あいう""のシート 2はシート1""かきく""のシート 3はシート1""さしす""のシート 4はシート1""たちつ""のシート を指定するようになっています。 ここでとりあえず自分の希望のしーとになるように1~4の数字を選びます。 次にもうひとつのコマンドボタンを選択するとテキストボックスが現れます。 記入し、テキストボックスと同userformにあらかじめ作っていたコマンドボタンをクリックすると先ほど選択した1~4にテキストボックスを転送するようにしたいのです。 hideを使って先ほど表示させたコンボボックスのuserformを隠して、テキストボックスのuserformを閉じる際に指定したシートをにとさせようとしましたが、 そのテキストボックスのuserformが何個かあるのでどうすればいいのかわかりません。 どなたかご教授願えませんでしょうか? よろしくお願い致します。 なお、私の説明不足で内容がよくわからなかったら一報ください。 申し訳ありませんが、どうぞよろしくお願い致します。

  • エクセルのユーザーフォームのことです

    はじめまして。よろしくお願いします。 エクセルで、リストを作成しようと思っています。内容は、顧客名簿で、A名前、B住所、CからEまでははじめから項目があって、それに該当するものにチェックを入れる。項目とは、C医療、D教育、E学校という項目です。ユーザーフォームでテキストボックスを2つとチェックボックスを3つ、その他に確定ボタン、閉じるボタンを付けました。ユーザーフォームの名前住所に文字を入れ、チェックボックスに該当するもののチェックを入れ、確定ボタンでシートに転記し、続けて次の名簿を入れる・・という風にしたいのです。いろいろ参考にしながら作成したのですが、、、 質問(1)一人目、3つあるチェックボックスのうち2つにチェックを入れる→確定ボタンを押してもチェックボックスのチェックが残ってしまい、二人目を入れるのにチェックを一度消さなくてはならないのです。確定ボタンを押すと転記された後チェックがリセットされるようにするには、どうしたらよいのでしょうか? 質問(2)チェックをシートに転記すると、現在セルにはTRUEと入ります。これを”○”とか”レ”とかの記号にするにはどうしたらよいですか? おそらく、既に回答がある質問だとは思ったのですが、探すのが下手なのか見つけられずに、はじめてこちらに質問させて頂く次第です。よろしくお願いいたします。

  • エクセルのユーザーフォームについての質問です。

    エクセルのユーザーフォームについての質問です。 かなりの初心者です。 テキストボックスを3つ、チェックボックスを10個作りました。 チェックボックスは複数チェックすることができます。 コマンドボタンをクリックすると、テキストボックスに入力された値とチェックされた チェックボックスがsheet1に自動入力できるようにしたいです。 たとえば、 テキストボックス1には「あいう」 テキストボックス2には「かきく」 テキストボックス3には「さしす」と入力。 チェックボックス1から10のうち、「1」「2」「3」にチェック。 この状態でコマンドボタンをクリックすると、Sheet1には     A列       B列       C列        D列 1行目 テキスト1    テキスト2    テキスト3     チェックボックス 2行目 あいう      かきく      さしす       1 3行目 あいう      かきく      さしす       2 4行目 あいう      かきく      さしす       3 このように、チェックボックスにチェックがあった数だけ、テキストボックスも コピーされて、次々と下の行に入って行くようにしたいのです。 こんなことができるのでしょうか? できるのなら、コードを教えてください。 お願いします。

  • ユーザフォームのリストボックス

    お世話になります。 ユーザフォームのリストボックス内の下記2個のどちらかを選択し Private Sub UserForm_Initialize() ListBox1.AddItem ("印刷プレビュー") ListBox1.AddItem ("印刷") End Sub CommandButton1をクリックして Worksheets("Sheet1").PrintOut か Worksheets("Sheet1").PrintPreview を実行したいのですが どうやってリストボックスとコマンドボタンを 連動できるようにすればいいのでしょうか コマンドボタンのみだったら出来るのですが、 リストボックスを使うとうまくいきません。 ご教授よろしくお願いいたします。

  • ExcelVBAを用いてツールを作成しております。

    ExcelVBAを用いてツールを作成しております。 内容としては、以下の通りです。 (1)Excelファイルのシート名をリストボックスに表示させる。 ⇒実装済み (2)リストボックスからシート名を選択(複数選択可)し、「OK」ボタンを押下すると処理を実施する。 チェックとして、リストボックスから何も選択せず、「OK」ボタンを押下したときに エラーメッセージを表示させるようにしたいと思いますが、調べてもわからなかったので、 こちらに質問させて頂きました。 どなたかお分かりの方ご教授ください。よろしくお願い致します。

  • エクセル VB: フォーム内のリストボックスの項目

    エクセルVBなのですが、フォームをつくってその中にリストボックスを配置しました。 コマンドボタンで呼び出して、シート内にあるリストから項目を抽出し反復を省略したリストを フォーム内のリストボックスに作りたいのですが。 Private Sub CommandButton1_Click() UserForm1.Show (このあとリスト項目のコード) End Sub コマンドボタンをクリックすると、UserForm1が現れますが、リストの中身は空です。一度Unload meでフォームを終わらせて、2回目クリックするとリストの中身が現れます。 一回目のクリックでエラーは出ません。 一回目のクリックでリストを配置したいのですが、何が問題なんでしょうか? Excel2003 Windows Xp です。 よろしくご教示下さい。

  • フォームの表示

    エクセルでsheet2を開くと、すでに作成してあるuserform2が表示されて以下ボタンの押下によって、処理が進むようにしたい。 このときsheet2を開くと、すでに作成してあるuserform2が表示されるようにするには、どのようにするのでしょうか。

専門家に質問してみよう