• 締切済み

Form オブジェクトの戻り値の設定

はじめまして。Porome です。 Excel 2003 の VBA を使ってプログラミングをしています。 Form オブジェクトの戻り値の設定方法/受取方法について教えてください。 実装したいプログラムの概要は、以下の通りです。 標準モジュールに記載したサブルーチンから Form オブジェクトを 生成し、Form オブジェクトで入力されたデータを標準モジュール側 で取得する…というものです。 書きたいソースコードのイメージは以下の通りです。 Sub MySub1() dim i_Form As New MyForm1 dim i_Name As String dim i_Age As String dim i_Ret As Integer 'MyForm1OK, MyForm1Cancel が戻ってくるまで、じっと待つ i_Ret = i_Form.Show, vbModal Select Case i_Ret 'MyForm1 で OK ボタンが押された Case MyForm1OK: i_Name = i_Form1.txtName.Value i_Age = i_Form1.txtAge.Value MsgBox(i_Name & " さんの年齢は " & i_Age & " 歳です") 'MyForm1 で Cancel ボタンが押された Case MyForm1Cancel: MsgBox("処理はキャンセルされました") 'MyForm1 では、MyForm1 では、MyForm1OK, MyForm1Cancel 以外は '戻さない仕様とします。 Case Else '何もしない(ここには来てはいけない) End Select End Sub こういったことを実現するためには ・MyForm1 では、 OK ボタンを押したら、MyForm1OK を Show メソッドの戻り値として セットし、処理を MySub1 に戻す Cancel ボタンを押したら、MyForm1Cancel を Show メソッドの戻り値としてセットし、処理を MySub1 に戻す OK ボタン、Cancel ボタン Click 以外の Form イベントでは、MyForm1 での処理が継続され、MySub1 は MyForm1 の戻り値(MyForm1OK/MyForm1Cancel)を、じっと待つ といったことが必要になってくるかと思います。 こういった処理を実装するには、呼び出し元 (MySub1)、呼び出し先 (MyForm1) では、それぞれどのようなコードを記載すればよろしいでしょうか? 説明が下手で申し訳ありませんが、アドバイスをお願いいたします

みんなの回答

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.2

こんばんは。 解説はコードにあるコメントを読んで下さい。基本的な Tips はだい たい盛り込んであるかと。。 ' ■ 標準モジュール ----------------------------------------- Option Explicit ' // 標準モジュールで Public 定数として宣言しておく必要がある Public Const MyForm1OK   As Long = 1 Public Const MyForm1Cancel As Long = 2 Sub MySub1()   Dim i_Form   As MyForm1   Dim i_Name   As String   Dim i_Age    As String   Dim i_Ret    As Integer      ' // i_Form のインスタンスを生成   ' // フォームがメモリにロードされて表示される   ' // Dim xxxx As New MyForm1 はインスタンスが残る可能性がある   ' // ので、意味をよく分かっていない場合は使うべきでない。   ' // 次のように Set ステートメントで New を使う   Set i_Form = New MyForm1   'MyForm1OK, MyForm1Cancel が戻ってくるまで、じっと待つ   ' ↓   ' // 単純にフォームを表示するだけで良い   ' // Form が閉じられるか、Hide されると次行に処理フローが戻る   i_Form.Show vbModal      ' // [X]で閉じられた場合は、プロパティーを参照するとエラーが   ' // 発生するので、エラーハンドラに飛ばして Cancel 扱いの   ' // 処理をおこなう   On Error GoTo Err_UserClose   i_Ret = i_Form.Value ' <------ココ。エラー発生の可能性あり        ' // エラーハンドラから Resume Next でここに戻る   ' // エラー処理の初期化   On Error GoTo 0   ' // i_Ret の値で条件分岐処理   Select Case i_Ret     Case MyForm1OK:   'MyForm1 で OK ボタンが押された       i_Name = i_Form.txtName.Value       i_Age = i_Form.txtAge.Value       MsgBox (i_Name & " さんの年齢は " & i_Age & " 歳です")     Case MyForm1Cancel: 'MyForm1 で Cancel ボタンが押された       MsgBox ("処理はキャンセルされました")     Case Else       '何もしない(ここには来てはいけない)   End Select      ' // フォームをメモリーから開放   Unload i_Form Terminate: ' // 終了処理   ' // オブジェクト変数の破棄   Set i_Form = Nothing   Exit Sub    Err_UserClose: ' // [X]ボタンによるエラーハンドラ   ' // キャンセル扱いとする   i_Ret = MyForm1Cancel   ' // エラーハンドラから処理を戻すときは必ずエラーをクリアする   Err.Clear   Resume Next End Sub ' ■ MyForm1モジュール ------------------------------------- Option Explicit ' // Value プロパティー用のモジュールレベル変数 Private mlValue As Long ' // Value プロパティー(読み取り専用)を用意 Public Property Get Value() As Long   Value = mlValue   ' // Public 変数を使うという手もあるが Property プロシージャ   ' // にした方が様々な処理を同時に行える。読み取り専用の   ' // プロパティー、書き込み専用プロパティーなど柔軟な処理が   ' // 可能。 End Property ' // イベントプロシージャ Private Sub UserForm_Initialize()   ' // 初期値などを設定する   mlValue = MyForm1Cancel End Sub Private Sub CommandButton1_Click()   mlValue = MyForm1OK   ' // Hide すると処理フローは MySub1 に戻るが MyForm1 は   ' // オンメモリのままなので、Unload されるまでは、   ’// プロパティー等にアクセス可能。   Me.Hide End Sub Private Sub CommandButton2_Click()   mlValue = MyForm1Cancel   Me.Hide End Sub

Porome
質問者

お礼

なるほど。 たくさんのエッセンスが盛り込まれていて、サンプルコードを 読ませていただくだけで、すごく勉強になります。 エラーハンドリングを除くと、ポイントとなるのは ・Form.Hide を実行したタイミングで、呼び出し元に処理が戻る。  ただし、Hide にしただけではオンメモリのままなので、呼び出し元  で、Unload するまでは、プロパティアクセスが可能 ということですね。 インスタンスの生成やエラーハンドリングなど、細かいところまで アドバイスをいただき、お忙しいところお手数をおかけして申し訳 ありませんでした。 ソースコードはコメントのおかげもあって、ほぼ理解できました。 ありがとうございました。

  • Nayuta_X
  • ベストアンサー率46% (240/511)
回答No.1

Public を使用します。 例: 以下の様にすると Public で、宣言された、変数は、Form からでも モジュールからでも 使用できます。 Public i_Form As New MyForm1 Public i_Name As String Public i_Age As String Public i_Ret As Integer Sub MySub1()

Porome
質問者

お礼

返事が遅くなって大変失礼しました。 たしかに、Public な(グローバルな)変数を定義してしまえば 機能としては十分だと思います。 今回、私が考えていたのは、事前に、VbMsgBoxResult (MsgBox の戻り値) のようなものを定義しておき、 UserForm から VbMsgBoxResult のような戻り値を 返してもらって、その値によって、呼び出し側で 処理を変更する(UserForm のプロパティを参照する) といったことができないかな…ということでした。 わかりにくい説明で申し訳ありませんでした。

関連するQ&A

専門家に質問してみよう