アプリ版:「スタンプのみでお礼する」機能のリリースについて

はじめまして。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) では、それぞれどのようなコードを記載すればよろしいでしょうか?

説明が下手で申し訳ありませんが、アドバイスをお願いいたします

A 回答 (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
    • good
    • 0
この回答へのお礼

なるほど。
たくさんのエッセンスが盛り込まれていて、サンプルコードを
読ませていただくだけで、すごく勉強になります。

エラーハンドリングを除くと、ポイントとなるのは
・Form.Hide を実行したタイミングで、呼び出し元に処理が戻る。
 ただし、Hide にしただけではオンメモリのままなので、呼び出し元
 で、Unload するまでは、プロパティアクセスが可能
ということですね。

インスタンスの生成やエラーハンドリングなど、細かいところまで
アドバイスをいただき、お忙しいところお手数をおかけして申し訳
ありませんでした。

ソースコードはコメントのおかげもあって、ほぼ理解できました。
ありがとうございました。

お礼日時:2007/06/13 17:42

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()
    • good
    • 0
この回答へのお礼

返事が遅くなって大変失礼しました。

たしかに、Public な(グローバルな)変数を定義してしまえば
機能としては十分だと思います。

今回、私が考えていたのは、事前に、VbMsgBoxResult
(MsgBox の戻り値) のようなものを定義しておき、
UserForm から VbMsgBoxResult のような戻り値を
返してもらって、その値によって、呼び出し側で
処理を変更する(UserForm のプロパティを参照する)
といったことができないかな…ということでした。

わかりにくい説明で申し訳ありませんでした。

お礼日時:2007/06/13 17:25

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

このQ&Aを見た人はこんなQ&Aも見ています