Accessではフォームのなかに別のフォームを埋め込むことができます。
一般的には、大元のフォームを「親フォーム」または「メインフォーム」、大元のフォームのなかに埋め込んだフォームを「子フォーム」または「サブフォーム」と呼びます。
この「親フォーム」と「子フォーム」は、両者から相手側のフォーム内のコントロールをVBAで参照する場合の構文が独特であり、Access VBA初心者には若干敷居が高い操作です。
よって今回の記事では、Access VBAで「親フォーム」と「子フォーム」、さらに「孫フォーム」を参照する方法を初心者の人でもわかりやすく紹介していきます。
フォームのなかにフォームを埋め込む構成について
Accessでは一つのフォームのなかに別のフォームを埋め込むことができます。
埋め込むフォームは一つだけではなく複数でも可能です。
また、埋め込んだフォームのなかに、さらに別のフォームを埋め込むこともできます。
前述したように、フォーム内に別のフォームを埋め込む構成を親フォーム、子フォームなどと呼びます。
この親フォームと子フォームが使えるようになると、UI(ユーザーインターフェイス)における表現の幅が広がり、業務アプリケーションの使い勝手の向上に大きく貢献できます。
また、よく使われる親子フォームの例としては、「表形式」の子フォームを親フォームに埋め込み、親フォーム側で入力された値を元に絞り込んだ結果を子フォームで表示するといった使われ方があります。
このように複数のフォームを一つのフォームに収めることで、そのフォーム間で表示内容を連携させることができ、画面の遷移をさせることなくユーザーが必要とする情報を一つの画面のなかにまとめて表示させることができます。
画面遷移による実装と比べると処理は若干複雑になりますが、ぜひ積極的にチャレンジしてみてください。
親フォームから子フォームを参照する書き方例
親フォームから子フォームを参照する書き方はいくつもあります。
当項では、そのいくつかの書き方の例を紹介していきます。
親フォームから絶対参照的に指定する書き方
親フォームから絶対参照的に子フォーム内のコントロールを指定する場合は、「Formsオブジェクト」を使用します。
尚、「Forms オブジェクト」では、現在開いているフォームのコレクションを取得します。
詳しくはMicrosoftの以下の記事をご確認ください。
Formsオブジェクトを使用して、絶対参照的にサブフォーム内のコントロールを指定する書き方の例は以下です。
'感嘆符演算子で各コントロールを繋げた場合 Forms!親フォーム名!子フォーム名.Form!子フォーム内のコントロール名
または以下のようにも書けます。
'ドット演算子で各コントロールを繋げた場合 Forms.親フォーム名.子フォーム名.Form.子フォーム内のコントロール名
また、Formsオブジェクトはコレクションを取得するため、以下のような書き方でも指定可能です。
Forms(0).子フォーム名.Form.子フォーム内のコントロール名
ここまでは、Formsオブジェクトを指定して子フォームを参照しましたが、自分自身のフォームを表す「Me」を使って子フォームを指定することもできます。
'Formsオブジェクトを省略してMeから指定する場合 Me.子フォーム名.Form.子フォーム内のコントロール名
【参考】Accessにおける「ドット演算子(.)」と「感嘆符演算子(!)」の違い
Accessにおける「ドット演算子(.)」と「感嘆符演算子(!)」は共にオブジェクトやコレクション、プロパティなどの要素を参照するための「メンバーアクセス演算子」です。
ドット演算子ではVBE内で入力支援機能が有効になり、そのステートメントに続くメソッドやプロパティの候補が表示されます。
また、自動構文チェック機能も動くため、構文の入力ミスもすぐに気付けます。
感嘆符演算子ではそのような機能は効かないため、構文の入力ミスはプログラムを実行しないと気付けません。
表面上ではこのような違いがありますが、内部仕様的には以下の違いがあります。
※Microsoftの記事から抜粋
クラス、構造体、インターフェイス、または列挙型でメンバーアクセス演算子として使用します。
メンバーには、フィールド、プロパティ、イベント、またはメソッドを指定できます。
ディクショナリ アクセス演算子としてクラスまたはインターフェイスでのみ使用します。
クラスまたはインターフェイスには、単一の String 引数を受け入れる既定のプロパティが必要です。
! 演算子の直後の識別子は、既定のプロパティに文字列として渡される引数値になります。
ドット演算子はそのあとに続く候補のステートメントがVBE内で表示されることもあり、あまり説明は要らないかと思いますが、感嘆符演算子が少しわかり難いです。
感嘆符演算子はクラス、又はインターフェイスで、単一の引数を持ち、且つ既定のプロパティに対して文字列の識別子を渡せる演算子です。
よって、その条件に合うステートメントでしか値を渡せません。
詳しくは以下のMicrosoftの記事をご一読ください。

