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

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

新規登録して質問してみよう
ただいま回答率
85.44%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

Q&A

解決済

2回答

21580閲覧

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

退会済みユーザー

退会済みユーザー

総合スコア0

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

0グッド

0クリップ

投稿2019/07/10 02:38

編集2019/07/16 02:56

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

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

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

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

VBA

1Forms!F_CustomerMaster!Sub_CustomerMaster.Requery

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

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

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

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

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

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

VBA

1'---------------------------- 2'登録・編集ボタン使用時 3'---------------------------- 4 5Private Sub Button_Add_Click() 6 7 Me.Requery 8 9 '背景色(白) 10 Me.Text_CustomerName.BackColor = 16777215 11 Me.Text_Address.BackColor = 16777215 12 13 '未入力エラー処理 背景色(赤) 14 If IsNull(Me.Text_CustomerName) Or IsNull(Me.Text_Address) Then '顧客名 15 If IsNull(Me.Text_CustomerName) Then 16 Me.Text_CustomerName.BackColor = 12695295 17 End If 18 If IsNull(Me.Text_Address) Then '住所 19 Me.Text_Address.BackColor = 12695295 20 End If 21 MsgBox "未入力の項目があります", vbOKOnly + vbExclamation, "未入力エラー" 22 Exit Sub 23 End If 24 25 '追加・編集処理分岐 26 27 Select Case Me.OpenArgs 28 29 '追加モード 30 Case "追加" 31 Call add_tables 32 Call del_tables 33 MsgBox "追加しました", vbOKOnly + vbInformation, "確認" 34 35 'マスタの更新 36 Dim a As String 37 a = IsNull(Me.Text_CustomerCode) 38 With Forms!F_CustomerMaster!Sub_CustomerMaster.Form 39 .Requery 40 .Recordset.FindFirst "F_CustomerCode = '" & 100 & "'" 41 End With 42 43 44 'レコード数をカウントする 45 TOTAL = DCount("F_CustomerCode", "T_Customer", "F_DeleteFlag = False") 46 Forms!F_CustomerMaster.Text_Num = TOTAL + "件" 47 48 '採番値を+1する 49 CurrentDb.Execute "UPDATE T_Num SET F_MgtCode = F_MgtCode +1 WHERE F_TableName = 'Customer'" 50 wFormat = DLookup("F_Format", "T_Num", "F_TableName = 'Customer'") 51 wMgtCode = DLookup("F_MgtCode", "T_Num", "F_TableName = 'Customer'") 52 Text_CustomerCode = Format(wMgtCode, wFormat) 53 54 '編集モード 55 Case "編集" 56 wEdit = MsgBox("編集してもよろしいですか?", vbYesNo + vbQuestion, "確認") 57 If wEdit = vbYes Then 58 Call edit_tables 59 MsgBox "編集しました", vbOKCancel + vbInformation, "確認" 60 Exit Sub 61 Else 62 Exit Sub 63 End If 64 End Select 65End Sub

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

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

vba

1Forms!F_CustomerMaster!Sub_CustomerMaster.Requery

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

vba

1Forms!F_CustomerMaster!Sub_CustomerMaster.Form.Requery

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

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


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

上記のコード例

vba

1With Forms!F_CustomerMaster!Sub_CustomerMaster 2 Dim AP As Long 3 AP = .Form.Recordset.AbsolutePosition 4 .Requery 5 .Form.Recordset.AbsolutePosition = AP 6End With

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

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

vba

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

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

vba

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

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

投稿2019/07/10 03:41

編集2019/07/10 06:41
hatena19

総合スコア33856

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/07/10 04:19

私もその方法を見て、実践してみたのですが、レコードの追加後、一番上のレコードに戻ってしまうのです。 因みにAccessのバージョンは、もともと2010で作成していたのですが、今は最新のもので作成しております。
hatena19

2019/07/10 04:43 編集

標準モジュールにこのコード1行のみのプロシージャを作成して、実行してみても先頭に移動しますか。 当方も最新のAccessで動作確認してますが、レコード移動はしません。ただし、カレントレコードが表示範囲外にあるときは、カレントレコードが見える位置までスクロールはします。このスクロールのことをいっていますか。
退会済みユーザー

退会済みユーザー

2019/07/10 05:10

