レコードセットをページングするには
Accessのデータベースado.mdbから得意先テーブルのレコードセットを作成して複数のページに分割して表示する方法を説明します。レコードセットの内容をHTMLページに表示させるとき、レコード数を制約しないと結果が表示されるまで時間がかかり過ぎて実用的ではありません。この場合、1回の要求で表示するレコード数を適当な範囲で制約することにより快適なレスポンスを保障することができます。
レコードセットを複数のページに分割して表示する場合、すべてアプリケーション側で対処する方法もありますが、RecordsetオブジェクトのPageSize, PageCount, AbsolutePageプロパティを使用することにより比較的簡単にページング処理を行うことができます。
● ページ当たりのレコード数を固定とするサンプル
得意先テーブルのレコードセットをページ当たり10レコード単位で複数のページに分割して表示する方法を説明します。ここで紹介するサンプルは、ページを移動するために「Prev 1 2 3 4 5 Next」のようなハイパーリンクを表示します。3はカレントのページを意味します。Prevのリンクをクリックするとページ2を表示します。Nextのリンクをクリックするとページ4を表示します。ページ番号(1 2 4 5)のリンクをクリックすると対応するページを表示します。
Access + Webのダウンロードにサンプルが収録されています。ダウンロードの目次を表示させたら、「AbsolutePage, PageSize, PageCountプロパティを利用した手法」をクリックしてください。Internet Explorerの左側のフレームには、ASPのソースが表示されます。右側のフレームには、実行結果が表示されます。
リストの行43では、intPageSizeにページ当たりのレコード件数10を設定しています。このサンプルでは、1ページ当たり10レコード表示します。
43: intPageSize = 10
行45-49では、RequestオブジェクトのQueryStringメソッドでカレントページ(page=)のQueryStringを取得して値を調べています。カレントページのQueryStirngが空白のときは、intPageCurrentに1を設定して初期化します。カレントページのQueryStringが指定されているときは、CInt()関数で整数型に変換してintPageCurrentに保存します。QueryStringは、ページ移動用のハイパーリンクに指定しています。
<a href='RecordsetPaging.asp?page=1'>1</a>
45: if len(request.QueryString("page")) = 0 then
46: intPageCurrent = 1
47: else
48: intPageCurrent = CInt(request.QueryString("page"))
49: end if
行51-54では、Accessのデータベースado.mdbを接続するための処理を行っています。行51-52では、OLEDBのProviderとData Sourceを設定してstrConnectionに保存しています。行54では、ConnectionオブジェクトのOpenメソッドでado.mdbを接続しています。
51: strConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" _
52: & "Data Source=" & server.MapPath("webdb/ado.mdb")
53: set cnn = server.CreateObject("adodb.connection")
54: cnn.Open strConnection
行56-58では、得意先テーブルからレコードを抽出するSQLを作成してstrSQLに保存しています。SQLのSELECTのフィールド名には、得意先コード、得意先名、担当者名、電話番号を指定しています。また、このSQLには、ORDER BY句が指定されていますので得意先コード順に並べ替えられます。
56: strSQL = "Select 得意先コード,得意先名,担当者名,電話番号" _
57: & " From 得意先" _
58: & " Order by 得意先コード;"
行60では、ServerオブジェクトのCreateObjectメソッドでRecordsetのインスタンスを生成しています。行61では、RecordsetオブジェクトのPageSizeプロパティにintPageSizeを設定します。intPageSizeには、10が保存されていますので1ページに10レコード表示されます。行62では、RecordsetのCursorLocationプロパティにadUseClientを設定しています。行63では、RecordsetのCashSizeプロパティにintPageSizeを設定しています。(つまり、キャッシュサイズとページサイズを一致させています。)行64-65では、RecordsetのOpenメソッドで得意先テーブルのレコードセットを生成しています。
60: set rs = server.CreateObject("adodb.recordset")
61: rs.PageSize = intPageSize
62: rs.CursorLocation = adUseClient
63: rs.CacheSize = intPageSize
64: rs.Open strSQL, cnn, adOpenStatic, _
65: adLockReadOnly, adCmdText
行66-70では、RecordsetオブジェクトのPageCountプロパティを調べています。PageCountプロパティが0なら、Response.Clearメソッドでバッファの内容を消去してからEchoを呼び出して「レコードがありません!」のメッセージを表示します。最後に、Response.Endメソッドでこのページの処理を終了します。
66: if rs.PageCount = 0 then
67: response.Clear
68: Echo "レコードがありません!"
69: response.End
70: end if
Sub Echoは、行6-8に定義されています。このSubは、引数で指定された文字列をResponse.Writeメソッドでブラウザに送信します。Sub EchoNLは、行9-11に定義されています。このSubは、引数で指定された文字列をResponse.Writeメソッドでブラウザに送信します。このとき、NewLine(CR+LF: Carriage Return + Line Feedの略)も同時に送信します。
行72では、RecordsetオブジェクトのPageCountプロパティをintPageCountに保存しています。このプロパティにはレコードセットの総ページ数が格納されています。
72: intPageCount = rs.PageCount
行74-79では、QueryStringのカレントページがRecordsetの総ページ数の範囲内か調べています。カレントページがRecordsetの総ページ数より大きいときは、カレントページをRecordsetの総ページ数にします。また、カレントページが1より小さいときは、1にします。
74: if intPageCurrent > intPageCount then
75: intPageCurrent = intPageCount
76: end if
77: if intPageCurrent < 1 then
78: intPageCurrent = 1
79: end if
行81では、RecordsetのAbsolutePageプロパティにQueryStringのカレントページを設定します。これでカレントレコードは、QueryStringのカレントページの先頭レコードに位置付けされます。
81: rs.AbsolutePage = intPageCurrent
行82-84では、カレントページと総ページ数を「Page 1 of 6」の形式で表示します。
82: echo "Page <b>" & intPageCurrent _
83: & "</b> of <b>" & intPageCount & "</b>"
84: echoNL"<br><br>"
行86,107では、HTMLの表を作成するために<table>・・・</table>タグを送信しています。
86: EchoNL"<table border='1'>"
・・・
107: EchoNL"</table>"
行87-93では、表の見出しを送信しています。行88-92のfor…nextでは、Recordsetのフィールド名を見出しとして送信しています。
87: EchoNL vbTab & "<tr>"
88: for intI = 0 to rs.Fields.Count - 1
89: Echo vbTab & vbTab & "<th>"
90: Echo rs.Fields(intI).Name
91: EchoNL "</th>"
92: next
93: EchoNL vbTab & "</tr>"
行95-106では、QueryStringのカレントページをブラウザに送信しています。行95では、カレントページに送信したレコード数を0に初期化しています。行96-106のdo while…loopでは、カレントページに表示するレコードを送信しています。行98-102のfor…nextでは、カレントレコードのすべてのフィールドを送信しています。行104では、カレントページに送信したレコード数を+1加算しています。行105では、RecordsetのMoveNextメソッドで次のレコードに移動しています。カレントレコードがカレントページの最終レコードのとき、またはEOFが報告されたときdo while…loopが終了します。
95: intRecordsShown = 0
96: do while intRecordsShown < intPageSize and not rs.EOF
97: EchoNL vbTab & "<tr>"
98: for intI = 0 to rs.Fields.Count - 1
99: Echo vbTab & vbTab & "<td>"
100: Echo rs.fields(intI)
101: EchoNL "</td>"
102: next
103: EchoNL vbTab & "</tr>"
104: intRecordsShown = intRecordsShown + 1
105: rs.MoveNext
106: loop
行109-110では、レコードセットを閉じてデータベースを切断しています。
109: rs.Close
110: cnn.Close
行115-132では、表の最後にページ移動用のハイパーリンク(HTMLの<a>・・・</a>タグ)を生成しています。行115-118では、カレントページが1以上のとき「Prev」のハイパーリンクを生成します。
<a href='RecordsetPaging.asp?page=3'>Prev</a>
115: if intPageCurrent > 1 then
116: EchoNL "<a href='RecordsetPaging.asp?page=" _
117: & intPageCurrent - 1 & "'>Prev</a> "
118: end if
行120-127のfor…nextでは、カレントページを除く各ページのハイパーリンクを生成しています。カレントページは、通常のテキストとして表示します。「 」は、印字されない空白でCHR(160)に対応します。HTMLでは、空白CHR(32)を送信しても無視されますが、CHR(160)を送信すると空白が確保されます。
<a href='RecordsetPaging.asp?page=1'>1</a>
<a href='RecordsetPaging.asp?page=2'>2</a>
<a href='RecordsetPaging.asp?page=3'>3</a>
4
<a href='RecordsetPaging.asp?page=5'>5</a>
<a href='RecordsetPaging.asp?page=6'>6</a>
120: for intI = 1 to intPageCount
121: if intI = intPageCurrent then
122: Echo intI & " "
123: else
124: EchoNL "<a href='RecordsetPaging.asp?page=" _
125: & intI & "'>" & intI & "</a> "
126: end if
127: next
行129-132では、カレントページが最終ページ以外のとき「Next」のハイパーリンクを生成しています。
<a href='RecordsetPaging.asp?page=5'> Next</a>
129: if intPageCurrent < intPageCount then
130: EchoNL "<a href='RecordsetPaging.asp?page=" _
131: & intPageCurrent + 1 & "'> Next</a>"
132: end if
|
|
図 得意先テーブルのレコードを複数ページに分割して表示するサンプル(その1)
|
|
図 得意先テーブルのレコードを複数ページに分割して表示するサンプル(その2)
リスト RecordsetPaging.aspのソースコード
|
1: <%@ language=vbscript %> 2: <% option explicit %> 3: <% response.buffer = true %> 4: <!--#include file=adovbs.inc --> 5: <% 6: sub Echo(strMsg) 7: response.write strMsg 8: end sub 9: sub EchoNL(strMsg) 10: response.write strMsg & vbNewLine 11: end sub 12: %> 13: <html> 14: <head> 15: <style> 16: tr { 17: background: cyan; 18: font-size: 80%; 19: } 20: 21: th { 22: color: blue; 23: } 24: 25: td { 26: color: black; 27: } 28: 29: </style> 30: </head> 31: <body> 32: <% 33: dim cnn, rs 34: dim strSQL 35: dim strConnection 36: 37: dim intPageSize 38: dim intPageCount 39: dim intPageCurrent 40: dim intRecordsShown 41: dim intI 42: 43: intPageSize = 10 44: 45: if len(request.QueryString("page")) = 0 then 46: intPageCurrent = 1 47: else 48: intPageCurrent = cint(request.QueryString("page")) 49: end if 50: 51: strConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" _ 52: & "Data Source=" & server.MapPath("webdb/ado.mdb") 53: set cnn = server.CreateObject("adodb.connection") 54: cnn.open strConnection 55: 56: strSQL = "Select 得意先コード,得意先名,担当者名,電話番号" _ 57: & " From 得意先" _ 58: & " Order by 得意先コード;" 59: 60: set rs = server.CreateObject("adodb.recordset") 61: rs.PageSize = intPageSize 62: rs.CursorLocation = adUseClient 63: rs.CacheSize = intPageSize 64: rs.Open strSQL, cnn, adOpenStatic, _ 65: adLockReadOnly, adCmdText 66: if rs.PageCount = 0 then 67: response.clear 68: echo "レコードがありません!" 69: response.end 70: end if 71: 72: intPageCount = rs.PageCount 73: 74: if intPageCurrent > intPageCount then 75: intPageCurrent = intPageCount 76: end if 77: if intPageCurrent < 1 then 78: intPageCurrent = 1 79: end if 80: 81: rs.AbsolutePage = intPageCurrent 82: echo "Page <b>" & intPageCurrent _ 83: & "</b> of <b>" & intPageCount & "</b>" 84: echoNL"<br><br>" 85: 86: echoNL"<table border='1'>" 87: echoNL vbTab & "<tr>" 88: for intI = 0 to rs.fields.count - 1 89: echo vbTab & vbTab & "<th>" 90: echo rs.fields(intI).name 91: echoNL "</th>" 92: next 93: echoNL vbTab & "</tr>" 94: 95: intRecordsShown = 0 96: do while intRecordsShown < intPageSize and not rs.eof 97: echoNL vbTab & "<tr>" 98: for intI = 0 to rs.fields.count - 1 99: echo vbTab & vbTab & "<td>" 100: echo rs.fields(intI) 101: echoNL "</td>" 102: next 103: echoNL vbTab & "</tr>" 104: intRecordsShown = intRecordsShown + 1 105: rs.MoveNext 106: loop 107: echoNL"</table>" 108: 109: rs.close 110: cnn.close 111: set rs = nothing 112: set cnn = nothing 113: 114: echo "<br>" 115: if intPageCurrent > 1 then 116: echoNL "<a href='RecordsetPaging.asp?page=" _ 117: & intPageCurrent - 1 & "'>Prev</a> " 118: end if 119: 120: for intI = 1 to intPageCount 121: if intI = intPageCurrent then 122: echo intI & " " 123: else 124: echoNL "<a href='RecordsetPaging.asp?page=" _ 125: & intI & "'>" & intI & "</a> " 126: end if 127: next 128: 129: if intPageCurrent < intPageCount then 130: echoNL "<a href='RecordsetPaging.asp?page=" _ 131: & intPageCurrent + 1 & "'> Next</a>" 132: end if 133: %> 134: </body> 135: </html> |
● ページ当たりのレコード数を可変とするサンプル
ここで紹介するサンプルは、得意先テーブルのレコードセットを複数のページに分割して表示するとき、ページ当たりのレコード数をドロップダウンリストから選択することができます。さらに、レコードセットを得意先コード順、またはフリガナ順に並べ替えて表示させることができます。
Access + Webのダウンロードにサンプルが収録されています。ダウンロードの目次を表示させたら、「ページサイズ、ソート順を任意に選択可能とした例」をクリックしてください。Internet Explorerの左側のフレームには、ASPのソースが表示されます。右側のフレームには、実行結果が表示されます。
リスト にサンプルのソースを掲載していますが、網がけの部分が追加/変更された箇所です。ここでは、追加変更された箇所を中心に説明します。
行49-65では、RequestオブジェクトのQueryStringメソッドでpage=, pagesize=, order=のQueryStringを取得しています。これらのQueryStringは、ページ移動用のハイパーリンクで設定しています。再設定のボタンをクリックしたときは、ドロップダウンリストから選択したpagesizeと orderが自動的にQueryStringに設定されます。行49-53では、page=のQueryStringを取得してintPageCurrentに保存しています。行55-59では、pagesize=のQueryStirngを取得してintPageSizeに保存しています。行61-65では、order=のQueryStringを取得してstrOrderByに保存しています。order=には、「得意先コード」または「フリガナ」が指定されますが、URLEncodeされています。たとえば、「得意先コード」の場合、以下のようにURLEncodeされて渡されます。
order=%93%BE%88%D3%90%E6%83R%81%5B%83h
Server.QueryStringメソッドで、order=のQueryStringを取得すると自動的にDecodeされて「得意先コード」が返されます。
<a href='RecordsetPaging2.asp?page=7&pagesize=5&order='>Prev</a>
<a href='RecordsetPaging2.asp?page=1&pagesize=5&order='>1</a>
・・・
<a href='RecordsetPaging2.asp?page=12&pagesize=5&order='>12</a>
<a href='RecordsetPaging2.asp?page=8&pagesize=5&order='>Next</a>
49: if len(request.QueryString("page")) = 0 then
50: intPageCurrent = 1
51: else
52: intPageCurrent = CInt(request.QueryString("page"))
53: end if
54:
55: if len(request.QueryString("pagesize")) = 0 then
56: intPageSize = 10
57: else
58: intPageSize = CInt(request.QueryString("pagesize"))
59: end if
60:
61: if len(request.QueryString("order")) = 0 then
62: strOrderBy = "得意先コード"
63: else
64: strOrderBy = request.QueryString("order")
65: end if
行72-74で得意先テーブルからレコードを取得するSQLを作成するとき、ORDER BY句には、QueryStirngのorder=で指定されているフィールド名を使用します。
72: strSQL = "Select 得意先コード,得意先名,担当者名,電話番号" _
73: & " From 得意先" _
74: & " Order by " & strOrderBy & ";"
行135-141では、カレントページが1以上のときPrevのハイパーリンクを生成します。行139では、ServerオブジェクトのURLEncodeメソッドでstrOrderByをURLEncodeしています。strOrderByには、「得意先コード」または「フリガナ」が格納されています。漢字をQueryStringに指定するときは、URLEncodeした値を指定する必要があります。(Internet Explorerなどの最新のブラウザでは、自動的にURLEncodeしますが他のブラウザでは保障されません。)
<a href='RecordsetPaging2.asp?page=3&pagesize=10&order='>Prev</a>
135: if intPageCurrent > 1 then
136: echoNL "<a href='RecordsetPaging2.asp?page=" _
137: & intPageCurrent - 1 _