プロが教える店舗&オフィスのセキュリティ対策術

こんにちは。
早速質問させていただきます。

ExcelVBAでプログラムを組んでいて、
そのExcelシート上に同じUserFormを動かすためのコマンドボタンが
数十個あります。

ちなみに、UserFormの中身はチェックボックスです。

数十個のコマンドボタンそれぞれを押下後、
UserFormでチェックした項目を再度表示させたいのですが、
それぞれのコマンドボタンから同じUserFormを呼んでいるため、
UserForm.Hide
では、他のコマンドボタンでチェックした内容が
出力されてしまいます。

どのようにしたら、UserFormを複数作らずに
UserFormの内容を保持できるでしょうか。

回答よろしくお願いします。

A 回答 (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

多少複雑になりますが、上記対応でループ化が可能です。
    • good
    • 0
この回答へのお礼

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

お礼日時:2005/12/13 15:57

エラー内容についてですが、



UserForm1という「プライベートオブジェクトモジュール(外部アクセス不可能なオブジェクト=フォームなど)」をSheet1という「パブリックオブジェクト
モジュール(外部アクセス可能なオブジェクト=シートなどのこと)」のなかで「Public(パブリック=外部アクセス可能)」にすることができないという意味です。
つまり、要約すると、「Sheet1の中でUserForm1をPublic宣言してはいけません」となります。

これを解消するためには「Public」を「Private」に変更すれば問題ありません。

注意書きが足りなくて混乱させてしまい申し訳ありません。
    • good
    • 0
この回答へのお礼

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

お礼日時:2005/12/13 14:17

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
を入力します。
※無い場合はそのまま先頭から記入します。

この回答への補足

ありがとうございます。
フォームを別インスタンスで開くことが出来ました。

もう一つ質問してもよろしいでしょうか。
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
かなんかでループできたら…とおもっているのですが。

補足日時:2005/12/13 14:03
    • good
    • 0

変数に値を退避し、それを初期化時に設定してやるのがわかりやすい方法だと思います。



ただ、他の方法でも可能です。
具体的には以下の方法で実装します。
(オブジェクト指向の考えが必要になります)

【実装方法】
※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」を使用するように注意する必要があります。

この回答への補足

>※ModuleやSheetなどForm以外で変数を定義します。

どこで定義したらよいのかいまいちわかりません。
Sheet1のOption Explocitの下にpublic form1 As New UserForm1と
追加したところ以下のエラーが表示されます。

コンパイルエラー:
プライベートオブジェクトモジュールを、パブリックオブジェクト
モジュール内で、パブリックプロシージャの引数または戻り値、
パブリックデータメンバ、またはパブリックのユーザ定義型の
フィールドとして、使用する事は出来ません。

どういう意味かさっぱりわかりません。
ご教授願います。

補足日時:2005/12/13 13:09
    • good
    • 0

>Excelシート上に同じUserFormを動かすためのコマンドボタンが数十個あります。



このような事をする意味がわかりませんが・・・
チェックの有無をはっきりさせたいなら、こちらにチェックボックスを置くべきかと思います。
また、ボタンの表示(文字)を変更するのも一つの方法かと思います。

状態を記憶させたいなら、標準フォームにグローバル変数(Public 宣言)を置いて、個々の変数に1対1にするとか、配列変数に状態を格納すると良いでしょう。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!