Access (VBA)

Access VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Home : Access 2007)
フィルターで絞り込んだレコードの前後に移動したい
投稿日時: 18/09/15 20:47:05
投稿者: ekane

よろしくお願いいたします。
現在
単票フォーム(検索)にテキストボックス108とコマンドボタン(A)と下の詳細部分にはフィルターで
絞り込まれたレコードが表示されコマンドボタン(B)があります
 
絞り込まれたレコードのコマンドボタン(B)をクリックすると単票フォーム(詳細)が開くように
なっております(ここまでは完了です)
 
この後作成したい事
開いた単票フォーム(詳細)からその前後のレコードに移動させたいのですが、フィルターがかかって
いる為 移動すると新規レコードになってしまいます、普通に前後に移動させる方法をご教授頂きたく
存じます。
 
イメージとしては9/10でフィルターを掛けると詳細部分にはデータがある2016年と2018年が絞り込ま
れますここで2016年のコマンドボタン(B)をクリックし単票フォーム(詳細)の2016/9/10を開いた後
更にその前後の日にち(レコード)にも移動させたいと思うものであります。なお下記はテキスト型です
 
コマンドボタン(A) Me.Filter = "年月日 like ""*" & Me!テキスト108 & "*"""
              Me.FilterOn = True
コマンドボタン(B) DoCmd.OpenForm "frm詳細", , , "ID=" & Me!ID
 
ご指導よろしくお願いいたします。

回答
投稿日時: 18/09/18 10:08:30
投稿者: sk

引用:
単票フォーム(検索)にテキストボックス108とコマンドボタン(A)と
下の詳細部分にはフィルターで絞り込まれたレコードが表示され
コマンドボタン(B)があります
 
絞り込まれたレコードのコマンドボタン(B)をクリックすると
単票フォーム(詳細)が開くようになっております

・フォーム[frm検索]のレコードソースと
 フォーム[frm詳細]のレコードソースは
 同じテーブル/クエリなのか。
 
・フォーム[frm検索]は本当に単票フォームなのか。
 それとも実際は帳票フォームなのか。
 
引用:
開いた単票フォーム(詳細)からその前後のレコードに移動させたいのですが、
フィルターがかかっている為 移動すると新規レコードになってしまいます、
普通に前後に移動させる方法をご教授頂きたく存じます。

ここでの「前後」とは、フォーム[frm検索]において
フォームフィルターが適用されている状態での「前後」と
フォームフィルターが適用されていない状態での「前後」の
どちらを意味しているのでしょうか。
 
引用:
Me.Filter = "年月日 like ""*" & Me!テキスト108 & "*"""

引用:
イメージとしては9/10でフィルターを掛けると
詳細部分にはデータがある2016年と2018年が絞り込まれます
ここで2016年のコマンドボタン(B)をクリックし
単票フォーム(詳細)の2016/9/10を開いた
更にその前後の日にち(レコード)にも移動させたい
と思うものであります。

例えば、フォーム[frm検索]に対してフィルターが適用された結果、
[年月日]の値が 2016/09/10 であるレコードと
[年月日]の値が 2018/09/10 であるレコードとが
それぞれ 1 件ずつ抽出されたと仮定して、その状態での
「前後」ならば、フォーム[frm詳細]における「次のレコード」
(または「前のレコード」)の[年月日]の値は 2018/09/10 となり、
「前のレコード」(または「次のレコード」)は存在しない、
ということになるはず。
 
逆に、フィルターが適用されていない状態での「前後」ならば、
「前のレコード」と「次のレコード」がどれになるかは、
単純にフォーム[frm詳細]側におけるレコードの並べ替え順に
よって決まります。
 
いずれにせよ、「前後」の基準が[年月日]であるならば、
フォーム[frm詳細]のレコードが[年月日]の昇順に並べ替えられるよう、
あらかじめ設定しておかなければならないでしょう。
 
引用:
DoCmd.OpenForm "frm詳細", , , "ID=" & Me!ID

今のところ確実に申し上げられるのは、この抽出条件式を
OpenForm メソッドの引数 WhereCondition に渡すのではなく、
[frm詳細]を開いてから上記の抽出条件にマッチするレコードに
移動させるという操作が必要となるであろう、ということです。

回答
投稿日時: 18/09/18 15:07:55
投稿者: Suzu

引用:
DoCmd.OpenForm "frm詳細", , , "ID=" & Me!ID

   ↓
1. フォームを開く
2. 特定条件で、フォーム上のレコードを検索する
   (Docmd.FindRecord / DoCmd.SearchForRecord)
