下拉  最近經常被詢問的問題就是如何建立動態下拉式選單 (二階層),一個月之內被問了不下十次,其實單純要做到動態下拉式選單 (二階層) 並不困難,但是要和資料庫結合,把資料庫的資料以動態下拉式選單來建立就必須要加上一點技巧了,今天筆者也不打算做二階層的動態下拉式選單,乾脆直接挑戰三階層,再把資料庫一起結合,讓大家了解的透徹一點。
  首先先讓我們看看靜態下拉式選單(三階層) 的原始程式,等你看懂了之後咱們再利用 ASP 和 SQL 來產生動態下拉式選單 (三階層):
  動態下拉式選單 (三階層):
  表單名稱為 myForm 
  第一個下拉式選單名稱為 color
  顏色:
  紅色">紅色
  黃色">黃色
  綠色">綠色 
  第二個下拉式選單名稱為 fruit
  水果:
  蘋果
  蓮霧
  李子
  第三個下拉式選單名稱為 price
  價格:
  10元
  20元
  30元
  定義顏色下拉式選單為一個一維陣列,且陣列長度為三(表示有三種顏色)
  key=new Array(3);
  //定義顏色下拉式選單中第一個顏色選項為一個一維陣列,且陣列長度為三(表示有三種水果),以下依此類推
  key[0]=new Array(3);
  key[1]=new Array(2);
  key[2]=new Array(3);
  //這邊重複定義一個陣列是為了在指定水果下拉式選項中之水果名稱時已經把水果名稱
  //指定給相關的陣列索引,這些陣列索引無法被重複定義成陣列,為了要讓價格下拉式選
  //單能沿用之前所定義的陣列值,所以我們在此處另外再定義一個一模一樣的陣列索引。 
  key1=new Array(3);
  key1[0]=new Array(3);
  key1[1]=new Array(2);
  key1[2]=new Array(3);
  //定義水果下拉式選單中第一個水果選項為一個一維陣列,且陣列長度為三(表示有三種
  //價格),此水果是屬於顏色下拉式選單中之第一種顏色,以下依此類推 
  key1[0][0]=new Array(3);
  key1[0][1]=new Array(3);
  key1[0][2]=new Array(3);
  //定義水果下拉式選單中第一個水果選項為一個一維陣列,且陣列長度為三(表示有三種
  //價格),此水果是屬於顏色下拉式選單中之第二種顏色,以下依此類推
  key1[1][0]=new Array(3);
  key1[1][1]=new Array(3);
  //定義水果下拉式選單中第一個水果選項為一個一維陣列,且陣列長度為三(表示有三種
  //價格),此水果是屬於顏色下拉式選單中之第三種顏色,以下依此類推
  key1[2][0]=new Array(3);
  key1[2][1]=new Array(3);
  key1[2][2]=new Array(3);
  //指定水果下拉式選項中之水果名稱 
  //紅色
  key[0][0]="蘋果";
  key[0][1]="蓮霧";
  key[0][2]="李子";
  //黃色
  key[1][0]="柳丁";
  key[1][1]="葡萄柚";
  //綠色
  key[2][0]="芭樂";
  key[2][1]="西瓜";
  key[2][2]="棗子";
  //指定價格下拉式選單中各個水果的價格 
  //蘋果
  key1[0][0][0]="10元"
  key1[0][0][1]="20元"
  key1[0][0][2]="30元"
  //蓮霧
  key1[0][1][0]="40元"
  key1[0][1][1]="50元"
  key1[0][1][2]="60元"
  //李子
  key1[0][2][0]="70元"
  key1[0][2][1]="80元"
  key1[0][2][2]="90元"
  //柳丁
  key1[1][0][0]="100元"
  key1[1][0][1]="110元"
  key1[1][0][2]="120元"
  //葡萄柚
  key1[1][1][0]="130元"
  key1[1][1][1]="140元"
  key1[1][1][2]="150元"
  //芭樂
  key1[2][0][0]="160元"
  key1[2][0][1]="170元"
  key1[2][0][2]="180元"
  //西瓜
  key1[2][1][0]="190元"
  key1[2][1][1]="200元"
  key1[2][1][2]="210元"
  //棗子
  key1[2][2][0]="220元"
  key1[2][2][1]="230元"
  key1[2][2][2]="240元"
  //改變顏色下拉式選單之選項值時,會觸動 Buildkey 函數,並將顏色下拉式選單中之選
  //項索引值傳給 num 變數,以本範例而言,紅色會傳來 0 的索引值,黃色會傳來 1 的索引
  //值,綠色會傳來 2 的索引值
  
  function Buildkey(num)
  {
  //將水果下拉式選單之指標索引指定為0。
  document.myForm.fruit.selectedIndex=0;
  //由於改變水果下拉式選單時,價格下拉式選單也必須跟著變動,所以我們在此順便呼
  //叫 Buildkey1函數,並強迫價格下拉式選單中之選項索引值為 0 ,表示不管目前是何種
  //顏色的水果,價格下拉式選單都會呈現此水果的第一種價格
  
  Buildkey1(0);
  //這邊是最關鍵的步驟,在 JavaScript 中,for(ctr=0;ctr//[color=#0000ff]就等於 VBScript 中的 For ctr = 0 to key[num].length,若有不懂的地方建議大
  //家買一本 JavaScript 的書來看,舉個範例來說明底下的程式大家會比較清楚,當我們
  //選了紅色之後,此時 num=0 (前面已經說過了),此時 key[0]的陣列長度我們可以透過
  //先前定義得知, key[0].length=3,而水果下拉式選單將開始改變,水果下拉式選單中
  //第一個選項將變成key[0][0],也就是蘋果,水果下拉式選單中第二個選項將變成key
  //[0][1],也就是蓮霧,水果下拉式選單中第三個選項將變成key[0][2],也就是李子,這樣
  //大家該了解了吧!!
  
  for(ctr=0;ctr將key[0].length指定為目前水果下拉式選單之索引陣列長度。
  document.myForm.fruit.length=key[num].length;
  }
  function Buildkey1(num)
  {
  //將價格下拉式選單之指標索引指定為0。
  document.myForm.price.selectedIndex=0;
  //改變價格下拉式選單的選項除了跟水果下拉式選單相關之外,還跟目前所選顏色有關
  //個範例來說明底下的程式大家會比較清楚,當我們選了紅色之後,此時 
  //document.myForm.color.selectedIndex=0 (因為紅色是顏色下拉式選單中之第
  //一個指標索引值),如果我們在水果下拉式選單中選的水果是蓮霧,此時 num=1 ,而 
  //key1[document.myForm.color.selectedIndex][num].length 此時變成 key1
  //[0][1].length,從之前的定義可以知道這個值是3,而價格下拉式選單將開始改變,價格//下拉式選單中第一個選項將變成key[0][1][0],也就是40 元,價格下拉式選單中第二
  //個選項將變成key[0][1][1],也就是50 元,水果下拉式選單中第三個選項將變成key
  //[0][1][2],也就是60 元,這樣大家該了解了吧!! 
  for(ctr=0;ctr由顏色下拉式選單索引取得水果陣列值;
  document.myForm.cost.options[ctr]=new Option(key1[document.myForm.color.selectedIndex][num][ctr],key1[document.myForm.color.selectedIndex][num][ctr]);
  }
  }
  //-->
  上面的程式希望大家用帶值進去的方式來學習,我想會比較好學習,若有任何看不懂的地方可以直接留言告訴我,接下來我們開始利用 ASP 與 SQL 來動態產生上面那段程式,希望大家不要因為上面的程式看不太懂而退縮,因為底下的程式將更為複雜,如果大家能將整個流程吸收,我相信不管是動態下拉式選單 (四階層)或動態下拉式選單 (五階層)都將難不倒你了,之所以會用上面的方式來動態建立下拉式選單是因為筆者覺得這個範例雖然比較麻煩,但是卻是比較容易理解的,另外兩種方式筆者覺得可能寫出來之後會不好解釋所以作罷!! 
在進入實作之前,先讓我們建立三個資料表,一個是 color 資料表,一個是 fruit 資料表,一個是 price 資料表,資料表架構如下:
三個資料表內容分別如下所示: 
   
  
  大家可以看的到 fruit 資料表是以 COLORID 欄位與 color 資料表形成關聯,而 price 資料表又以 FRUITID 欄位與 fruit 資料表形成關聯,我們想要讓資料是以下面的方式來呈現該如何做呢?
紅色→蘋果→10元
紅色→蘋果→20元
紅色→蘋果→30元
紅色→蓮霧→40元
紅色→蓮霧→50元
紅色→蓮霧→60元
紅色→李子→70元
紅色→李子→80元
紅色→李子→90元
黃色→柳丁→100元
黃色→柳丁→110元
黃色→柳丁→120元
黃色→葡萄柚→130元
黃色→葡萄柚→140元
黃色→葡萄柚→150元
綠色→芭樂→160元
綠色→芭樂→170元
綠色→芭樂→180元
綠色→西瓜→190元
綠色→西瓜→200元
綠色→西瓜→210元
綠色→棗子→220元
綠色→棗子→230元
綠色→棗子→240元
  我們用 JOIN 的方式來將三個資料表關聯起來, JOIN 的規則是把 fruit 資料表中 COLORID 欄位值等於 color 資料表中 ID 欄位的資料且 price 資料表中 FRUITID 欄位值等於 fruit 資料表中 ID 欄位的資料 JOIN 起來。
<%
myDSN="Provider=SQLOLEDB; Data Source=Jackal; Initial Catalog=pubs; User ID=sa; Password="
strSQL="select color.color, fruit.fruit, price.cost from color join fruit on color.ID=fruit.COLORID join price on price.FRUITID=fruit.ID order by color.ID"
Set my_conn = Server.CreateObject("ADODB.Connection")
my_conn.open myDSN
set rs=my_conn.execute(strSQL)
DO UNTIL rs.eof
Response.Write rs(0) & "→" & rs(1) & "→" & rs(2) & "
"
rs.movenext
LOOP
rs.close
set rs=nothing
my_conn.close
set my_conn=nothing
%>

  就上面的資料架構而言我們可以很清楚了看到,紅色→蘋果→10元相當於是 key1[0][0][0] 這個陣列索引的值,而綠色→棗子→240元就相當於是 key1[2][2][2] 這個陣列索引的值,而紅色→蘋果也相當於是 key[0][0] 這個陣列索引的值,請注意一個是 key ,一個是 key1,也就是我們在文章一開始告訴你為何要定義兩個陣列值的原因, OK ,看了資料的架構之後最麻煩的事情來了,要如何把這樣的資料架構轉成陣列,而且還要和資料庫作結合呢?底下這一段程式可能有點複雜,不過我會盡量解釋清楚: 
  DynamicSelectBox.asp
  
  ByRef。請直接觀看底下副程式的部分
  myDSN="Provider=SQLOLEDB; Data Source=Jackal; Initial Catalog=pubs; User ID=sa; Password="
  strSQL="select color.color, fruit.fruit, price.cost from color join fruit on color.ID=fruit.COLORID join price on price.FRUITID=fruit.ID order by color.ID"
  call listmaker(myDSN, strSQL, colorlist,"color", fruitlist ,"fruit", pricelist, "price", pubevent, pubfun, "myForm")
  %>
  顏色:
  水果:
  價格:
  -->
  "
  '利用 fruitlist 字串變數來建立第二個下拉式選單的 Html 原始碼。
  fruitlist="" 
  '利用 pricelist 字串變數來建立第三個下拉式選單的 Html 原始碼。
  pricelist=""
  '在這裡初始某些變數值,當作底下執行運算時之旗標值。
  loopcounter=0
  lastvalue=rs(0)
  lastvalue2=rs(1)
  redim tempArray(1)
  'thisgroupcount 代表某種顏色共有幾種水果
  thisgroupcount=0
  'thissubgroupcount 代表某種水果共有幾種價格,當水果變換時 thissubgroupcount 會歸零,並重新
  '累加。
  thissubgroupcount=0
  'howmanygroups 代表共有幾種顏色
  howmanygroups=0
  'howmanysubgroups 代表共有幾種水果,當顏色變換時 howmanysubgroups 會歸零,並重新
  '累加。
  howmanysubgroups=0
  DO UNTIL rs.eof
  thisvalue=rs(0)
  thisvalue2=rs(1)
  thisvalue3=rs(2)
  
  '如果發現水果名稱改變,而且目前水果是某種顏色的第一種水果時,譬如:紅色→蘋果 
  '或:黃色→柳丁時就在 Script 中加上顏色標記 (為了讓大家更容易將 Script 區隔開
  '來),然後再將水果名稱定義到 key 陣列值,
  '接著再定義 key1[第幾種顏色][第幾種水果] 之陣列長度。
  
  if thisvalue2lastvalue2 then 
  If howmanysubgroups=0 then
  tempSTR1=tempSTR1 & "// " & lastvalue & vbcrlf
  tempSTR2=tempSTR2 & "// " & lastvalue & vbcrlf
  end If
  tempSTR2=tempSTR2 & "key1[" & howmanygroups & "][" & howmanysubgroups & 
  "]=new Array(" & thissubgroupcount & ");" & vbcrlf
  tempSTR1=tempSTR1 & "key[" & howmanygroups & "][" & howmanysubgroups & 
  "]=""" & lastvalue2 & """;" & vbCRLF
  howmanysubgroups=howmanysubgroups+1
  thissubgroupcount=0
  lastvalue2=thisvalue2
  end if
  '執行結果如下
  // 紅色
  key[0][0]="蘋果";
  key[0][1]="蓮霧";
  key[0][2]="李子";
  // 黃色
  key[1][0]="柳丁";
  key[1][1]="葡萄柚";
  // 綠色
  key[2][0]="芭樂";
  key[2][1]="西瓜";
  key[2][2]="棗子";
  // 紅色
  key1[0][0]=new Array(3);
  key1[0][1]=new Array(3);
  key1[0][2]=new Array(3);
  // 黃色
  key1[1][0]=new Array(3);
  key1[1][1]=new Array(3);
  // 綠色
  key1[2][0]=new Array(3);
  key1[2][1]=new Array(3);
  key1[2][2]=new Array(3);
  '如果發現顏色名稱改變,就定義 key[第幾種顏色] 陣列值,
  '接著再定義 key1[第幾種顏色] 之陣列長度,重複定義的原因在之前已跟大家說過了,然
  '後將howmanygroups (顏色種類) 值加一,並將水果種類計數值 (thisgroupcount) 歸零
  if thisvaluelastvalue then
  tempSTR=tempSTR & "key[" & howmanygroups & "]=new Array(" & howmanysubgroups & ");" & _
  vbcrlf 
  tempSTR=tempSTR & "key1[" & howmanygroups & "]=new Array(" & howmanysubgroups & ");" & _
  vbcrlf 
  thisgroupcount=0
  howmanygroups=howmanygroups+1
  howmanysubgroups=0
  end if
  '執行結果如下
  key=new Array(3);
  key1=new Array(3);
  key[0]=new Array(3);
  key1[0]=new Array(3);
  key[1]=new Array(2);
  key1[1]=new Array(2);
  key[2]=new Array(3);
  key1[2]=new Array(3)
  '如果 thisgroupcount=0 代表目前顏色改變,此時將顏色名稱寫到 color 下拉式選單中
  if thisgroupcount=0 then
  colorlist =colorlist & "" & thisvalue & "" & vbcrlf
  end if
  '如果 thissubgroupcount=0 代表目前水果改變,此時在key1[第幾種顏色][第幾種水果][第幾
  '種價格] 陣列值前加上水果名稱標記,讓大家更容易將水果名稱與價格區隔開來。
  if thissubgroupcount=0 then
  tempSTR3=tempSTR3 & "// " & lastvalue2 & vbcrlf
  end if
  '定義key1[第幾種顏色][第幾種水果][第幾種價格] 陣列值。
  tempSTR3=TempSTR3 & "key1[" & howmanygroups & "][" & howmanysubgroups & "][" & thissubgroupcount & "]=""" & thisvalue3 & """;" & vbCRLF 
  '執行結果:
  // 頻果
  key1[0][0][0]="10元";
  key1[0][0][1]="20元";
  key1[0][0][2]="30元";
  // 蓮霧
  key1[0][1][0]="40元";
  key1[0][1][1]="50元";
  key1[0][1][2]="60元";
  // 李子
  key1[0][2][0]="70元";
  key1[0][2][1]="80元";
  key1[0][2][2]="90元";
  // 柳丁
  key1[1][0][0]="100元";
  key1[1][0][1]="110元";
  key1[1][0][2]="120元";
  // 葡萄柚
  key1[1][1][0]="130元";
  key1[1][1][1]="140元";
  key1[1][1][2]="150元";
  // 芭樂
  key1[2][0][0]="160元";
  key1[2][0][1]="170元";
  key1[2][0][2]="180元";
  // 西瓜
  key1[2][1][0]="190元";
  key1[2][1][1]="200元";
  key1[2][1][2]="210元";
  // 棗子
  key1[2][2][0]="220元";
  key1[2][2][1]="230元";
  key1[2][2][2]="240元";
  '如果目前是第一種顏色,而且水果名稱正在改變,就將水果名稱寫到 fruit 下拉式選單中 
  if howmanygroups=0 then
  If thissubgroupcount=0 then
  fruitlist = fruitlist & "" & thisvalue2 & "" & vbcrlf
  end if
  End If
  '如果目前是第一種顏色,而且是第一種水果,就將價格寫到 price 下拉式選單。
  if howmanygroups=0 then
  if howmanysubgroups=0 then
  pricelist = pricelist & "" & thisvalue3 & "" & vbcrlf
  end if
  End if
  thisgroupcount=thisgroupcount+1
  thissubgroupcount=thissubgroupcount+1
  lastvalue=thisvalue
  loopcounter=loopcounter+1
  rs.movenext
  LOOP
  '別忘了最後一個 key[第幾種顏色] 和 key1[第幾種顏色] 的陣列長度還未定義。
  tempSTR=tempSTR & "key[" & howmanygroups & _
  "]=new Array(" & howmanysubgroups+1 & ");" & _
  vbcrlf 
  tempSTR=tempSTR & "key1[" & howmanygroups & _
  "]=new Array(" & howmanysubgroups+1 & ");" & _
  vbcrlf 
  '別忘了最後一個 key[第幾種顏色][第幾種水果] 和 key1[第幾種顏色][第幾種水果] 的陣列長
  '度還未定義。
  tempSTR2=TempSTR2 &"key1[" & howmanygroups & "][" & howmanysubgroups & "]=new Array(" & thissubgroupcount & ");" & _
  vbcrlf 
  tempSTR1= TempSTR1 & "key[" & howmanygroups & "][" & howmanysubgroups & "]=""" & lastvalue2 & """;" & vbCRLF 
  tempSTR=tempSTR & TempSTR1 & TempSTR2 & tempSTR3
  '將 color 下拉式選單作一個結尾
  colorlist=colorlist & ""
  '將 fruit 下拉式選單作一個結尾
  fruitlist= fruitlist & ""
  '將 price 下拉式選單作一個結尾
  pricelist= pricelist & ""
  '一開始的 key 和 key1 陣列也不要忘記定義了。
  
  myevent=vbcrlf & "key=new Array(" & howmanygroups+1 & ");"
  myevent=myevent & vbcrlf & "key1=new Array(" & howmanygroups+1
  myevent=myevent & ");" & vbcrlf & tempSTR
  '大功告成,可以關閉資料庫了。
  rs.close
  set rs=nothing
  my_conn.close
  set my_conn=nothing
  '先產生 Buildkey 副程式,這邊一點都不困難,原理在上面已經解釋過了,筆者不再贅述,執行結果為:
  function Buildkey(num)
  {
  Buildkey1(0);
  document.myForm.fruit.selectedIndex=0;
  for(ctr=0;ctr
  tempSTR =vbcrlf & "function Buildkey" & "(num)" & vbcrlf 
  tempSTR =tempSTR & "{" & vbcrlf
  tempSTR =tempSTR & "Buildkey1(0);" & vbcrlf
  tempSTR =tempSTR & "document." & myForm & "." 
  tempSTR =tempSTR & listname2 & ".selectedIndex=0;" & vbcrlf
  tempSTR =tempSTR & "for(ctr=0;ctr
  再讓大家看看最後的結果:
  顏色:
  紅色
  黃色
  綠色
  水果:
  頻果
  蓮霧
  李子
  價格:
  10元
  20元
  30元
  送出">
  紅色
  key[0][0]="蘋果";
  key[0][1]="蓮霧";
  key[0][2]="李子";
  // 黃色
  key[1][0]="柳丁";
  key[1][1]="葡萄柚";
  // 綠色
  key[2][0]="芭樂";
  key[2][1]="西瓜";
  key[2][2]="棗子";
  // 紅色
  key1[0][0]=new Array(3);
  key1[0][1]=new Array(3);
  key1[0][2]=new Array(3);
  // 黃色
  key1[1][0]=new Array(3);
  key1[1][1]=new Array(3);
  // 綠色
  key1[2][0]=new Array(3);
  key1[2][1]=new Array(3);
  key1[2][2]=new Array(3);
  // 頻果
  key1[0][0][0]="10元";
  key1[0][0][1]="20元";
  key1[0][0][2]="30元";
  // 蓮霧
  key1[0][1][0]="40元";
  key1[0][1][1]="50元";
  key1[0][1][2]="60元";
  // 李子
  key1[0][2][0]="70元";
  key1[0][2][1]="80元";
  key1[0][2][2]="90元";
  // 柳丁
  key1[1][0][0]="100元";
  key1[1][0][1]="110元";
  key1[1][0][2]="120元";
  // 葡萄柚
  key1[1][1][0]="130元";
  key1[1][1][1]="140元";
  key1[1][1][2]="150元";
  // 芭樂
  key1[2][0][0]="160元";
  key1[2][0][1]="170元";
  key1[2][0][2]="180元";
  // 西瓜
  key1[2][1][0]="190元";
  key1[2][1][1]="200元";
  key1[2][1][2]="210元";
  // 棗子
  key1[2][2][0]="220元";
  key1[2][2][1]="230元";
  key1[2][2][2]="240元";
  function Buildkey(num)
  {
  Buildkey1(0);
  document.myForm.fruit.selectedIndex=0;
  for(ctr=0;ctr
其實這個程式說難不難,重點還是在陣列索引的觀念,同樣的有問題可以在討論區直接提出,希望大家看了這篇文章之後,不要再問我動態下拉式選單 (二階層)該如何做了!!祝大家身體健康, Coding 快樂。
 
  
 
 
  
