- ベストアンサー
access vba 『○○件づつ表示』を行いたい。
フォームにデータ一覧を決まった数ずつ表示させ、『次の10件』『前の10件』ボタンで、表示を切り替えたいのですが、構文をどう繋げてよいか理解できません。 今やっている事は、データにOutoNoを振り、まずフォームオープン時、SQL文ではじめの10件を抽出しています。その時、表示中データのOutoNoが一番小さいものにフラグを立てて変数にし、それを元に次の(又は『前の』)10件を抽出、と考えているのでが、、。 NEXT~FOR文を使うのかなと思うのですが、それをどう絡ませていけばよいのか分かりません。 データの最後が10で割った数にならないので、それもどうやって処理するか。 どうかご教授願います。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
ソース見ました。 ・毎回[Q_有給]を作りなおす という構造ですね? ・Q_有給は固定 ・Q_有給からデータを10件ずつ抽出する という流れにした方が、良いと思います。 以下のSQL文で、クエリを作成してください。 ※注意!!≪全角スペースを利用しておりますので、半角に置換してください≫ クエリ[Q_有給] ------------------------------------------------------------ SELECT M_社員.ナンバー ,T_日数.コード ,M_社員.氏名 ,M_社員.入社日 ,T_日数.有給付与日 ,T_日数.有給日数 FROM M_社員 INNER JOIN T_日数 ON M_社員.コード = T_日数.コード WHERE IIF((M_社員.退社日) > Date(),Null,(M_社員.退社日)) IS NULL ------------------------------------------------------------ [M_社員].[ナンバー] がオートナンバーフィールドですよね。 オートナンバーのフィールドが ・1-10 ・11-20 ・21-30 と、連続しているとは限りません。 [M_社員].[退社日]の状態により、不連続なデータになります。 入力キャンセルを行った場合だけでも、不連続データが発生します。 回避するためには、表示エリアデータの起点を見つけ、その前方/後方の表示対象データのキーを取得する必要があります。 フォームの中に、以下のソースを埋め込んでください。 VBAソース ------------------------------------------------------------ Option Compare Database Option Explicit '定数 Private Const DEF_SQL_MAIN As String = "SELECT * FROM Q_有給" & vbCrLf 'メインのSQL文 Private Const DEF_AUTO_NO As String = "[ナンバー]" 'クエリのメインキー Private Const DEF_SQL_ORDER As String = "ORDER BY " & DEF_AUTO_NO & vbCrLf 'SQLのOrderBy句 Private Const DEF_MOVE_VECT As Integer = 10 '表示量 '列挙:移動種別 Private Enum ENM_MOVE MV_開始 MV_戻る MV_進む End Enum '構造体:表示領域 Private Type typ表示領域 lng開始 As Long lng終了 As Long End Type '表示領域記憶変数 Private m表示状態 As typ表示領域 'イベント/ボタン/進む Private Sub cmd進む_Click() Call Sub画面リフレッシュ(MV_進む) End Sub 'イベント/ボタン/戻る Private Sub cmd戻る_Click() Call Sub画面リフレッシュ(MV_戻る) End Sub 'イベント/フォーム/開く時 Private Sub Form_Open(Cancel As Integer) Call Sub画面リフレッシュ(MV_開始) End Sub '画面のレコードソースとボタン状態の切替を行う Private Sub Sub画面リフレッシュ( _ ByVal p_移動方向 As ENM_MOVE _ , Optional ByVal p_lng移動量 As Integer = DEF_MOVE_VECT _ ) 'データ操作用 Dim strSQL As String Dim daoDB As DAO.Database Dim daoRec As DAO.Recordset 'オートナンバー対策 Dim lng基準 As Long Dim lng開始番号 As Long Dim lng終了番号 As Long 'ボタン制御用フラグ Dim bln戻る As Boolean Dim bln進む As Boolean '基本的にボタンは使用不可とする bln戻る = False bln進む = False '基準点を得る Select Case p_移動方向 Case MV_開始 lng基準 = 0 Case MV_戻る lng基準 = m表示状態.lng開始 Case MV_進む lng基準 = m表示状態.lng終了 End Select '基準点をベースにSQLを発行 strSQL = "" strSQL = strSQL & DEF_SQL_MAIN strSQL = strSQL & "WHERE " & DEF_AUTO_NO & IIf((p_移動方向 = MV_戻る), "<=", ">=") & lng基準 & vbCrLf strSQL = strSQL & DEF_SQL_ORDER Set daoRec = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot) '取得できない If daoRec.EOF Then lng開始番号 = 0 lng終了番号 = 0 '終了処理へ GoTo PGMEND End If '取得できた Select Case p_移動方向 Case MV_開始, MV_進む '先頭 daoRec.MoveFirst If (p_移動方向 = MV_開始) Then '開始ポイントの記憶 lng開始番号 = daoRec(DEF_AUTO_NO) Else '戻るボタン使用可能 bln戻る = True '一個移動 daoRec.MoveNext '移動し過ぎの回避 If daoRec.EOF Then daoRec.MovePrevious End If '開始ポイントの記憶 lng開始番号 = daoRec(DEF_AUTO_NO) End If '移動:表示エリア + 1 daoRec.Move p_lng移動量 'データの存在チェックを行い、進むボタンの使用可能状態を決める bln進む = Not daoRec.EOF '移動:表示エリアの最後 daoRec.MovePrevious '終了ポイントの記憶 lng終了番号 = daoRec(DEF_AUTO_NO) Case MV_戻る '最後 daoRec.MoveLast '進むボタン使用可能 bln進む = True '一個移動 daoRec.MovePrevious '移動し過ぎの回避 If daoRec.BOF Then daoRec.MoveNext End If '終了ポイントの記憶 lng終了番号 = daoRec(DEF_AUTO_NO) '移動:表示エリア - 1 daoRec.Move -p_lng移動量 'データの存在チェックを行い、戻るボタンの使用可能状態を決める bln戻る = Not daoRec.BOF '移動:表示エリアの先頭 daoRec.MoveNext '開始ポイントの記憶 lng開始番号 = daoRec(DEF_AUTO_NO) End Select '終了処理 PGMEND: 'データセット開放 daoRec.Close Set daoRec = Nothing '表示領域エリアを記憶 m表示状態.lng開始 = lng開始番号 m表示状態.lng終了 = lng終了番号 '画面の入力フィールドにフォーカスを当てる Me.コード.SetFocus 'ボタン状態の制御 Me.cmd戻る.Enabled = bln戻る Me.cmd進む.Enabled = bln進む 'SQLを作成 strSQL = "" strSQL = strSQL & DEF_SQL_MAIN strSQL = strSQL & "WHERE " & DEF_AUTO_NO & " BETWEEN " & lng開始番号 & " AND " & lng終了番号 & vbCrLf strSQL = strSQL & DEF_SQL_ORDER 'SQLを設定 Me.RecordSource = strSQL End Sub
その他の回答 (4)
- ALGO-9
- ベストアンサー率66% (12/18)
指定件数単位に抽出するクエリを作成し、それを基に一覧形式のフォームを作成 出来上がったフォームをメインフォームへサブフォームとして埋め込み画面 は完了 後は、『次の10件』『前の10件』のイベントでSQL文を編集しサブフォームの基となっているクエリを変更し、画面をリフレッシュすればOK ※データ表示を一覧形式のフォームを利用すると仮定した場合 Event:NextBotton Dim l_OutoNo = l_OutoNo + 10 SSQL = "SELECT * FROM データテーブル WHERE Between OutoNo & CStr(l_OutoNo) & " And " & CStr(l_OutoNo + 9) SubForm_Query.SQL = SSQL Me.MainForm.SubForm.Form.F_Sub.Refresh
お礼
回答を有難うございます。 なるほど、next forにこだわりすぎていました。勉強になります。
- 1050 円(@1050YEN)
- ベストアンサー率69% (477/687)
SQL文の発行は、DAO?ADO? DAOなら 「Set レコードセット=CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot)」 として、EOF/BOFのチェック さらに 「レコードセット.Move 移動量」 で指定のレコード位置にカーソルを移動できます。 存在するレコード以下、あるいは以上の位置にカーソルを移動しようとすると、EOF/BOFになります。 >SQL文ではじめの10件を抽出しています 現在どのような処理が行われているのか、コードが見たいです。 それにより、極力改造を必要としない方法が見つかるかもしれません。
お礼
大変失礼しました。 まずフォームオープン時、 Dim qdf As QueryDef Dim strsql As String strsql = "" strsql = strsql & "SELECT T_日数.コード, M_社員.氏名, M_社員.入社日, T_日数.有給付与日, T_日数.有給日数, " strsql = strsql & "FROM M_社員 INNER JOIN T_日数 ON M_社員.コード = T_日数.コード " strsql = strsql & "WHERE (((M_社員.退社日)>Date() Or (M_社員.退社日) Is Null and (M_社員.ナンバー)<=10 ));" Set qdf = CurrentDb.QueryDefs("Q_有給") qdf.SQL = strsql qdf.Close Me.RecordSource = "Q_有給" です。 そして各『前ページ』『次ページ』を各コードに書かず、モジュール側で10を変数にして扱うのはどうしたら、、、と困っていたのです。 DAOも他で使っている箇所があるんですが、色々参考書を読んでみてるんですけど、いまいち明確な使い方(データを見せるだけの処理であるとか、架空のものとか)がただの抽出とどう違うのかが難しくて。 私事ですが.netも覚える事になっていて、その辺りもまた詳しく質問をさせてもらおうと思っています。ありがとうございました。
- skink
- ベストアンサー率38% (7/18)
#1ですが、ざっと書いてみました。 データは配列に格納できているものとします。 「フォームに表示」の形態がわからないので、仮にテキストボックスとしました。 Private DataNum as Long '全部のデータ数 Private DataBuff() as String 'データを格納した配列 Private cnt As Long '「進む」ボタンクリック Private Sub cmdnext_Click() Dim i As Integer txtData.Text = "" For i = 0 To 9 If 10 * cnt + i > DataNum Then Exit Sub txtData.Text = txtData.Text & vbCrLf & DataBuff(10 * cnt + i) Next cnt = cnt + 1 End Sub '「戻る」ボタンクリック Private Sub cmdpre_Click() Dim i As Integer txtData.Text = "" cnt = cnt - 1 If cnt < 0 Then cnt = 0 For i = 0 To 9 txtData.Text = txtData.Text & vbCrLf & DataBuff(10 * cnt + i) Next End Sub
お礼
丁寧なご回答をありがとうございます。 色んな方法を知ることができて勉強になりました。 今後も役に立ちそうです。 感謝します!!
- skink
- ベストアンサー率38% (7/18)
こんにちは。 いちいち毎回10件ずつのSQLを発行するのではなく、最初に全部取得して配列に格納してしまい、 それを表示した方が楽だと思います。
お礼
できました! 別の回答で教えて頂いたように、コードを見るって勉強になりますね。 とても丁寧な解説に感謝しています。 ありがとうございました。