質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

Access サブフォームに追加後のRequeryでレコードの移動をもとの場所で表示させたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 613
退会済みユーザー

退会済みユーザー

質問内容

管理システムを作成しているのですが、マスタのサブフォームのRequery後のレコードの位置を戻したいです。

概要

マスタにサブフォームがあり、それが帳票になっています。
マスタのフッターにある新規登録ボタンを押すと、新規にデータを登録するフォームが開きます。
そのフォームで入力後、登録ボタンを押すと、マスタのサブフォームに追加されます。
この時にRequeryをしているためか、サブフォームの先頭のレコードに移動してしまうため、この時にレコードを新規登録する前の状態にしたいです。

例えば、サブフォーム内で一番下までスクロールした状態で、新規登録をした場合、サブフォームに新しく追加され、なお一番下までスクロールしてある状態にしたいです。

現状は、新規登録フォームで登録を押したときに

Forms!F_CustomerMaster!Sub_CustomerMaster.Requery


のような文を加えてあります。

この手の問題は調べると関連した記事が多く出るのですが、いまいち理解できなかったためコチラで直接質問させていただきました。

補足

(とある方の考え方を引用)
Requeryすると先頭のレコードへ移動してしまうので
Requeryする前のレコードの番号を取得して
Requery後にそのレコード番号へ移動 

といった感じが私としては、イメージがつきやすかったです。

追記

hatenaさんが提示してくださった感じで、追加後はサブフォームの帳票の方では、今追加したレコードをカレント?フォーカス?してある状況を作りたいです。

現状の登録フォームの登録コマンドボタンの処理です。

'----------------------------
'登録・編集ボタン使用時
'----------------------------

Private Sub Button_Add_Click()

    Me.Requery

    '背景色(白)    
    Me.Text_CustomerName.BackColor = 16777215
    Me.Text_Address.BackColor = 16777215

    '未入力エラー処理 背景色(赤)    
    If IsNull(Me.Text_CustomerName) Or IsNull(Me.Text_Address) Then  '顧客名    
        If IsNull(Me.Text_CustomerName) Then        
            Me.Text_CustomerName.BackColor = 12695295            
        End If        
        If IsNull(Me.Text_Address) Then  '住所        
            Me.Text_Address.BackColor = 12695295            
        End If       
        MsgBox "未入力の項目があります", vbOKOnly + vbExclamation, "未入力エラー"
        Exit Sub
    End If

    '追加・編集処理分岐

    Select Case Me.OpenArgs

        '追加モード        
        Case "追加"       
            Call add_tables
            Call del_tables            
            MsgBox "追加しました", vbOKOnly + vbInformation, "確認"

            'マスタの更新            
            Dim a As String           
            a = IsNull(Me.Text_CustomerCode)          
            With Forms!F_CustomerMaster!Sub_CustomerMaster.Form
                .Requery
                .Recordset.FindFirst "F_CustomerCode = '" & 100 & "'"
            End With


            'レコード数をカウントする
            TOTAL = DCount("F_CustomerCode", "T_Customer", "F_DeleteFlag = False")
            Forms!F_CustomerMaster.Text_Num = TOTAL + "件"

            '採番値を+1する           
            CurrentDb.Execute "UPDATE T_Num SET F_MgtCode = F_MgtCode +1 WHERE F_TableName = 'Customer'"                        
            wFormat = DLookup("F_Format", "T_Num", "F_TableName = 'Customer'")
            wMgtCode = DLookup("F_MgtCode", "T_Num", "F_TableName = 'Customer'")            
            Text_CustomerCode = Format(wMgtCode, wFormat)

        '編集モード        
        Case "編集"            
            wEdit = MsgBox("編集してもよろしいですか?", vbYesNo + vbQuestion, "確認")        
            If wEdit = vbYes Then                
                Call edit_tables           
                MsgBox "編集しました", vbOKCancel + vbInformation, "確認"                
                Exit Sub            
            Else    
                Exit Sub
            End If   
        End Select
End Sub


↓こちらのサイトを参考にしてみましたが、
サブフォームだけで、レコード削除したときはこちらでできたのですが、
今回の場合はうまく使えなくて・・・
参考にしてみた記事

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

Access のバージョンはなんでしょうか。
最近のAccess(2007以降ぐらい?)なら、

Forms!F_CustomerMaster!Sub_CustomerMaster.Requery


ではレコード移動しないはずですが。下記なら先頭へレコード移動します。

Forms!F_CustomerMaster!Sub_CustomerMaster.Form.Requery

この仕様変更になったときに、こりゃ便利だと話題になりました。

ちなみに、カレントレコード位置とスクロール位置は無関係です。上記はカレントレコード位置の保持です。スクロール位置を保持させたいという場合は、APIを必要としますので高度なスキルか必要になります。


Requeryする前のレコードの番号を取得して
Requery後にそのレコード番号へ移動 

上記のコード例

With Forms!F_CustomerMaster!Sub_CustomerMaster
    Dim AP As Long
    AP = .Form.Recordset.AbsolutePosition
    .Requery
    .Form.Recordset.AbsolutePosition = AP
End With

マスタのフッターにある新規登録ボタンを押すと、新規にデータを登録するフォームが開きます。
そのフォームで入力後、登録ボタンを押すと、マスタのサブフォームに追加されます。

