
オフィス2007です。
Sub test()
Dim obj As AccessObject
For Each obj In CurrentProject.AllForms
Debug.Print obj.Name
Next
End Sub
---------------------------------
上記のコードでデータベースのすべてのフォーム名は取得できますが
フォーム1に乗っかっている複数のサブフォームを取得するにはどうすればいいのでしょうか?
サブフォームに独自の名前を付けて、IFステートメントを使うしかないですか?
No.4ベストアンサー
- 回答日時:
No.3です。
> Function SFEnumの方が使い方がよくわかりません。
SFEnum関数は、
・SFListup関数の「For Each ~ Next」のループ内
・SFEnum関数自身の中(→再帰呼出)
で使用するために定義した関数ですので、直接呼び出す必要は
ありません。
(2つセットになって、初めて目的の動作をする関数です)
「◆こちらの関数の再帰呼出により~」のコメントがわかりにくかった
ようで、すみません(汗)
以下、かなり大雑把に、前回のコードの説明をしてみます。
1)SFListup関数内のループで、当該データベース内のフォームを、
デザインビューで順次開いていく
2)当該フォームを「Frm」変数に記録した上で、指定したフォーム内
のサブフォームの情報を確認するSFEnum関数を呼び出す
3)SFEnum関数では、その直下にある全てのコントロールを確認
(→「For Each Cntl In Frm.Controls」以降)
4)コントロールがサブフォームだった場合は、更に詳細を確認
(→「If Cntl.ControlType = acSubform Then」以降)
5-a)サブフォームに「ソースオブジェクト」が設定されていない場合
(→「Case sSource = ""」):
イミディエイトウィンドウに、表示用フォームが指定されていないこと
を明示するため、sSourceに「(オブジェクト未設定)」と記録
5-b)サブフォームの「ソースオブジェクト」に、テーブルやクエリを直接
指定している場合(→「Case sSource Like "*.*"」):
※サブフォームには、「テーブル.(テーブル名)」の形を使用すると
テーブルやクエリを指定できるため、これを曖昧検索で確認
テーブル/クエリの中にサブフォームは設置できないので、その
サブフォームは確認終了
【訂正】
半角ピリオドはフォーム名に使用できないのですが、全角なら使用
可能なので、「sSource Like "*.*"」ではなくInStr関数を使用
して、「半角ピリオドを含むかどうか」を判定するべきでした(汗)
(→「Case InStr(1, sSource, ".", vbBinaryCompare) > 0」、と)
5-c)サブフォームの「ソースオブジェクト」にフォームを指定している
場合(→「Case Else」):
その下に、さらにサブフォームが存在する可能性があるため、
SFEnum関数で確認(→sFeNum関数の中で、同じSFEnum関数
を呼出:これを再帰呼出といいます)
6)それぞれの場合の確認が終わったら、引数iLvに記録されている
現在の階層数に合わせてスペースを追加して、変数sSourceに
記録した情報を、引数sEnumに追記
(→「sEnum = Space(iLv * 5) & Cntl.Name & "【" & sSource & "】"」)
・・・以上です。
この「再帰呼出」というのは、慣れないとちょっとわかりにくいと思います
ので(→少なくとも私自身はVBAを扱うようになってからも暫くは手が
出せていませんでした(汗))、気長に眺めてみることをお勧めします。
この再帰呼出の部分をさらに大雑把に説明すると、
1)デザインビューで開いたフォームにサブフォームがあるか確認
2)サブフォームがあったら、親フォームの情報をsEnumに記録する
前に、iLvに「1」を加算(→階層の記録)して、子フォームに移動
3)子フォームにもサブフォーム(孫)があったら、子フォームの情報を
sEnumに記録する前に、孫フォームに移動
4)サブフォームがなくなったところで、sEnumに自身の情報を記録
して、直接の呼出元(孫まであった場合は子の階層)に戻る
5)戻ってきたところでsEnumに自身の情報を追加して、同じく直接
の呼出元(子の場合は親の階層)に戻る
6)SFListup関数にまで戻ったら、イミディエイトウィンドウに表示
となります。
SFEnum関数内で定義したRslやCntlなどの変数は、再帰呼出を
しても上書されません。
(あたかも「Rsl’」や「Cntl’」という変数が別に用意されたかのように、
繰り返した階層ごとの値が、パソコンのメモリ内に保持されます)
・・・多分ここが、一番感覚がついてこないところではないかと・・・(汗)
・・・長くなりましたが(汗)、以上です。
No.3
- 回答日時:
遅れ馳せながら、再帰呼出により全てのサブフォームをデバッグ ウィンドウに
出力させる関数を作成してみました。
親子関係は、半角スペース5個のインデントで表す形としました。
また、サブフォームのコントロール名に加え、ソースオブジェクトも同時に
表示させています。
なお、サブフォームのソースオブジェクトが空白だったり、テーブル・クエリを
指定した場合にも念のため対応しました。
'◆イミディエイトウィンドウなどから呼び出すのはこちらの関数になります◆
Public Function SFListup() As Boolean
On Error GoTo エラー処理
Dim Rsl As Boolean, Obj As AccessObject, Frm As Form
Dim sName As String, sEnum As String
For Each Obj In CurrentProject.AllForms
sName = Obj.Name
DoCmd.OpenForm sName, acDesign
Set Frm = Forms(sName)
sEnum = "" '初期化
Rsl = SFEnum(Frm, sEnum, 0)
If Rsl = False Then
sEnum = Space(5) & "★エラーにより確認不可★" & vbCrLf
ElseIf sEnum = "" Then
sEnum = Space(5) & "(サブフォームなし)" & vbCrLf
End If
Debug.Print "~~~以下『" & sName & "』配下~~~"
Debug.Print sEnum
DoCmd.Close acForm, sName
Next
終了処理:
SFListup = Rsl
Set Obj = Nothing
Set Frm = Nothing
Exit Function
エラー処理:
MsgBox Err.Number & ":" & Err.Description
Resume 終了処理
End Function
'◆こちらの関数の再帰呼出により、全階層のサブフォームを取得します◆
Private Function SFEnum(Frm As Form, sEnum As String, ByVal iLv As Integer) As Boolean
On Error GoTo エラー処理
'[Frm=サブフォームを確認するフォーム, sEnum=デバッグウィンドウに表示する情報を記録, iLv=サブフォームの階層を記録]
Dim Rsl As Boolean, Cntl As Control, sSource As String
iLv = iLv + 1
For Each Cntl In Frm.Controls
If Cntl.ControlType = acSubform Then
sSource = Cntl.SourceObject
Select Case True
Case sSource = ""
Rsl = True
sSource = "(オブジェクト未設定)"
Case sSource Like "*.*"
Rsl = True
Case Else
Rsl = SFEnum(Cntl.Form, sEnum, iLv)
End Select
If Rsl = False Then GoTo 終了処理
sEnum = Space(iLv * 5) & Cntl.Name & "【" & sSource & "】" & vbCrLf & sEnum
End If
Next
Rsl = True
終了処理:
SFEnum = Rsl
Set Cntl = Nothing
Exit Function
エラー処理:
MsgBox Err.Number & ":" & Err.Description, vbCritical, "SFEnum"
Rsl = False
Resume 終了処理
End Function
・・・以上、参考まで。

ご回答がとても遅くなってしまい申し訳ございませんでした。
二つのプロシージャー
・Function SFListup
・Function SFEnum
を標準モジュールに張り付けて実行してみました。
Function SFListupはVBE画面でF5を押したら実行され、
イミティエイドウインドウに求める結果が表示されたのですが
Function SFEnumの方が使い方がよくわかりません。
F5を押しても何も起きないです・・・
せっかく教えていただいたのに
うまく使えてなくてごめんなさい。
もっと勉強してみます。
No.2
- 回答日時:
孫フォームまでですが、フォーム1が有った場合に
親子関係を分かりやすくしたつもり。
Sub b()
Dim ctl As Control
Dim ctl2 As Control
Dim frm As Object
Dim sMsg As String
For Each frm In CurrentProject.AllForms
If frm.Name = "フォーム1" Then
DoCmd.OpenForm frm.Name, view:=acDesign, windowmode:=acIcon
For Each ctl In Forms(frm.Name).Controls
If ctl.ControlType = acSubform Then
sMsg = "親=" & frm.Name & " 子=" & ctl.Name
For Each ctl2 In ctl.Form
If ctl2.ControlType = acSubform Then
sMsg = sMsg & " 孫=" & ctl2.Name
End If
Next
Debug.Print sMsg
End If
Next
DoCmd.Close acForm, frm.Name
End If
Next
End Sub
No.1
- 回答日時:
こんにちは。
すべてのフォームと、それに乗っているサブフォーム名をイミディエイトに出力します。
Sub test()
Dim obj As AccessObject
For Each obj In Application.CurrentProject.AllForms
Macro2 obj.Name
Next
End Sub
Sub Macro2(ByVal fName As String)
Dim ctrl As Control
Dim sbf As SubForm
Dim str As String
DoCmd.OpenForm fName
str = "**** " & fName & "のサブフォーム名 ****" & vbCrLf
For Each ctrl In Forms(fName).Controls
On Error GoTo 10
Set sbf = ctrl
str = str & vbTab & sbf.Name & vbCrLf
20:
Next
DoCmd.Close acForm, fName
Debug.Print str
Exit Sub
10:
Resume 20
End Sub
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) EXCEL VBAにて動的にCheckBOXを複数作成し、同BOXにイベントを追加したい 1 2023/03/16 07:05
- Visual Basic(VBA) ユーザーフォーム「frm_基本❶」を立ち上げると新規で入力する行数を右下のNoとして表示しています。 1 2023/03/16 19:02
- Visual Basic(VBA) VBA Userformで一部別シートに転記がしたいのですが 2 2023/05/24 13:08
- Visual Basic(VBA) outlook マクロが終了しません。 1 2022/09/02 11:14
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る バッチからEXEの結果を受け取りたいのですが、 下記のバッ 1 2023/07/04 15:13
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る EXEの実行内容の結果によって、戻り値を0か1かで返したい 1 2023/07/04 16:40
- Excel(エクセル) B列に文字がはいったらA列に数字が入るマクロードを完成させたい 4 2023/04/21 01:58
- Visual Basic(VBA) VBA This Workbookモジュールを別ファイルにコピーする方法 1 2022/09/14 01:51
- Visual Basic(VBA) Vba LongPtrについて教えてください 2 2022/08/19 11:14
- Visual Basic(VBA) 【VBA】写真の貼り付けコードがうまく機能しません。 5 2022/09/01 18:43
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
サブフォームに対してGoToRecor...
-
クエリで出来た表にチェックボ...
-
サブフォームのあるフォームか...
-
ACCESS VBA メインフォーム及び...
-
ACCESS 帳票フォームとデータ...
-
親フォームからサブフォームの...
-
皆さん使っているブラウザを教...
-
親・子リンクフィールドの設定...
-
Accessで埋め込んだサブフォー...
-
ACCESSのサブフォームコピーに...
-
サブフォームを非表示させる方...
-
Access フォームで条件抽出し...
-
DLookup関数を使ってサブフォー...
-
Access2010 サブフォームの並び...
-
ACCESSにて
-
Access:データシート形式表示...
-
Excel VBA 全部のUserForm名
-
アクセスで数値型のフィールド...
-
Access レポート印刷するときに...
-
リストボックスで選択したレコ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
サブフォームに対してGoToRecor...
-
クエリで出来た表にチェックボ...
-
親フォームからサブフォームの...
-
サブフォームを非表示させる方...
-
ACCESSにて
-
ACCESS──メインフォームでサブ...
-
Accessで埋め込んだサブフォー...
-
ACCESSのフォームで列固定?
-
ACCESS VBA メインフォーム及び...
-
親・子リンクフィールドの設定...
-
皆さん使っているブラウザを教...
-
サブフォームのあるフォームか...
-
Access2007 ラベルの削除がで...
-
Accessでセレクタをダブルクリ...
-
ACCESSで条件によってサブフォ...
-
access vba サブフォームに条件...
-
ACCESSのサブフォームコピーに...
-
Access 登録ボタンからサブフォ...
-
Access フォームで条件抽出し...
-
access フォーム上で複数行の...
おすすめ情報