実際には、どのクラスやインターフェイスだと既定の引数が単一で文字列の値を受け取れるかを正確に覚えきれないですし、なんとなく使い分ける感じで良いかと思います。
【参考】フォーム名を角括弧[ ]で囲むことは必要なの?
ネットでサンプルコードを探すと、VBAでフォーム名を指定する際に、フォーム名を角括弧 [ ] で囲んでいるコードをよく見かけます。
ただ、囲まなくても動作はするようです。
この角括弧で囲む必要はあるのでしょうか?
例えばフォーム名にスペースが含まれていたり、ハイフンやアスタリスクなどの特別な意味を持つ記号が含まれていると、VBAではフォーム名として上手く認識してくれません。
フォーム名の途中にスペースが含まれていれば、そのスペースの前後で別の文字列として認識しますし、ハイフンやアスタリスクが含まれていれば、それらを算術演算子として認識してしまいます。
これは、フォーム名だけではなく、他のコントロールの名前やテーブル名、フィールド名などでも同様です。
そのような名前を正しくVBAに認識させるためには、角括弧で囲む必要があります。
逆に言えば、フォーム名などにそのような命名をしなければ、角括弧は必ずしも必要ではありません。
ただし、角括弧があると人が視覚的にもコードを解読し易くなるため、慣れないうちは角括弧も書くようにしたほうが無難かもしれません。

