Dim arrNames()
intSize = 0
Set objGroup = GetObject("LDAP://CN=Accountants,OU=Finance,DC=fabrikam,DC=com")
For Each strUser in objGroup.Member
Set objUser = GetObject("LDAP://" & strUser)
ReDim Preserve arrNames(intSize)
arrNames(intSize) = objUser.CN
intSize = intSize + 1
Next
For i = (UBound(arrNames) - 1) to 0 Step -1
For j= 0 to i
If UCase(arrNames(j)) > UCase(arrNames(j+1)) Then
strHolder = arrNames(j+1)
arrNames(j+1) = arrNames(j)
arrNames(j) = strHolder
End If
Next
Next
For Each strName in arrNames
Wscript.Echo strName
Next
以建立名為 arrNames 的動態陣列開始 (如需詳細資訊,請參閱 Microsoft Windows 2000 指令碼指南 (英文) 的這個部份)。為什麼要這樣做呢?我們已經知道了 ADSI 沒有內建的排序機制;因此,我們無法排序傳回的資料。相反的,我們必須取得資料、暫時將資料儲存在陣列中,然後排序陣列。
下一步,我們會使用這行程式碼來繫結到虛擬 Active Directory 的 Accountants 群組:
Set objGroup = GetObject("LDAP://CN=Accountants,OU=Finance,DC=fabrikam,DC=com")
繫結到群組時,取得的其中一個屬性是 Member 屬性,這個屬性剛好保存了群組的成員清單。如果只是想要回應每個群組成員的辨別名稱,且不需要排序成員清單,就可以使用像下列的程式碼:
For Each objMember in objGroup.Member
Wscript.Echo objMember
Next
但我們不是要這個,對吧!第一,我們可能不需要像 CN=Ken Myer、OU=Finance、DC=fabrikam 及 DC=com 的辨別名稱。而是要單純的舊式一般名稱 (CNs),像 Ken Myer 這樣的名稱。因此,在 For-Each 迴圈中,我們繫結到每個使用者帳戶,就可更輕易取得每個使用者的 CN。我們使用這個程式碼來繫結到個別的使用者帳戶:
Set objUser = GetObject("LDAP://" & strUser)
第二,我們不想馬上回應使用者名稱;我們要將這些名稱儲存在陣列中,然後在螢幕中實際顯示前,先進行排序。這就是這個程式碼的功用;它會取得每個使用者的 CN, 然後在 arrNames 陣列內建立位置儲存 CN:
ReDim Preserve arrNames(intSize)
arrNames(intSize) = objUser.CN
intSize = intSize + 1
(好吧,我們知道,如果您不習慣使用陣列,這會比撰寫程式碼看起來更不知所云。如果需要相關解釋,請參閱 Microsoft Windows 2000 指令碼指南 (英文)。)
最後,arrNames 會包含 Accountants 群組中每個使用者的 CN。我們所要作的就是用反昇排序去排序陣列。我們無法在此專欄中解釋反昇排序的詳細資訊;我們會在「指令碼週 2」中作更進一步的解釋。現在,反昇排序會有條不紊地將集合中的每個項目與其他項目進行比較,慢慢準確地判斷字母順序。例如,假設陣列看起來像這樣:
Sam
Mary
Abigail
反昇排序會開始比較 Sam 及 Mary。因為照字母的順序,Mary 在 Sam 前面,所以反昇排序會將它們在陣列中的位置對調。陣列就會看起來像這樣:
Mary
Sam
Abigail
然後,排序會比較 Sam 及 Abigail,然後再次對調在陣列中的位置。現在陣列看起來像這樣:
Mary
Abigail
Sam
我們現在知道 Sam 是陣列中的最後一個項目。就是這樣沒錯;我們已經將 Sam 與其他每個項目進行比較了。因此,在這個簡單範例中,反昇排序已完成 Sam,所以只要比較 Mary 跟 Abigail 就好了。指令碼會進行兩者的比較、對調「它們」的位置,然後提供最後的排序清單:
Abigail
Mary
Sam
這只是基本的概念,坦白說,實際的程式碼看起來更複雜:
For i = (UBound(arrNames) - 1) to 0 Step -1
For j= 0 to i
If UCase(arrNames(j)) > UCase(arrNames(j+1)) Then
strHolder = arrNames(j+1)
arrNames(j+1) = arrNames(j)
arrNames(j) = strHolder
End If
Next
Next
如果您花時間去追蹤發生的事情,您會看見這個程式碼遵循了上述的程序;且看起來還不賴。唯一要注意的是,我們必須將每個名稱轉換成大寫 (使用 UCase 函數),才能進行比較。因為 VBScript 會使用每個字母的 ASCII 值來進行比較。在 ASCII 中,大寫字母一律會排在小寫字母前;因此 Zachary 會排在 anne 前面。將每個名稱轉換成大寫可確保 ANNE 排在 ZACHARY 前面。
最後,我們使用其他的 For-Each 迴圈循環 arrNames 陣列,並按字母的順序回應使用者名稱。
我們已經注意到,反昇排序不是唯一排序資料的方法,它有一些限制如下:最好是用在只有一個欄位 (如使用者名稱) 要處理的時候,且如果清單中有上百個項目,速度會很慢。如果反昇排序無法處理您的排序需求,您可以收聽「指令碼週 2」,或參閱《指令碼指南》中的中斷連接資料錄集中的簡短討論。 |