複数のドロップダウンリストを連動させるには
Accessのデータベースの商品区分マスタと商品マスタをドロップダウンリストに表示させて連動させる方法を説明します。ここで紹介するサンプルでは、商品区分リストからアイテムを選択すると、商品リストには商品区分に該当するアイテムのみ表示されるように連動させています。
|
|
図 商品区分と商品のドロップダウンリストを連動させたサンプル
Access + Webのダウンロードにサンプルが収録されています。ダウンロードの目次を表示させたら、「商品区分と商品のドロップダウンリストを連動させる」をクリックしてください。Internet Explorerの左側のフレームには、ASPのソースが表示されます。右側のフレームには実行結果が表示されます。このサンプルは、NestedDropdown.aspとNestedDropdownInc.aspファイルから構成されています。ASPファイルのソースコードを解説する前にプログラムの概要を説明します。図に示すように、ドロップダウンリストを連動させるには、arrCascadeに親子のドロップダウンリストのエレメント名(selCategory, selProduct)と子のアイテムを定義した配列変数名(arrProduct)を格納しておきます。
項番①の商品マスタの配列は、Sub WriteClientArrayを呼んで生成します。②③のドロップダウンリストは、Sub SelectBoxを呼んで生成します。商品区分(selCategory)のドロップダウンリストからアイテムを選択すると④のonchangeイベントが発生してChangeOptions()関数を呼びます。ChangeOptions()では、arrCascadeに格納されている情報を基に商品区分マスタと商品マスタのドロップダウンリストを連動させます。具体的には、商品区分のドロップダウンリストで選択した商品アイテムのみ表示されるように商品のドロップダウンリストのアイテムを書き換えます。この処理は、クライアントのブラウザ側で処理するためにJavaScriptで記述しています。WriteClientArrayとSelectBoxは、サーバー側で実行されるのでVBScriptで記述しています。商品のドロップリストからアイテムを選択すると、⑤のonchangeイベントが発生してChangeOptions()が呼ばれます。商品のドロップダウンリストには、連動するドロップダウンリストがないので何もしないで戻ります。
|
|
図 ドロップダウンリストを連動させるプログラムの概要
● NestedDropdown.aspのソースコード説明
リストに、NestedDropdown.aspのソースコードが掲載されていますので、ここで参照する行番号と対応させてください。
行3では、include file=でNestedDropdownInc.aspファイルを指定しています。(Includeファイルのソースコードは、リスト に掲載されています。)このIncludeファイルには、VBScriptのサブプロシージャとJavaScriptの関数が記述されています。
3: <!-- #include file=NestedDropdownInc.asp -->
行8-11では、Accessのデータベースado.mdbを接続するための処理を行っています。行8-9では、OLEDBのProviderとData Sourceを設定してstrConnectionに保存しています。行10-11では、Connectionのインスタンスを生成してOpenメソッドでado.mdbを接続しています。
8: strConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" _
9: & "Data Source=" & server.MapPath("webdb/ado.mdb")
10: set cnn = server.CreateObject("adodb.connection")
11: cnn.Open strConnection
行13-14では、Server.CreateObjectで商品区分マスタと商品マスタのRecordsetのインスタンスを生成しています。
13: set rsCategory = server.CreateObject("adodb.recordset")
14: set rsProduct = server.CreateObject("adodb.recordset")
行18-21では、JavaScriptの配列変数arrCascadeに親子のドロップダウンリストのエレメント名と子のアイテムを定義した配列変数名を格納しています。ここで定義した配列変数は、NestedDropdownInc.aspに登録されているChangeOptions()関数で参照します。
18: <script language= "javascript">
19: var arrCascade = new Array();
20: arrCascade[0] = new Array ('selCategory', 'selProduct', 'arrProduct');
21: </script>
行29-33では、商品区分マスタを抽出するSQLを作成して、RecordsetオブジェクトのOpenメソッドでレコードセットを作成しています。行33では、先頭レコードの区分コードをintFirstIDに保存しています。
29: strSQL = "SELECT 区分コード, 区分名" _
30: & " FROM 商品区分" _
31: & " ORDER BY 区分コード;"
32: rsCategory.Open strSQL, cnn
33: intFirstID = rsCategory("区分コード")
行35-38では、商品マスタを抽出するSQLを作成して、RecordsetオブジェクトのOpenメソッドでレコードセットを作成しています。
35: strSQL = "SELECT 区分コード, 商品コード, 商品名, 梱包単位, 単価" _
36: & " FROM 商品" _
37: & " ORDER BY 区分コード, 商品コード;"
38: rsProduct.Open strSQL, cnn
行40-41では、Sub WriteClientArrayを呼び出して商品マスタの配列を生成しています。WriteClientArrayは、NestedDropdownInc.aspファイルに登録されています。
40: WriteClientArray "arrProduct", rsProduct, _
41: "区分コード","商品コード","商品名"
è<script language= "javascript">
èvar arrProduct = new Array();
èarrProduct[0] = new Array ('1', '1', '果汁100% オレンジ');
èarrProduct[1] = new Array ('1', '2', '果汁100% グレープ');
èarrProduct[2] = new Array ('1', '3', '果汁100% レモン');
è・・・
èarrProduct[122] = new Array ('8', '118', '特選さざえ');
è</script>
行47では、Sub SelectBoxを呼び出して商品区分マスタのドロップダウンリストを生成しています。SelectBoxは、NestedDropdownInc.aspファイルに登録されています。SelectBoxには、以下のような引数を指定します。
SelectBox(rsOption, strName, strValue, strDisplay)
rsOptionには、Recordsetのオブジェクトを指定します。strNameには、<select>タグのエレメント名を指定します。strValueには、<option>タグのvalue=に埋め込むレコードセットのフィールドを指定します。strDisplayには、<option></option>タグの間に埋め込むレコードセットのフィールドを指定します。
47: SelectBox rsCategory,"selCategory","区分コード","区分名"
è<select
name="selCategory" id="selCategory"
onChange="ChangeOptions('selCategory')">
è<option
value="1">飲料</option>
è・・・
è<option
value="8">魚介類</option>
è</select>
行52では、RecordsetオブジェクトのFilterメソッドで商品マスタのレコードを絞り込んでいます。intFirstIDには、商品区分マスタの先頭レコードの区分コードが格納されていますので「飲料」に該当する商品のみ選択されます。
52: rsProduct.Filter =
"区分コード=" & intFirstID
行53では、Sub SelectBoxを呼び出して商品マスタのドロップダウンリストを生成しています。SelectBoxは、NestedDropdownInc.aspファイルに登録されています。
53: SelectBox
rsProduct,"selProduct","商品コード","商品名"
è<select
name="selProduct" id="selProduct"
onChange="ChangeOptions('selProduct')">
è<option
value="1">果汁100% オレンジ</option>
è・・・
è<option
value="123">林檎果汁</option>
è</select>
行54では、RecordsetオブジェクトのFilterメソッドに0を設定して絞込みを解除しています。
54: rsProduct.Filter =
0
行58-60では、商品区分、商品マスタのレコードセットを閉じて、データベースを切断しています。
58: rsCategory.Close
59: rsProduct.Close
60: cnn.Close
行62-64では、Recordset、 Connectionオブジェクトを解放しています。
62: set rsCategory =
nothing
63: set rsProduct =
nothing
64: set cnn = nothing
● Sub SelectBoxの説明(NestedDropdownInc.aspのVBScript)
Sub SelectBoxは、HTMLの<select>・・・</select>タグを生成してレコードセットのドロップダウンリストを生成します。
|
SelectBox(rsOptions, strName, strValue, strDisplay) |
rsOptionsには、HTMLの<option>・・・</option>タグを生成するRecordsetのオブジェクトを指定します。strNameには、<select>タグのエレメント名を指定します。strValueには、<option>タグのvalue=に埋め込むレコードのフィールドを指定します。strDisplayには、<option>・・・</option>タグの間に埋め込むレコードのフィールドを指定します。
<select name=”strName” id=”strName” ・・・>
<option value=”rsOptions(strValue)”>rsOptions(strDisplay)</option>
行7では、変数Qにダブルクオテーション(“)を設定しています。
7: Q = chr(34)
行8-13では、HTMLの<select>タグを生成してブラウザに送信しています。行10-11では、<select>タグにonChangeイベントを挿入しています。onChangeイベントでは、JavaScriptのChangeOptions()関数を呼び出します。
8: strSelect = vbNewLine & "<select name=" & Q & strName & Q & _
9: " id=" & Q & strName & Q & _
10: " onChange=" & Q & "ChangeOptions('" & _
11: strName & "')" & Q & ">" & vbNewLine
12:
13: response.Write strSelect
è <select name=”strName” id=”strName”
onChange=”ChangOptions(“”strName””)”>
行14-22では、引数rsOptionsで指定したRecordsetオブジェクトを参照しています。
行15-19のdo until…loopでは、レコードセットのすべてのレコードを読み込んでHTMLの<option>・・・</option>タグを生成してブラウザに送信しています。<option>タグのvalue=には、引数strValueで指定したフィールド値を埋め込みます。<option>・・・</option>タグの間には、引数strDisplayで指定したフィールド値を埋め込みます。行18では、RecordsetオブジェクトのMoveNextメソッドで次のレコードに移動しています。カレントがレコードセットの最終レコードのとき、MoveNextメソッドを実行するとEOFが報告されてdo until…loopが終了します。行20では、RecordsetオブジェクトのMoveFirstメソッドでレコードセットの先頭レコードに移動しています。行21では、HTMLの</select>タグをブラウザに送信しています。
14: with rsOptions
15: do until .EOF
16: response.Write "<option value=" & Q & .Fields(strValue) & Q & ">"
17: response.Write trim(.Fields(strDisplay)) & "</option>" & vbNewLine
18: .MoveNext
19: loop
20: .MoveFirst
21: response.Write "</select>"
22: end with
● Sub WriteClientArrayの説明(NestedDropdownInc.aspのVBScript)
Sub WriteClientArrayでは、ドロップダウンリストに表示させるアイテムをJavaScriptの配列変数に定義します。ここで定義した配列変数は、HTMLの<select>タグのonchangeイベントでドロップダウンリストのアイテムを書き換えるときに使用します。
<script language= "javascript">
var arrProduct = new Array();
arrProduct[0] = new Array ('1', '1', '果汁100% オレンジ');
arrProduct[1] = new Array ('1', '2', '果汁100% グレープ');
arrProduct[2] = new Array ('1', '3', '果汁100% レモン');
・・・
arrProduct[122] = new Array ('8', '118', '特選さざえ');
</script>
|
WriteClientArray(strArrName, rsSource, strKey, strValue, strDisplay) |
strArrNameでは、配列変数名を指定します。rsSourceには、配列変数に格納するRecordsetのオブジェクトを指定します。(例:商品区分マスタと商品マスタのドロップダウンリストを連動させるときは、商品マスタのレコードセットを指定します。)strKeyには、rsSourceで指定したレコードセットのフィールドを指定します。(例:商品区分マスタと商品マスタのドロップダウンリストを連動させるときは、商品マスタの区分コードを指定します。)ここで指定したフィールドは、ドロップダウンリストを連動させるときに関連付けを行うために利用します。strValueには、rsSourceで指定したレコードセットのフィールドを指定します。ここで指定したフィールドは、<option>タグのvalue=の値として利用されます。(例:rsSourceが商品マスタのときは商品コードを指定します。)strDisplayには、rsSourceで指定したレコードセットのフィールドを指定します。ここで指定したフィールドは、<option>・・・</option>タグの間に挿入されてドロップダウンリストに表示されます。(例:rsSourceが商品マスタのときは商品名を指定します。)
行29では、HTMLの<script language=”javascript”>を生成しています。Response.Writeで”<script language=’javascript’>”のように記述すると「ネストしたScriptです」のエラーになりますので<script>タグを認識させないように分割して送信します。
29: response.Write "<sc" & "ript language= ""javascript"">" & vbNewLine
行30では、JavaScriptのvar strArrName = new Array();を生成しています。
30: response.Write "var " & strArrName & " = new Array(); " & vbNewLine
行33-45では、引数rsSourceで指定したRecordsetのオブジェクトを参照しています。行34-43のdo until …loopでは、引数rsSourceで指定したレコードセットの内容を二次元の配列変数に定義しています。行42では、RecordsetオブジェクトのMoveNextメソッドで次のレコードに移動しています。カレントが最終レコードのとき、MoveNextメソッドを実行するとEOFが報告されてdo until…loopが終了します。行44では、HTMLの</script>タグを生成しています。ASPのエラーを回避するために</script>タグを認識させないように分割して送信しています。
33: with rsSource
34: do until .EOF
35: response.Write strArrName & "[" & cstr(intRow) & _
36: "] = new Array ('" & _
37: replace(trim(.Fields(strKey)), "'", "\'") & _
38: "', '" & replace(trim(.Fields(strValue)), "'", "\'") & _
39: "', '" & replace(trim(.Fields(strDisplay)), "'", "\'") & _
40: "');" & vbNewLine
41: intRow = intRow + 1
42: .MoveNext
43: loop
44: response.Write "</sc" & "ript>"
45: end with
● Function ChangeOptions()の説明(NestedDropdownInc.aspのJavaScript)
ChangeOptons()関数は、複数のドロップダウンリストを連動(ネスト)させます。この関数は、HTMLの<select>タグのonchangeイベントから呼ばれます。この関数を使用するには、事前に以下のような配列変数を定義しておく必要があります。
<script language= "javascript">
var arrCascade = new Array();
arrCascade[0] = new Array ('selCategory', 'selProduct', 'arrProduct');
</script>
arrCascadeは、二次元の配列変数です。配列の要素1には、親のドロップダウンリストのエレメント名を格納します。エレメント名は、<select>タグのname=で指定します。要素2には、子のドロップダウンリストのエレメント名を格納します。要素3には、子のドロップダウンリストのアイテムデータを定義している二次元の配列変数名(arrProduct)を格納します。
var arrProduct = new Array();
arrProduct[0] = new Array ('1', '1', '果汁100% オレンジ');
arrProduct[1] = new Array ('1', '2', '果汁100% グレープ');
arrProduct[2] = new Array ('1', '3', '果汁100% レモン');
・・・
複数のドロップダウンリストをネストさせるときは、以下のような配列変数を定義します。なお、ドロップダウンリストは、親è子è孫è曾孫のようにネストさせることもできます。
var arrCascade = new Array();
arrCascade[0] = new Array ('selPrimary0', 'selSecondary0', 'arrOptions0');
arrCascade[1] = new Array ('selPrimary1', 'selSecondary1', 'arrOptions1');
arrCascade[2] = new Array ('selPrimary2', 'selSecondary2', 'arrOptions2');
この例の場合、selPrimary0 è selSecondary0、selPrimary1 è selSecondary1、selPrimary2 è selSecondary2がそれぞれ独立してネストします。
var arrCascade = new Array();
arrCascade[0] = new Array ('selParent', 'selChild', 'arrOpt0');
arrCascade[1] = new Array ('selChild', 'selGrandChild', 'arrOpt');
arrCascade[2] = new Array ('selGrandChild', 'selGreatGandChild', 'arrOpt2');
この例では、selParent è selChild è selGrandChild è selGreatGrandChildのようにネストします。
|
ChangeOptions(selPrimary) |
selPrimaryには、HTMLの<select>タグのエレメント名(name=で指定)を指定します。
<select name=”selCategory” onchange=”ChangeOptions(‘selCategory’)” >
行57-61では、引数selPrimaryで指定されたドロップダウンリストにアイテムが定義されているか調べています。アイテムは、<option>・・・</option>タグで定義します。アイテムが定義されているときは、ドロップダウンリストから選択したアイテムの値をstrKeyに保存します。たとえば、商品区分マスタのドロップダウンリストから「飲料」をクリックしたときは、区分コード”1”が保存されます。行57を解りやすく記述すると以下のようになります。
if ((document.forms[0].selCategory.options.length) > 0)
57: if (eval("document.forms[0]." + selPrimary + ".options.length") > 0) {
58: var strKey = eval("document.forms[0]."
59: + selPrimary + ".options[document.forms[0]."
60: + selPrimary + ".selectedIndex].value");
61: }
行63-83のforステートメントでは、配列変数arrCascadeの処理を行っています。行64では、arrCascadeの要素1に格納されているエレメント名(例:”selCategory”)と引数selPrimaryに指定されているエレメント名が一致するか調べています。一致するときは、行65-81を実行します。行65-66では、arrCascadeの要素2(例:”selProduct”)と要素3(例:”arrProduct”)から値を取得して変数selSecondaryとarrSourceに保存しています。たとえば、arrCascadeが以下のように定義されているときselSecondaryには”selProduct”、arrSourceには”arrProduct”が保存されます。
var arrCascade = new Array();
arrCascade[0] = new Array ('selCategory', 'selProduct', 'arrProduct');
行67では、selSecondaryに格納されているエレメント(例:”selProduct”)のアイテム(<option>・・・</option>で定義する)件数を0に初期化しています。行68では、strKeyの内容(例:商品区分コード”1”が格納されている)が0か調べています。0以外のときは、行69-79を実行します。行70-76のforステートメントでは、arrSourceに格納されている配列変数(例:”arrProduct”)のデータを基にドロップダウンリストのアイテムを追加しています。行71では、arrSource(例:”arrProduct”)に格納されている配列変数の要素1(例:区分コード)の値とstrKey(例:商品区分のドロップダウンリストで選択したアイテムの値)が一致するか調べています。一致するときは、行72-73を実行してドロップダウンリストのアイテムを追加します。行72-73を、解りやすく記述すると以下のようになります。
document.forms[0].selProduct.options[listLen] =
new Option(arrProduct[j][2], arrProduct[j][1])
arrProduct[j][2]には、商品名が格納されています。arrProduct[j][1]には、商品コードが格納されています。Optionオブジェクトには、引数としてアイテムリストに表示される名称と値を指定します。このステートメントは、HTMLの<option>・・・</option>タグでアイテムを定義することをJavaScriptで行っています。
行77-79では、ドロップダウンリストのアイテムが追加されたか調べて、追加されたときは先頭のアイテムをデフォルト表示させます。
行81では、ChangeOptions()関数を再帰的に呼び出しています。引数にselSecondary(例:”selProduct”)を指定しています。この場合、selSecondaryのドロップダウンリストが親となります。このように再帰的にこの関数を呼び出すことにより複数のドロップダウンリストがネストされます。
63: for (var i = 0; i < arrCascade.length; i++) {
64: if (arrCascade[i][0] == selPrimary) {
65: selSecondary = arrCascade[i][1];
66: arrSource = arrCascade[i][2];
67: eval("document.forms[0]." + selSecondary + ".options.length = 0");
68: if (strKey != 0){
69: listLen = 0;
70: for (var j = 0; j < eval(arrSource + ".length"); j++) {
71: if (eval(arrSource + "[j][0]") == strKey) {
72: eval("document.forms[0]." + selSecondary
73: + ".options[listLen] = new Option(" + arrSource + "[j][2], " +
arrSource + "[j][1])" );
74: listLen = listLen + 1;
75: }
76: }
77: if (listLen > 0) {
78: eval("document.forms[0]." + selSecondary +
".options[0].selected = true");
79: }
80: }
81: ChangeOptions(selSecondary);
82: }
83: }
リスト NestedDropdown.aspのソースコード
|
1: <%@ language=vbscript %> 2: <% option explicit %> 3: <!-- #include file=NestedDropdownInc.asp --> 4: <% 5: dim cnn, rsCategory, rsProduct 6: dim strConnection 7: 8: strConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" _ 9: & "Data Source=" & server.MapPath("webdb/ado.mdb") 10: set cnn = server.CreateObject("adodb.connection") 11: cnn.open strConnection 12: 13: set rsCategory = server.CreateObject("adodb.recordset") 14: set rsProduct = server.CreateObject("adodb.recordset") 15: %> 16: <html> 17: <head> 18: <script language= "javascript"> 19: var arrCascade = new Array(); 20: arrCascade[0] = new Array ('selCategory', 'selProduct', 'arrProduct'); 21: </script> 22: </head> 23: 24: <body> 25: <% 26: dim strSQL 27: dim intFirstID 28: 29: strSQL = "SELECT 区分コード, 区分名" _ 30: & " FROM 商品区分" _ 31: & " ORDER BY 区分コード;" 32: rsCategory.open strSQL, cnn 33: intFirstID = rsCategory("区分コード") 34: 35: strSQL = "SELECT 区分コード, 商品コード, 商品名, 梱包単位, 単価" _ 36: & " FROM 商品" _ 37: & " ORDER BY 区分コード, 商品コード;" 38: rsProduct.open strSQL, cnn 39: 40: WriteClientArray "arrProduct", rsProduct, _ 41: "区分コード","商品コード","商品名" 42: %> 43: <p>商品区分と商品のドロップダウンリストを連動させるサンプル</p> 44: <form id=form1 name=form1> 45: 商品区分リスト:<br> 46: <% 47: SelectBox rsCategory,"selCategory","区分コード","区分名" 48: %> 49: <br><br> 50: 商品リスト:<br> 51: <% 52: rsProduct.filter = "区分コード=" & intFirstID 53: SelectBox rsProduct,"selProduct","商品コード","商品名" 54: rsProduct.filter = 0 55: %> 56: </form> 57: <% 58: rsCategory.close 59: rsProduct.close 60: cnn.close 61: 62: set rsCategory = nothing 63: set rsProduct = nothing 64: set cnn = nothing 65: %> 66: </body> 67: </html> |
リスト NestedDropdownInc.aspのソースコード
|
1: <script runat="server"
language="vbscript">
2: '-----------------------------------------------------
3: sub SelectBox(rsOptions, strName, strValue, strDisplay)
4: dim Q
5: dim strSelect
6:
7: Q = chr(34)
8: strSelect =
vbNewLine & "<select name=" & Q & strName & Q & _
9: "
id=" & Q & strName
& Q & _ 10: " onChange=" & Q
& "ChangeOptions('" & _ 11: strName &
"')" & Q & ">" & vbNewLine 12: 13: response.write strSelect 14: with rsOptions 15: do until .eof 16:
response.write "<option value=" & Q &
.fields(strValue) & Q & ">" 17:
response.write trim(.fields(strDisplay)) &
"</option>" & vbNewLine 18: .MoveNext 19: loop 20: .MoveFirst 21: response.write
"</select>" 22: end with 23: end sub 24: 25: '
---------------------------------------------------------------------- 26: sub WriteClientArray(strArrName,
rsSource, strKey, strValue, strDisplay) 27: dim intRow 28: 29: response.write
"<sc" & "ript language=
""javascript"">" & vbNewLine 30: response.write "var "
& strArrName & " = new Array(); " & vbNewLine 31: 32: intRow = 0 33: with rsSource 34: do until .eof 35:
response.write strArrName & "[" & cstr(intRow) &
_ 36:
"] = new Array ('" & _ 37:
replace(trim(.fields(strKey)), "'", "\'") & _ 38:
"', '" & replace(trim(.fields(strValue)), "'",
"\'") & _ 39:
"', '" & replace(trim(.fields(strDisplay)),
"'", "\'")
& _ 40:
"');" & vbNewLine 41: intRow =
intRow + 1 42:
.MoveNext 43: loop 44: response.write
"</sc" & "ript>" 45: end with 46: end sub 47: </script> 48: 49: <script
language="javascript"> 50: // -------------------------------- 51: function ChangeOptions(selPrimary){
52: var listLen = 0; 53: var strKey = 0; 54: var selSecondary = 0; 55: var arrSource = 0; 56: 57: if
(eval("document.forms[0]." + selPrimary +
".options.length") > 0) { 58: var strKey =
eval("document.forms[0]." 59: +
selPrimary + ".options[document.forms[0]." 60: +
selPrimary + ".selectedIndex].value"); 61: } 62: 63: for (var i = 0; i <
arrCascade.length; i++) { 64: if (arrCascade[i][0]
== selPrimary) { 65:
selSecondary = arrCascade[i][1]; 66:
arrSource =
arrCascade[i][2]; 67:
eval("document.forms[0]." + selSecondary +
".options.length = 0"); 68: if
(strKey != 0){ 69:
listLen = 0; 70: for (var j = 0; j
< eval(arrSource + ".length"); j++) { 71:
if (eval(arrSource + "[j][0]") == strKey) { 72:
eval("document.forms[0]." + selSecondary 73:
+ ".options[listLen] = new Option(" + arrSource +
"[j][2], " + arrSource + "[j][1])" ); 74:
listLen = listLen + 1; 75:
} 76:
} 77:
if (listLen > 0) { 78:
eval("document.forms[0]." + selSecondary +
".options[0].selected = true"); 79:
} 80: } 81:
ChangeOptions(selSecondary); //
Recursive call 82: } 83: } 84: } 85: </script> |