標準モジュールということは、新しいまっさらなモジュールを作成し そこにこの一行を書いて、登録ボタンが押されたときにcallで呼び出すということでしょうか? スクロールというよりは、一番下のレコードが表示されている状態のことですね。 カレントレコードというのは、どうやって決まるのですか? レコードクリックした状態ということでしょうか?
hatena19

2019/07/10 05:27 編集

> 標準モジュールということは、新しいまっさらなモジュールを作成し > そこにこの一行を書いて、登録ボタンが押されたときにcallで呼び出すということでしょうか? はい、そうです。それで、レコード移動しなければ、別の部分に問題があると切り分けられます。 カレントレコードとは、選択されているか、現在、カーソルのあるレコードのことです。 帳票レコードなら、左端のレコードセレクターに ▶マークが表示されている行です。 例えば、先頭レコードを選択しておいて、スクロールバーで一番下までするロールした状態で、Requeryしたら先頭までスクロールします。 一番してまでするロールした後、最後のレコードをクリックして選択すれば、移動しません。 前期の、スクロール位置も保持したいのなら、回答にも書きましたがAPIが必要になりますので、高度なスキルが必要になります。 質問の補足の「とある方の考え方」はレコード位置の保持の方法です。
退会済みユーザー

退会済みユーザー

2019/07/10 05:28

今までレコードセレクトを表示させていなかったので表示させたらカレントレコードについては理解できました。それを踏まえてなのですが、一番下までスクロールして状態で一番最後のレコードをクリックしカレントにした状態で追加してみたのですが、再クエリすると、カーソルが一番初めのレコードまで戻ってしまいます。 うまくレコードの位置を保持出来ていないということでしょうか。
hatena19

2019/07/10 05:32

うーん、当方のAccessでは再現できないので、「とある方の考え方」のコードを回答の方に追記しておきます。
退会済みユーザー

退会済みユーザー

2019/07/10 05:49 編集

追記ありがとうございます。参考にさせていただきます。 因みにひとつ疑問なのですが、表示している状態をまんま保持するのは、スクロールバーと関係ありますか? イメージとしては、Me.Refreshみたいな感じで
hatena19

2019/07/10 06:23

「表示している状態をまんま保持する」という意味が、スクロールバーをマウスで移動したら保持できていないということなら、関係ありますね。 Refresh はカレントレコードのみ更新という意味ですので、Requery とはまったく異なる動作のものです。
hatena19

2019/07/10 06:27

そもそも、入力、更新対象のレコード(カレントレコード)がスクロールされて表示されていない状態というのはUI的には異常な状態といえると思います。更新対象のレコードが見える位置にスクロールするというのはまっとうな仕様だと思います。 新規レコードを追加するボタンなら、登録フォームて登録後、登録したレコードへ移動するというのがユーザーフレンドリーUIかと思います。
退会済みユーザー

退会済みユーザー

2019/07/11 00:08

追記ありがとうございます。 教えて頂いた方向で検討してみようと思います。
退会済みユーザー

退会済みユーザー

2019/07/11 01:19

上記の > DoCmd.OpenForm "", WindowMode:=acDialog の "" の中にはフォーム名を入れればいいですか? また、WindowMode:=acDialog は第二引数ですか?
hatena19

2019/07/11 02:07

""にはフォーム名をいれてください。 引数には2種類の書き方があります。第一引数から順番に記述していく方法と、引数の名前を指定して記述する方法です。上記は引数名で指定する方法です(名前付き引数といいます)。 WindowMode引数は第6引数ですが、このような場合は、名前付き引数にすると読みやすくなります。 今回のように別フォームで入力・更新する場合は、大ログモード(acDialog)を指定して、ほかの部分を操作できないようにしておくのは必須です。
退会済みユーザー

退会済みユーザー

2019/07/11 02:32

DoCmd.OpenForm "F_WCustomerInput", , , , ,WindowMode:=acDialog , "追加" ↑のように順番にやってみたのですが、これだと第七引数がエラーになってしみました。 因みに "追加" は 追加用と編集用を分岐させるものです。
dit.

2019/07/11 02:33

hatena19さん誤字ってるような気がするので一応突っ込んでおきます。 大ログモード→ダイアログモード
hatena19

2019/07/11 03:38

あら、(;'∀') dit.さん、ご指摘ありがとうございます。さっそく修正しておきました。
hatena19

2019/07/11 03:44

