LoginSignup
3
1

More than 5 years have passed since last update.

AccessVBAでサブフォームの実体の参照を捕まえる

Posted at

AccessVBAでサブフォームの実体の参照を捕まえる

帳票フォームをLoadする時にサブフォーム部品の中のFormのインスタンスの参照を取りたいと思った事はないだろうか。
私はよくある。
何故なら、サブフォームに定義したイベントを監視したり、プロシージャをCallしたりしたいからだ。
画面部品の『サブフォーム』をそのまま使うのでは、リンク項目で従属テーブルをぶら下げて表示したり、Requeryプロシージャで再表示したりするくらいしかできず、やきもきさせられる。

そんな時は型を明示してサブフォームの実体を取り出せばよい。そのやり方を以下に示す。
レポートでも同じように出来るのかは検証していないが、多分上手く行くだろう。

間違った方法1:デザインしてあるサブフォームから取り出そうとする

普通の手順では、デザインビューを使ってサブフォーム部品を貼り付け、ソースオブジェクトを設定する。従属テーブルであればここでリンク項目も設定しておけば、大体上手くいく。
サブフォームには最初から目当てのフォームが表示出来ているので、後はこれを取り出してやればよさそうだ。
この時のコードは以下のようになる。

Form_Main
Private WithEvents m__SubFoo As Form_SubFoo

Private Sub Form_Load()
  Set m__SubFoo = Me.subform.Form '<- Nothing
End Sub

メンバ変数の参照がNothingのままなので、操作しようとするとエラー(ぬるり)になる。
As Newで宣言すればエラーは回避されるが恐らく望んだ動作にはなるまい。

Loadイベントの実行順を知っている人なら、何が起こっているのか分かるかと思う。
サブフォームの中身のインスタンスの生成は親フォームのOpenが終わるまで遅延されるので、このタイミングではFormプロパティを見ても参照を取る事ができない。

間違った方法2:Newしてからサブフォームにはめ込もうとする

方法1ではサブフォームの中身が出来上がってないのが悪いのだった。
そうであるならば、自分でインスタンスを作ってやれば解決しそうにみえる。
別ウィンドウとして開く時みたいに目的のフォームを明示的にNewするだけだし、簡単そうだ。
この時のコードは以下のようになる。

Form_Main
Private WithEvents m__SubFoo As Form_SubFoo

Private Sub Form_Load()
  Set m__SubFoo = New Form_SubFoo
  Set Me.subform.Form = m__SubFoo '<- RuntimeError. ReadOnly Property!
End Sub

なんてこった。万事休すだ。
サブフォームのFormプロパティは読み取り専用なので、外からSetできない。
Openイベントの完了まで待たないと取れないとなるとイベントを監視するためのインスタンスを取り出す機会がない。
Timerでタイミングをずらして上手くいくように祈るしかないのだろうか。

正しい方法:たった一つの冴えたやり方

もちろん、解決策はある。しかもシンプルなやつだ。
普段使わないであろうTimerなんぞに登場してもらう必要もない。
正解のコードは以下のようになる。

Form_Main
Private WithEvents m__SubFoo As Form_SubFoo

Private Sub Form_Load()
  Me.subform.SourceObject = "SubFoo" '<- include:New Form_SubFoo
  Set m__SubFoo = Me.subform.Form
End Sub

Private Sub m__SubFoo_Notify(ByVal msg As String)
  Call MsgBox(Prompt:=msg, Buttons:=vbOkOnly)
End Sub
Form_SubFoo
Public Event Notify(ByVal msg As String)

Private Sub Command1_Click()
  RaiseEvent Notify("SubFoo.Command1_Clicked!")
End Sub

サブフォームのSourceObjectプロパティはFormモジュールの名前を設定する項目だが、
コード内でSetしてやると、その場でFormのインスタンスが生成される。
つまり、すぐ次の行でFormプロパティをGetして参照を得ることができる。

これでめでたくイベントを監視できるし、必要であればプロシージャをCallすることができる。
(ここではプロシージャCallの例は割愛している)

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1