VBScript按对象属性排序字典报错:对象不支持该属性或方法
解决旧版VBScript中Scripting.Dictionary按ID排序的问题
首先,咱们来拆解你遇到的问题:你的报错和排序逻辑的核心问题在于旧版Scripting.Dictionary的特性限制,以及对Dictionary无序性的误解。
为什么原来的代码会报错?
- 对象不能直接比较:你的排序函数里用
dict.Item(i) <= dict.Item(j)直接比较两个TestClass实例,VBScript根本不知道怎么比较对象,这是导致错误的关键原因之一——你应该比较对象的ID属性,而不是对象本身。 - Dictionary的无序性:Scripting.Dictionary本质是哈希表,旧版里完全不保证遍历顺序,就算你交换了两个Item的值,遍历的时候顺序还是由哈希表的内部逻辑决定,不会按照你想要的排序结果来。
- 旧版遍历/索引的兼容性问题:早期VBScript版本对
For Each i In dict的支持可能有问题,而且dict.Items()(1)这种直接索引访问Items集合的方式,在旧版里也可能不被支持,需要先把Items赋值给数组变量再访问。
修正后的解决方案
既然旧版VBScript限制多,咱们换个思路:先把Dictionary里的对象提取到数组中排序,再按需放回新的Dictionary或者直接用数组——数组是有序的,能保证排序后的顺序。
1. 排序函数(返回排序后的Dictionary)
这个函数先把对象提取到数组,按ID冒泡排序,再重新存入新的Dictionary:
Function SortDictByID(ByVal dict) ' 第一步:把字典中的对象转存到数组 Dim objArr() Dim idx: idx = 0 Dim key ' 遍历字典的键(旧版VBScript遍历字典的标准方式) For Each key In dict ReDim Preserve objArr(idx) Set objArr(idx) = dict(key) idx = idx + 1 Next ' 第二步:冒泡排序数组,按ID升序排列 Dim i, j, tempObj For i = 0 To UBound(objArr) - 1 For j = i + 1 To UBound(objArr) ' 比较对象的ID属性,而不是对象本身 If objArr(i).ID > objArr(j).ID Then Set tempObj = objArr(i) Set objArr(i) = objArr(j) Set objArr(j) = tempObj End If Next Next ' 第三步:把排序后的对象存入新字典(保留原ID作为键) Dim newDict Set newDict = CreateObject("Scripting.Dictionary") For i = 0 To UBound(objArr) newDict.Add objArr(i).ID, objArr(i) Next Set SortDictByID = newDict End Function
2. 调用代码(兼容旧版VBScript)
注意旧版里不要直接用dict.Items()(1),改用遍历键或者数组索引:
Set gDic = CreateObject("Scripting.Dictionary") For i = 1 to 5 Set temp = New TestClass temp.ID = i temp.TestText = "Test" & i gDic.Add i, temp Next Set NewDic = SortDictByID(gDic) ' 方式1:遍历新字典的键访问(旧版最可靠的方式) Dim key For Each key In NewDic MsgBox NewDic(key).TestText ' 如果要取第二个元素,可以加判断或者用数组方式 Next ' 方式2:如果直接用数组更方便,用下面的函数 Function SortDictToArrByID(ByVal dict) Dim objArr() Dim idx: idx = 0 Dim key For Each key In dict ReDim Preserve objArr(idx) Set objArr(idx) = dict(key) idx = idx + 1 Next Dim i, j, tempObj For i = 0 To UBound(objArr) - 1 For j = i + 1 To UBound(objArr) If objArr(i).ID > objArr(j).ID Then Set tempObj = objArr(i) Set objArr(i) = objArr(j) Set objArr(j) = tempObj End If Next Next SortDictToArrByID = objArr End Function ' 调用数组版函数,直接按索引访问 Dim sortedArr sortedArr = SortDictToArrByID(gDic) MsgBox sortedArr(1).TestText ' 数组索引从0开始,这里取第二个元素,显示Test2
关键注意事项
- 永远不要直接比较VBScript对象,一定要比较对象的具体属性(比如这里的
ID)。 - 旧版Scripting.Dictionary是无序的,不要指望通过修改Item来改变遍历顺序,必须借助数组来实现有序排列。
- 遍历字典时,优先用
For Each key In dict的方式,再通过dict(key)访问值,这是旧版VBScript最兼容的写法。
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

