VBA中ArrayList查找Range对象索引报错原因及自定义类实现要求
关于VBA中ArrayList使用IndexOf的问题解答
1. 报错的原因是什么?
这事儿核心在于**.NET ArrayList的IndexOf默认用引用相等性判断对象**,而VBA里的Range对象有个特殊点:每次你写Range("a1"),VBA都会生成一个全新的Range对象实例——哪怕它们指向同一个单元格,这两个实例在内存里的引用是完全不同的。
你代码里先Add了Range("a1")(第一个实例),然后调用IndexOf时又传了Range("a1")(第二个新实例),ArrayList找不到第二个实例的引用,自然就抛出“值不在预期范围内”的错误了。
2. 自定义myClass类需实现什么才能让IndexOf生效?
如果想用自定义类让IndexOf正确匹配,你需要在类模块里实现Equals方法,重写默认的引用比较逻辑,改成基于你需要的属性值来判断相等。
举个例子,假设你的myClass有个ID属性,类模块代码可以这么写:
' 在myClass类模块中 Public ID As Integer Public Function Equals(ByVal other As Variant) As Boolean ' 先判断传入的对象是不是myClass类型 If Not TypeOf other Is myClass Then Equals = False Exit Function End If ' 基于ID属性判断相等 Equals = Me.ID = other.ID End Function
这样ArrayList的IndexOf就会调用这个Equals方法来比较对象,而不是只看引用是否相同。
3. 是否无法在ArrayList中查找对象?
当然不是!只是要注意正确的查找姿势:
- 如果是引用查找:你需要先把对象实例保存到变量里,Add和IndexOf都用同一个变量(也就是同一个引用)。比如修改你的测试代码:
Sub testFixed() Dim testList As Object Dim targetRng As Range Set testList = CreateObject("System.Collections.ArrayList") Set targetRng = Range("a1") ' 保存同一个实例 testList.Add targetRng Debug.Print testList.IndexOf(targetRng) ' 会返回0,正常找到索引 End Sub - 如果是值查找:对于自定义类就像上面说的实现Equals方法;对于内置类型(比如字符串、数字),ArrayList本身就能直接用IndexOf找到,因为它们的Equals方法已经是基于值比较的了。
内容的提问来源于stack exchange,提问作者Greedo
相关产品推荐
相关产品推荐