角括弧は書いても書かなくてもどちらでもよいですが、角括弧で囲む意味は理解しておいてください。
SubFormオブジェクトを生成して指定する書き方
Accessでは「SubFormオブジェクト」が用意されており、親フォームと子フォームをこのオブジェクトに格納して扱うことが可能です。
SubFormオブジェクトの詳しい説明は以下をご参照ください。
SubFormオブジェクトを使用して子フォーム内のコントロールを指定する場合は以下のように書きます。
Dim objSubForm As SubForm Set objSubForm = Forms.親フォーム名.子フォーム名 objSubForm.Form.子フォーム内のコントロール名
親フォームから子フォームまでを指定する文字列が長くなりがちなので、SubFormオブジェクトにまとめて扱う方がコードはすっきりするかと思います。
親フォームから孫フォームを参照する書き方例
当項では、親フォームから子フォームのなかの孫フォームを参照する場合の書き方を紹介します。
基本的には親フォームから子フォームを参照する場合と同じ書き方でOKです。
親フォームから絶対参照的に指定する書き方
孫フォームの場合も子フォームの書き方と同様に、Formsオブジェクトを使用して絶対参照的に記述することができます。
'感嘆符演算子で各コントロールを繋げた場合 Forms!親フォーム名!子フォーム名!孫フォーム名.Form!孫フォーム内のコントロール名
ドット演算子で繋げる場合は、孫フォームを指定する際にFormオブジェクトを使用します。
'ドット演算子で各コントロールを繋げた場合 Forms.親フォーム名.子フォーム名.Form.孫フォーム名.Form.孫フォーム内のコントロール名
また、Formsオブジェクトの代わりに「Me」を指定して孫フォームを参照することもできます。
'Formsオブジェクトを省略してMeから指定する場合 Me!子フォーム名!孫フォーム名.Form!孫フォーム内のコントロール名
子フォームから親フォームを参照する書き方例
当項では、子フォームから親フォーム内のコントロールを参照する場合の書き方を紹介していきます。
子フォームから親フォームを絶対参照的に指定する書き方
子フォームから親フォームを絶対参照的に指定する書き方は、これまでと同様にFormsオブジェクトを使用します。
Forms.親フォーム名.親フォーム内のコントロール名
Forms!親フォーム名!親フォーム内のコントロール名
子フォームから親フォームを相対参照的に指定する書き方
子フォームから親フォームを相対参照的に指定する書き方として、Formオブジェクトの「Parentプロパティ」が使用できます。
Parentプロパティの詳しい説明は以下をご一読ください。
'Parentプロパティを使用して子フォームから親フォームを参照 Parent!親フォーム内のコントロール名
ドット演算子で繋げても指定が可能です。
Parent.親フォーム内のコントロール名
孫フォームから親フォームを参照する書き方例
当項では、孫フォームから親フォームを参照する書き方を紹介していきます。
親フォームから絶対参照的に指定する書き方
親フォームを絶対参照的に指定する場合は、Formsオブジェクトを使用します。
子フォームから親フォームを指定する場合と同じです。
Forms.親フォーム名.親フォーム内のコントロール名
Forms!親フォーム名!親フォーム内のコントロール名
孫フォームから親フォームを相対参照指的に定する書き方
孫フォームから親フォームを相対参照的に指定する場合、Formオブジェクトの「Parentプロパティ」を複数指定することもできます。
Parent.Parent.親フォーム内のコントロール名
サンプルコードと実装例
当項では、親フォームから子フォームの参照や、孫フォームへの参照などの実際の実装例を紹介します。
当記事用サンプルフォーム
今回の記事用にコードを実装するサンプル用フォームを作成しました。
当フォームのデザイナー画面と各コントロール名は以下です。
番号 | コントロール種類 | コントロール名 |
---|---|---|
① | フォーム | frm_親フォーム |
② | テキストボックス | txt_親テキスト |
③ | コマンドボタン | btn_親ボタン |
④ | フォーム | frm_子フォーム |
⑤ | テキストボックス | txt_子テキスト |
⑥ | コマンドボタン | btn_子ボタン |
⑦ | フォーム | frm_孫フォーム |
⑧ | テキストボックス | txt_孫テキスト |
⑨ | コマンドボタン | btn_孫ボタン |
フォームの実装するサンプルコード
上記のように作成した親フォーム、子フォーム、孫フォーム内のコマンドボタンのクリック時イベントに以下のコードを実装します。
尚、これまで説明したように、異なるフォームの参照方法は複数あるため、当サンプルコードで使用した参照方法は一つの例に過ぎません。
Private Sub btn_親ボタン_Click()
Dim msg As String
msg = "親フォームのボタンが押されました。"
'親→子フォームを参照
Me.frm_子フォーム.Form.txt_子テキスト.Value = msg
'親→孫フォームを参照
Me.frm_子フォーム.Form.frm_孫フォーム.Form.txt_孫テキスト.Value = msg
'親フォーム自身を参照
Me.txt_親テキスト.Value = msg
End Sub
Private Sub btn_子ボタン_Click()
Dim msg As String
msg = "子フォームのボタンが押されました。"
'子→親フォームを参照
Parent.txt_親テキスト.Value = msg
'子→孫フォームを参照
Me.frm_孫フォーム.Form.txt_孫テキスト.Value = msg
'子フォーム自身を参照
Me.txt_子テキスト.Value = msg
End Sub
Private Sub btn_孫ボタン_Click()
Dim msg As String
msg = "孫フォームのボタンが押されました。"
'孫→親フォームを参照
Parent.Parent.txt_親テキスト.Value = msg
'孫→子フォームを参照
Parent.txt_子テキスト.Value = msg
'孫フォーム自身を参照
Me.txt_孫テキスト.Value = msg
End Sub
最後に
今回の記事ではAccess VBAで親フォーム(メインフォーム)から子フォーム(サブフォーム)を参照するコードの書き方をいくつかのパターンで紹介しました。
頻繁にAccessで業務アプリの開発をしている人であれば迷うことはないかと思いますが、私自身たまにしか開発をしないため、毎回「どう書くんだったかな?」とネットで調べて実装しています。
よって今回の記事は私自身の備忘録的な意味合いでまとめてみました。
今回の記事がどなたかの役に立てば幸いです。
それでは皆さまごきげんよう!