でしょうか。
 
 
ただし、Docmdは、命令をするだけで、命令を完了するまで待ってくれません。
レコード数が多い場合等には、開く処理が終わらないにも関わらず
次の検索の 命令が発せられてしまう可能性もあります。(当然検索できません)
 
 
確実に検索する為には開くのを待って検索を行う必要があります。
開かれる側のOpenイベントで、検索を行います。
 
 
1. Docmd.OpenForm FormName:="frm詳細", OpenArgs:="ID=" & Me!I
 
2. frm詳細 の Openイベント
Private Sub Form_Open(Cancel As Integer)
  Dim rs As Object

  If Not IsNull(Me.OpenArgs) Then 
    Set rs = Me.RecordsetClone
    rs.FindFirst Me.OpenArgs

    If Not rs.NoMatch Then Me.BookMark = rs.BookMark
  EndIf 
End Sub

投稿日時: 18/09/18 21:40:21
投稿者: ekane

sk様
ありがとうございます。いつも拝見いたしております。
的外れがあるかと思いますがよろしくお願いいたします。
 

引用:
フォーム[frm検索]のレコードソースと
フォーム[frm詳細]のレコードソースは
同じテーブル/クエリなのか
ハイ 同じです
 
引用:
フォーム[frm検索]は本当に単票フォームなのか。
それとも実際は帳票フォームなのか。
失礼しました、プロパテイ-既定の
ビューで帳票フォームでした
 
引用:
ここでの「前後」とは、フォーム[frm検索]において
フォームフィルターが適用されている状態での「前後」と
フォームフィルターが適用されていない状態での「前後」の
どちらを意味しているのでしょうか。

「フォーム[frm検索]ではフィルターを適用しておりますが前後とはIDの前後です
DoCmd.OpenForm "frm詳細", , , "ID=" & Me!ID で単票フォームを表示したら
ここを元に(カレントレコードにしたい)その前後のレコードに移動させたいと
思っています
ID(オートナンバー型です)の前後のレコードです
引用:
例えば、フォーム[frm検索]に対してフィルターが適用された結果、
[年月日]の値が 2016/09/10 であるレコードと
[年月日]の値が 2018/09/10 であるレコードとが
それぞれ 1 件ずつ抽出されたと仮定して、その状態での
[前後」ならば、フォーム[frm詳細]における「次のレコード」
(または「前のレコード」)の[年月日]の値は 2018/09/10 となり、
「前のレコード」(または「次のレコード」)は存在しない、
ということになるはず。 

申し訳ございません。仮に2016/09/10としてフィルターを適用したら
そのレコードを中心にフィルターにかかっていない前後の2016/09/09や2016/09/11の
レコードにも移動したいのです(日付の方が前後がわかりやすいと思いました実際はID)
フィルターを適用したレコードをカレントレコードにすれば移動できると思うの
ですがわかりません。
返信にお時間がかかると思いますがよろしくお願いいたします。
           
       

投稿日時: 18/09/18 22:02:46
投稿者: ekane

Suzu様
ありがとうございます。いつも拝見させて頂いております
ご回答ありがとうございます。
   

引用:
ただし、Docmdは、命令をするだけで、命令を完了するまで待ってくれません。
レコード数が多い場合等には、開く処理が終わらないにも関わらず
次の検索の 命令が発せられてしまう可能性もあります。(当然検索できません)
  
確実に検索する為には開くのを待って検索を行う必要があります。
開かれる側のOpenイベントで、検索を行います。

 
Docmd.FindRecord / DoCmd.SearchForRecord 初めて拝見しました。
Docmdにもいろいろと制約というか特性があるのですね、上辺だけの勉強では無理ですね。
意味がわかりかねますがご教授頂いたコードを勉強させて頂きます。
返信にお時間がかかると思いますがよろしくお願いいたします。

回答
投稿日時: 18/09/19 10:01:26
投稿者: sk

引用:
フォーム[frm検索]ではフィルターを適用しておりますが
前後とはIDの前後です

引用:
仮に2016/09/10としてフィルターを適用したら
そのレコードを中心にフィルターにかかっていない
前後の2016/09/09や2016/09/11のレコードにも
移動したいのです
(日付の方が前後がわかりやすいと思いました実際はID)

では、Suzu さんが回答された通りの方針で
進めてみて下さい。
 
あとは(その必要はないかも知れませんが)、
フォーム[frm詳細]のレコードが[ID]の昇順に
並べ替えられるように設定しておけばよいでしょう。

投稿日時: 18/09/19 21:31:09
投稿者: ekane

sk様
お手数をおかけ致しまして申し訳ございません。

引用:
では、Suzu さんが回答された通りの方針で
進めてみて下さい。

ハッキリと学ぶべき方向をご指摘いただき あれこれ考える必要もなくなりました。
これよりSuzu様からご回答頂いた内容を勉強させて頂きます。
誠にありがとうございました。
 
 

投稿日時: 18/09/23 16:45:33
投稿者: ekane

再びお願いいたします。
Suzu様からお教えいただいたコードを実行させて頂きました。
コマンドボタン(B)の
DoCmd.OpenForm "frm詳細", , , "ID=" & Me!ID を

引用:
docmd.OpenForm FormName:="frm詳細", OpenArgs:="ID=" & Me!ID
に変更しました。
下記はそのまま引用しました。
引用:
2. frm詳細 の Openイベント
Private Sub Form_Open(Cancel As Integer)
  Dim rs As Object
 
  If Not IsNull(Me.OpenArgs) Then
    Set rs = Me.RecordsetClone
    rs.FindFirst Me.OpenArgs
 
    If Not rs.NoMatch Then Me.BookMark = rs.BookMark
  EndIf
End Sub
結果はfrm詳細は開くのですが検索フォームでフィルターをかけたIDを開いてくれません。
frm詳細の前回開いたレコードが表示されてしまいます
どのように修正したらよろしいのでしょうか。
(frm詳細を開いたらフィルターが適用されていないので前後のレコードには移動できます)
お手数をお掛け致しますがご指導お願いいたします。

回答
投稿日時: 18/09/25 14:58:14
投稿者: sk

引用:
結果はfrm詳細は開くのですが検索フォームでフィルターをかけたIDを開いてくれません。
frm詳細の前回開いたレコードが表示されてしまいます

フォーム[frm詳細]が既に開かれている状態のままで、
フォーム[frm検索]上のコマンドボタンをクリックして
OpenForm メソッドを実行なさろうとしているからでは
ないでしょうか。

回答
投稿日時: 18/09/25 15:37:27
投稿者: Suzu

コードは
【OpenArgs プロパティ】
https://support.office.com/ja-jp/article/openargs-%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3-c8616938-cd58-4b1a-84cf-3d043f59e13b
 
を一部改編した物なのですが。。
 
改編が中途半端ですね。。。
 
念のため
 
コマンドボタン(B)
---------------------------------------------------------------------
'IDが入力されている事の確認
If Not IsNull(Me.ID) Then
  '入力されていたら、当該レコード を frm詳細にて開く
  Docmd.OpenForm FormName:="frm詳細", OpenArgs:="ID=" & Me!ID
End If
---------------------------------------------------------------------
 
フォーム frm詳細 の 開く時イベント
 Microsoft DAO 3.6 ObjectLibrary に参照設定を行ってください。
---------------------------------------------------------------------
Private Sub Form_Open(Cancel As Integer)
  '要参照設定 Microsoft DAO 3.6 ObjectLibrary
 
  Dim rs As DAO.RecordSet
  ' OpenArgs に 値が入っていたら
 
  'テスト段階として OpenArges の 値を確認。
  '動作確認後は、削除して可。
  MsgBox Me.OpenArgs
 
  If Len(Me.OpenArgs)>0 Then
    'フォームのレコードセットクローンを取得
    Set rs = Me.RecordsetClone
    'レコードセットクローン に対し OpenArgs の値を検索条件にレコード検索
    rs.FindFirst Me.OpenArgs
 
    '検索の結果、合致するレコードが有れば
    'フォームのカレントレコードを 合致したレコードとする。
    If Not rs.NoMatch Then Me.BookMark = rs.BookMark
  EndIf
End Sub
---------------------------------------------------------------------
 
可能性としては、skさんのおっしゃる様に、既に開かれている が 濃厚な気がします、、

投稿日時: 18/09/25 22:02:14
投稿者: ekane

sk様 Suzu様
 
この度は誠にありがとうございました。
・sk様の

引用:
フォーム[frm詳細]が既に開かれている状態のままで
のおっしゃる通り
でございました。なんで開いているとダメなのかは私にはわかりませんが、原因が的確に
すぐわかると言う事は凄い事だと思います。
 
・Suzu様からのお教えいただいたコードを利用させて頂きました。
なんなく完璧に動作いたしました、しかもわかりやすいように注釈までつけて頂きありがたく
存じます。参照先を含めて時間がかかりますが勉強して行きます。
 
これで「キーワードをフィルターで絞り込んだのち その関連する言葉が前後のレコードにも
含まれていないか」という当初の目的が達成できました。
お二人様本当にありがとうございました。これからも多くの初心者のためにご指導お願い致します。