Yryuさん DoCmd.OpenForm "F_WCustomerInput", , , , ,acDialog , "追加" とするか、 DoCmd.OpenForm "F_WCustomerInput", WindowMode:=acDialog ,OpenArgs:="追加" とするか、 のどちらかです。 名前付き引数を使った記述法は引数の順番は自由にできます。 両者の記述法を混在させることはできません。
退会済みユーザー

退会済みユーザー

2019/07/12 01:10 編集

あ、なるほど、そういった書き方だったんですね。 了解いたしました。 疑問に思ったのですが、 なぜ、マスタの新規登録ボタンの時に一番下のレコードに移動させるのでしょうか?
hatena19

2019/07/16 01:10

正確には新規レコード行に移動ですね。 ユーザーに新規レコードを追加する操作だというとこは明確にするためです。 新規レコードが非表示の場合は、最後のレコードが違和感ないと思います。
退会済みユーザー

退会済みユーザー

2019/07/16 02:04

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

2019/07/16 02:09

テキスト型の場合は、  .Recordset.FindFirst "F_CustomerCode = '" & Me.Text_CustomerCode & "'" というように単引用符(')で囲んでください。
退会済みユーザー

退会済みユーザー

2019/07/16 02:20

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

0

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

vba

1 Dim newID As String 2 Forms!親フォーム!サブフォーム.Requery 3 newID = DMax("ID", "登録されたテーブル名") 4 If Len(newID) > 0 And IsNumeric(newID) Then 5 Forms!親フォーム!サブフォーム.Form.Recordset.FindFirst "ID = " & CLng(newID) 6 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]に「登録フォーム表示」ボタンを設置
クリック時イベントに以下を記述

vba

1 DoCmd.OpenForm "F_CustomerRegistration", WindowMode:=acDialog 2

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

vba

1 Dim newID As String 2 newID = Me.CustomerCode 3 DoCmd.Close acForm, Me.Name 4 With Forms!F_CustomerMaster!Sub_CustomerMaster.Form 5 .Requery 6 .Recordset.FindFirst "CustomerCode = '" & newID & "'" 7 End With

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

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

投稿2019/07/10 05:54

編集2019/07/12 07:34
dit.

総合スコア3235

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/07/12 04:37

IDがテキスト型なので Forms!F_CustomerMaster!Sub_CustomerMaster.Form.Recordset.FindFirst "F_CustomerCode = " & a のようにやってみたのですが、やはりデータ型でエラーがでてしまい、テキスト型の場合は、Cstrにすればよいのでしょうか。
dit.

2019/07/12 05:13

そもそも私回答でnewIDをstringにしてましたね。うっかり。 hatenaさんのやり方でOKだと思いますがテキスト型(数字じゃない)なら少し変えないといけないかも。 未テストですが多分こんな感じ。 ``` '登録処理省略 Dim newID As String newID = me.[ID入力テキストボックス名] With Forms!F_CustomerMaster!Sub_CustomerMaster.Form .Requery .Recordset.FindFirst "ID ='" & newID & "'" End With ``` ※違ったら詳しい方ツッコミお願いします。
退会済みユーザー

退会済みユーザー

2019/07/12 05:40 編集

>newID = me.[ID入力テキストボックス名]のところでnullの使い方が不正と出るので、isnullにしてみて実行したのですが、requeryはされるものの、サブフォームの方では、一番上(先頭?)のレコードまで戻ってしまいました。。。
dit.

2019/07/12 05:50

登録フォームの登録ボタンの処理の中で実行してますよね? me.[ID入力テキストボックス名]は登録フォームのテキストボックスの中身を入れたくて使ったので、登録フォームのIDを入力するためのボックスに文字列が入っていれば問題ないと思ったのですが…。 .Recordset.FindFirst "ID ='" & newID & "'"がうまく動くか確かめたいので、登録処理をコメントアウトなどで無効化したうえでnewID = "すでに登録されているID"に変えてテストしてみていただけますか?
退会済みユーザー

退会済みユーザー

2019/07/12 06:11

長々しいですが、一応現状の登録ボタンの処理を追記しておきました。 正常に動けば、登録されているIDのレコードにジャンプしてくれる動きということでよろしいでしょうか??
退会済みユーザー

退会済みユーザー

2019/07/12 06:27

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

退会済みユーザー

2019/07/12 08:14

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

2019/07/12 14:23

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.44%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問