という仕様なら、新規登録ボタンを押したときに、最後のレコードまで移動させてから、
登録フォームを開き、登録フォームで登録後、閉じたときに、追加したレコードがカレントレコードになっているというのがユーザーフレンドリーな仕様だと思います。
マスターの新規登録ボタンのクリック時

DoCmd.GoToRecord acActiveDataObject, , acLast
DoCmd.OpenForm "", WindowMode:=acDialog 


登録フォームの登録ボタン

’登録処理省略
With Forms!F_CustomerMaster!Sub_CustomerMaster.Form
    .Requery
    .Recordset.FindFirst "ID=" & Me.ID
End With
DoCmd.Close acForm , Me.Name


主キーフィールド名が ID で、データ型が数値型の場合のコード例です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/16 11:04

    With Forms!F_CustomerMaster!Sub_CustomerMaster.Form
    .Requery
     .Recordset.FindFirst "F_CustomerCode = " & Me.Text_CustomerCode
    End With
    ↑上記のように実行してみましたが、
    "抽出条件でデータ型が一致しません。" とういうエラーが出てしまい、わからず困惑しています。
    テキスト型のため、エラーが出ているのでしょうか。
    もしよろしければ、アドバイスの方をよろしくお願いします。

    キャンセル

  • 2019/07/16 11:09

    テキスト型の場合は、

     .Recordset.FindFirst "F_CustomerCode = '" & Me.Text_CustomerCode & "'"

    というように単引用符(')で囲んでください。

    キャンセル

  • 2019/07/16 11:20

    早速ありがとうございます。
    エラー問題は解決したのですが、Requery後にうまく動作していないみたいで、最新のレコードに飛んでくれないです。。。
    具体的には、
     .Recordset.FindFirst "F_CustomerCode = '" & Me.Text_CustomerCode & "'"
    この部分かと思われるのですが。。

    キャンセル

0

例えば登録していく伝票の主キー(IDとする)がオートナンバーで、一番最後に登録されたもののIDが一番大きくなり、その一番大きなIDと同じレコードに移動するのであれば以下のような方法でできるかもしれません。

  Dim newID As String
  Forms!親フォーム!サブフォーム.Requery
  newID = DMax("ID", "登録されたテーブル名")
  If Len(newID) > 0 And IsNumeric(newID) Then
    Forms!親フォーム!サブフォーム.Form.Recordset.FindFirst "ID = " & CLng(newID)
  End If


ただしおそらく希望の「95件から101件」ではなく「101件目から(下が余白)」のような感じになると思います。(hatenaさんの言うスクロール位置の保持ではなく「最新のレコードに移動する」ものです)
コード自体はこの辺のを参考にさせていただいた気がしますがちょっと前のことなので記憶が曖昧です。
https://tsware.jp/tips/tips_243.htm

IDが数字ではない(最大の数字では困る)場合などは一意となるデータで判断してください。


追記

簡易的に最低限のものを作ってテストしました。
Access2010
イメージ説明

テーブル

[CustomerTable]
CustomerCode テキスト型 主キー
CustomerName テキスト型

フォーム

[F_CustomerMaster]
ボタンやサブフォームを表示させるためのもの
非連結

[Sub_CustomerMaster]
顧客一覧を表示させるためのもの
[F_CustomerMaster]内にサブフォームとして表示(名前も[Sub_CustomerMaster])
レコードソース[CustomerTable]

[F_CustomerRegistration]
登録用フォーム
レコードソース[CustomerTable]
データ入力用「はい」

処理

1.[F_CustomerMaster]に「登録フォーム表示」ボタンを設置
クリック時イベントに以下を記述

  DoCmd.OpenForm "F_CustomerRegistration", WindowMode:=acDialog

2.[F_CustomerRegistration]に「登録」ボタンを設置
クリック時イベントに以下を記述

  Dim newID As String
  newID = Me.CustomerCode
  DoCmd.Close acForm, Me.Name
  With Forms!F_CustomerMaster!Sub_CustomerMaster.Form
      .Requery
      .Recordset.FindFirst "CustomerCode = '" & newID & "'"
  End With

これで一応
1.登録用(入力用)フォームをダイアログモードで表示
2.入力したCustomerCodeをnewIDに記憶し、Sub_CustomerMasterをRequery、newIDと同じレコードへ移動
はできると思われます。

実際は登録用フォームが入力用フォームではなかったり(非連結で追加クエリで追加してたり)CustomerCodeが自動的に入ったり他にも処理が入るとは思いますが「動かなくはないよ」という補足でした。
※元のコメントに書いたコードからDoCmd.Close acForm, Me.Nameの位置だけWithの前に移動してあります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/12 15:27

    With Forms!F_CustomerMaster!Sub_CustomerMaster.Form
    .Requery
    .Recordset.FindFirst "F_CustomerCode = '" & 100 & "'"
    End With
    登録処理をとりあえず無効にして、上記のように実行してみましたが、先程と実行結果は変わらずで。。。

    キャンセル

  • 2019/07/12 17:14

    わざわざ、再現していただきありがとうございます。
    同じレコードへ移動ということは、追加したレコードにカレントのカーソルがあるということでよろしいでしょうか?

    キャンセル

  • 2019/07/12 23:23

    そうですね、登録フォームで「999」とCustomerCodeを入力していた場合、リクエリされたSub_CustomerMasterの「999」があるレコードにカレントが移動するはずです。(レコードセレクタを"はい"にしておくとわかりやすいです)

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる