- 締切済み
Accessのサブフォームを検索
Accessで質問があります。 メインフォームに個人名簿があり、その人のセミナー受講実績が、セミナー受付情報として、サブフォームになっています。 個人名簿(個人ID、名前、住所、電話番号・・・) セミナー受付情報(個人ID、受付日、受講番号、セミナー名、入金日・・・) リンク親/子フィールドに個人IDを指定しています。 別の検索フォームから、サブフォームの受講番号を入力して、該当する個人名簿を検索する事はできますか?
- みんなの回答 (12)
- 専門家の回答
みんなの回答
- 30246kiku
- ベストアンサー率73% (370/504)
#11です どのような解決になっても、デバッグの仕方は変わりません。 デバッグはこんな感じでしていくものだと、感じてもらえればと思います。 (マクロでデバッグしたことないので、マクロだったらどうなるんでしょう) マクロは高級言語、VBAはアセンブラ見たいな感じで、 かゆいところまで手が届く=VBA というところでしょうか。 少しは、理解いただけているものと思っています。
- 30246kiku
- ベストアンサー率73% (370/504)
#10です > 同じように > 名前で検索 > 会社名で検索 > というように絞込が出来たので、受講番号でもできないものかと思いまして。 であれば、 "個人ID = " & Nz(DLookup("個人ID", "受付内容", "受講番号=" & Me.検索), 0) を、名前、会社名で検索と同じようにするだけだったかと思いますが。 > 初めに検索フォームを立ち上げて > そこに受講番号を入れると、メインフォーム(個人名簿)に飛ぶという説明だったのですが。 では、検索をかけた後でメインフォームを表示する ということで良いでしょうか。 メインフォームのレコードソースには、絞込み条件が記述されていないことを条件に。 (絞込み表示は、Filter を使っているという条件で) 以下の2通りの方法での例になります。 1)受講番号をもつ個人名簿に絞り込んで表示 2)絞込み表示はせず、受講番号を持つ個人名簿を表示 1)受講番号をもつ個人名簿に絞り込んで表示 検索文字列が未入力であれば、フォーム起動済みなら絞込み解除 検索文字列が入力済みなら、 フォーム起動済みなら、Filter で絞込み設定 フォームを起動していなければ、抽出条件とともにフォームを起動 (ここでの条件が Filter に設定されます) 絞込み結果0件なら、絞込み条件を解除 Dim sWhere As String Const fName As String = "F1" ' フォーム名 If (Not IsNull(Me.検索)) Then sWhere = "個人ID = " & Nz(DLookup("個人ID", "受付内容", "受講番号=" & Me.検索), 0) If (CurrentProject.AllForms(fName).IsLoaded) Then With Forms(fName) .Filter = sWhere .FilterOn = True End With Else DoCmd.OpenForm fName, acNormal, , sWhere End If With Forms(fName) If (.Recordset.RecordCount = 0) Then .FilterOn = False .Filter = "" End If End With Else If (CurrentProject.AllForms(fName).IsLoaded) Then With Forms(fName) .FilterOn = False .Filter = "" End With End If End If 2)絞込み表示はせず、受講番号を持つ個人名簿を表示 検索文字列が未入力であれば、フォーム起動済みなら絞込み解除 フォームが起動されていなければ、非表示状態でフォームを起動 絞込み Filter の設定を解除し、RecordsetClone 内を検索 あれば Bookmark を設定し、対象のものを表示対象に 処理が終わったところで、フォームを表示 Dim sWhere As String Const fName As String = "F1" ' フォーム名 If (Not IsNull(Me.検索)) Then sWhere = "個人ID = " & Nz(DLookup("個人ID", "受付内容", "受講番号=" & Me.検索), 0) If (Not CurrentProject.AllForms(fName).IsLoaded) Then DoCmd.OpenForm fName, acNormal, , , , acHidden End If With Forms(fName) .FilterOn = False .Filter = "" With .RecordsetClone .FindFirst sWhere If (.NoMatch) Then MsgBox "対象がありません" Else Forms(fName).Bookmark = .Bookmark End If End With .Visible = True End With Else If (CurrentProject.AllForms(fName).IsLoaded) Then With Forms(fName) .FilterOn = False .Filter = "" End With End If End If ※フォーム名を指定する箇所が複数あるので、一か所にまとめました。 Const fName As String = "F1" ' フォーム名 ここの F1 だけを変更すれば動くと思います。 #1で絞込みの方法としなかったので長くなりましたが、 絞込み表示で簡単なのは、メインフォームのレコードソースをクエリ記述にして、 検索フォームのコントロールを参照させます。 個人ID を入力するテキストボックスなり用意し、Me.検索 の更新後処理とかで Me.個人ID = Nz(DLookup("個人ID", "受付内容", "受講番号=" & Me.検索), 0) し、作成しておきます。 後は、検索フォームの内容を変更した時にボタン等で、メインフォームを再クエリ するだけです。 Forms("F1").Requery とかで、 また、起動されていなかったら起動するとか。
- 30246kiku
- ベストアンサー率73% (370/504)
#9です > メインフォーム"F1"を立ち上げないで、検索フォームから探すことは難しいのでしょうか? なのですが、#1の補足に > 検索フォームにテキストボックスを設置して、そこに受講番号を入力、検索ボタンを押すと、その個人名簿に飛ぶようにしたいのですが、 という記述もありました。 メインフォームを表示していて、検索フォームも起動。 検索フォームで、既に表示しているフォームのサブフォーム情報 「受講番号」を入力した時に、メインの表示をその「受講番号」を持つ個人名簿の表示に変えたい というように理解しておりましたが。。。 メインフォームである個人名簿の表示は、何かしらの条件で絞込み表示されているのでしょうか。
補足
すみません説明不足で・・・。 初めに検索フォームを立ち上げて そこに受講番号を入れると、メインフォーム(個人名簿)に飛ぶという説明だったのですが。 同じように 名前で検索 会社名で検索 というように絞込が出来たので、受講番号でもできないものかと思いまして。
- 30246kiku
- ベストアンサー率73% (370/504)
#8です > バージョンは2007です。 良かったです。 私は2007に慣れるために2007でやってみて、それから2000/2003でもやって・・・ 2000から触り始めたので、97ならどうしようとか不安でした。 あの思わぬエラーは無くなったのでしょうか? ウォッチ式ですがフォーム F1 が起動されていれば、 Forms("F1").RecordsetClone は表示されるはずです。 表示されなかったら、フォーム名を確認してみてください。 .FindFirst "個人ID=" はウォッチ式では表示できなかったと思います。 .FindFirst "個人ID=" 部分は素直にステップ実行して、FindFirst で検索した結果を Forms("F1").RecordsetClone で確認します。 検索結果は Forms("F1").RecordsetClone の NoMatch で確認できます。(True なら無し、False ならあり) ありなら Fields を辿って各フィールドの内容を確認できます。 (無しでも辿ればみれますが意味がないので) > 値の所が「対象範囲外」となっているのですが これは、ブレークポイントとかで実行が止まっていない時にでます。 また、止まっていても式を追加する際に指定した、 対象「プロシージャ」「モジュール」内で止まっている時にのみ表示されます。 私はよく「プロシージャ」を(すべてのプロシージャ)に設定して、そのフォームの動きを見ます。 ※再度の確認です。 「個人ID」「受講番号」は数値型で良かったのでしょうか。 テキスト型であれば #2 後半に書いてある変更が必要です。
補足
できました!!! 本当に本当にありがとうございます!!! これで、メインフォーム"F1"を立ち上げないで、検索フォームから探すことは難しいのでしょうか?
- 30246kiku
- ベストアンサー率73% (370/504)
#7です > このエラーは"F1"のフォームを出したままで、検索ボタンを押すと、パラメーターboxで出てきます。 思わぬエラーが出てきましたね。 では、以下の手順で。 ・Accessを一旦終了します。 ・エクスプローラでAccessファイルのコピーをとります。 ファイルを1回クリックし、マウスの右ボタンでそのファイルをドラッグしたまま少しずらし、 右ボタンを離して「ここにコピー」を選びます。 ・コピー元のファイルで、Accessを起動します。 ・Accessのメニューで、最適化を行います。 2000なら、「ツール」→「データベースユーティリティ」→「最適化/修復」 2002,2003 も近いと思います。 2007なら、「Officeボタン」→「管理」→「データベースの最適化/修復」 ・Accessを一旦終了します。 ・エクスプローラでAccessファイルのコピーをとります。 ・コピー元のファイルで、Accessを起動します。 これで、最適化前後のバックアップを取ったことになります。 ・コピー元のファイルで、Accessを起動します。 ・検索フォームをデザインビューで開き、検索ボタンの「クリック時」の右横「・・・」をクリックし、VBA記述部分を表示させます。 ・初めの If 部分にブレークポイントを設定します。 ・メインフォームを起動し、検索フォームも起動します。 ・条件を設定後、検索ボタンをクリックします。 ブレークポイントで止まったら、 イミディエイトウィンドウでメインフォームが起動されているか確認します。 True となったら、If の次の行の With 以降をマウスでドラッグし、コピーします。 ウォッチウィンドウを表示し、その上で右クリックし「ウォッチ式の追加」を選びます。 「式」のところで、先ほどコピーしたものを貼り付け「OK」ボタン。 内容的には、Forms("F1").RecordsetClone を参照するものになります。 参照できれば、その下のプロパティなど表示確認することができます。 構造体をもつものなどは、このウォッチウィンドウで確認していきます。 「式」のところに Me と入力すれば、自フォームの内容を、 Me.検索 と入力すれば、「検索」の内容を確認することができます。 関数とかを実行しその戻り値を確認したい時に、イミディエイトウィンドウを使います。 Me.検索 の値が、1234 だとした場合、 ?DLookup("個人ID", "受付内容", "受講番号=1234") とか確認します。 (そのままウォッチウィンドウの式に記述しても結果は得られます) ※ この手順でやってみて、まだエラーが出るようでしたら、 新規mdb を作成し、元のAccessファイルから全てをインポート後、 上記ブレークポイント設定個所から確認してみてください。 ※ ちなみにAccessのバージョンは何でしたでしょうか?
補足
何度も本当にすみません。 バージョンは2007です。 やってみたのですが、ウォッチ式に CurrentProject.AllForms("F1").IsLoaded と Nz(DLookup("個人ID", "受付内容", "受講番号=" & Me.検索), 0) は出来たのですが、 Forms("F1").RecordsetClone .FindFirst "個人ID=" を入れると 「ウォッチ式が不正です。」 とエラーが出ます。 ウォッチ式は良く分からないのですが、 値の所が「対象範囲外」となっているのですが、それは関係ありますか?
- 30246kiku
- ベストアンサー率73% (370/504)
#6です 書き漏れです。 #6でエラーが出なくなったら、後半の以下部分の F1 も同様に変更してください ・・・・ Else Forms("F1").Bookmark = .Bookmark End If ・・・・
- 30246kiku
- ベストアンサー率73% (370/504)
#5です > でも今度はエラーで > 「Visual Basicコードで参照されているフォーム"F1"が見つかりません。」 > と出てしまいました。 このエラーはどこで出たのでしょうか。 (「デバッグ」ボタンをクリックすると、エラーの行は黄色くなっていると思います) > If (CurrentProject.AllForms("F1").IsLoaded) Then ' ★1 > With Forms("F1").RecordsetClone ' ★2 ★1の記述が正しいことは、イミディエイトウィンドウで確認されたと思うので、 ★2の F1 部分も、#5でやったように、もしくは★1のフォーム名を貼り付けてください。 くれぐれも、メインフォームを起動した状態で実行してください。
補足
このエラーは"F1"のフォームを出したままで、検索ボタンを押すと、パラメーターboxで出てきます。 他にイミディエイトウィンドウで確認したのですが、 Forms("F1").RecordsetClone も .FindFirst "個人ID=" & Nz(DLookup("個人ID", "受付内容", "受講番号=" & Me.検索), 0) もエラーで 「変数が生成されてません」 と出てしまい、TrueかFalseかも確認できません。
- 30246kiku
- ベストアンサー率73% (370/504)
#4です > そして、イミディエイトウインドウに表示させてみたのですが、Falseとなってしまいました。 > メインフォームの名前は合っています。 現状では、メインフォームである F1 は起動されていないとなっています。 以下手順で、手入力せずにフォーム名を設定してみてください。 ・メインフォームを、起動/デザインで開く時にクリックすると思いますが、そのクリックした状態で以下の操作をします。 「F2」キーを押下し、名前を変更する状態にします(実際には変更しません) Ctrl + C でコピーし、「Esc」キーで変更状態を解除します。 ・If (CurrentProject.AllForms("F1").IsLoaded) Then 記述のところに移動し F1 部分をマウスでドラッグ反転させて、Ctrl + V で貼り付け 良ければ上書き保存します。 イミディエイトウィンドウを表示させ、上記Ifのカッコ内をコピーし ? の後に張り付けて Enterキーを押すと False と表示されると思います。 メインフォームを起動し、 イミディエイトウィンドウに戻り、前に書いた ? 部分をクリック後、Enterキーを押します。 今度は True と表示されると思います。 True と表示されれば記述は正しいことになるので、以降 Ifにブレークポイントを設定し、検索フォームを起動させて動作を確認していきます。
補足
早速の回答ありがとうございます。 Trueになりました。 これはメインフォームを出しながらやらないといけなかったんですね。 でも今度はエラーで 「Visual Basicコードで参照されているフォーム"F1"が見つかりません。」 と出てしまいました。 何回も質問してしまい申し訳ございません。
- 30246kiku
- ベストアンサー率73% (370/504)
#3です > If (CurrentProject.AllForms("F1").IsLoaded) Then > With Forms("F1").RecordsetClone > .FindFirst "個人ID=" & Nz(DLookup("個人ID", "受付_form", "受講番号=" & Me.検索), 0) DLookup のパラメータ2つ目はテーブル名になっていますか。 「受付_form」は、名前からフォームの様な気がするのですが。 次にデバッグしていきます。 If (CurrentProject.・・・ のところを、1回クリックして 「F9」キー、もしくはメニュー「デバッグ」→「ブレークポイントの設定/解除」を行います。 ブレークポイントが設定されると、その行が反転表示されます。 検索フォームを起動し、検索ボタンをクリックすると、設定したブレークポイントで止まります。 その後、ステップ実行「F8」キーで1行づつ実行していきます。 その際に内容を確認したければ、変数部分などにマウスカーソルをのせることで表示されるし、「表示」→「ウォッチウィンドウ」で見たいもの等を指定することもできます。 これらの繰り返しで動作を確認していきます。 まず、If で止まったら、「表示」→「イミディエイトウィンドウ」を表示させ、そこに ?CurrentProject.AllForms("F1").IsLoaded と入力しEnterキー これがどの値を返すのか True か False か。 フォーム F1 が起動されていれば、True となります。 False なら、フォーム名を確認します。 その後、VBA 記述のところをクリック後、「F8」キーで1行づつ実行していきます。
補足
何度も何度も本当にありがとうございます。 受付_formの所はテーブルに直しました。 そして、イミディエイトウインドウに表示させてみたのですが、Falseとなってしまいました。 メインフォームの名前は合っています。
- 30246kiku
- ベストアンサー率73% (370/504)
#2です > With Forms("F1").RecordsetClone.FindFirst "個人ID=" & Nz(DLookup("個人ID","受付_form","受講番号=" & Me.検索),0) 上記の部分 1行に書いたのでしょうか。 であれば、#1のように With Forms("F1").RecordsetClone .FindFirst "個人ID = " & Nz(DLookup(・・・・), 0) ' DLookupは上記の内容 行を分けてみてください。
補足
いつも丁寧なアドバイスありがとうございます! エラーは出なくなったのですが、ボタンを押しても何も起こりません・・・。 Private Sub 受講番号_Click() On Error GoTo Err_受講番号_Click If (CurrentProject.AllForms("F1").IsLoaded) Then With Forms("F1").RecordsetClone .FindFirst "個人ID=" & Nz(DLookup("個人ID", "受付_form", "受講番号=" & Me.検索), 0) If (.NoMatch) Then MsgBox "対象がありません" Else Forms("F1").Bookmark = .Bookmark End If End With End If Exit_受講番号_Click: Exit Sub Err_受講番号_Click: MsgBox Err.Description Resume Exit_受講番号_Click End Sub 以上のように記載しました。 "F1"はメインフォームのフォーム名です。 何か他に問題がありますか?
- 1
- 2
お礼
出来ました!! 長い間アドバイスをいただきまして、ありがとうございます!! メインフォームのフィールドの検索は出来たのですが、サブフォームの検索の方法が分からなく困っていたのです。 Dlookupを使えばいいのですね。 大変勉強になりました。 また分からない事があったらよろしくお願いします。