VBA自定义类报错:Object doesn't support this property or method 求助
问题排查与修复:VBA自定义集合类Add方法报错
我来帮你梳理下代码里的问题,你遇到的“Object doesn't support this property or method”错误主要来自两个关键问题,咱们一步步解决:
1. 错误根源:Add方法调用时的括号导致对象引用丢失
在VBA中,调用Sub过程时如果给参数加括号,会强制将对象转换为它的默认属性值(而不是传递对象本身)。你的cRange类第一个定义的Property Get是Low,所以rs.Add (r)实际上是把r.Low的字符串值传给了Add方法,而不是cRange对象。
这就导致你的m_Ranges集合里存的不是cRange对象,而是字符串。第二次调用rs.Add (r)时,Add方法期望接收cRange类型的参数,但你传的是字符串,类型不匹配,直接触发了报错。同时后面的Contains方法遍历集合时,元素是字符串而非cRange对象,也会因为没有Contains方法而失败。
2. 次要问题:复用同一个cRange对象导致数据被覆盖
VBA的对象是引用类型,你在主程序里复用了同一个r变量,第一次Add后修改r.Low和r.High,会直接修改集合里已经存在的那个对象的属性(因为它们指向同一块内存地址),最终集合里两个元素都会变成21-30,这显然不是你想要的结果。
修改后的完整代码
主程序(main)
Sub main() Dim r As cRange Dim rs As New cRanges ' 创建第一个范围对象并添加到集合 Set r = New cRange r.Low = "1" r.High = "10" rs.Add r ' 去掉括号,传递对象引用 ' 创建第二个全新的范围对象并添加到集合 Set r = New cRange r.Low = "21" r.High = "30" rs.Add r ' 去掉括号 Debug.Print rs.Contains("5") ' 输出 True Debug.Print rs.Contains("15") ' 输出 False Debug.Print rs.Contains("25") ' 输出 True End Sub
cRanges类模块
' CLASS MODULE - cRanges ' Member variables Private m_Ranges As New Collection ' Methods Public Sub Add(r As cRange) m_Ranges.Add r ' 去掉括号,确保添加的是对象引用 End Sub Public Sub Remove(r As cRange) ' VBA集合的Remove方法不支持直接传对象,需遍历找到索引再删除 Dim idx As Integer idx = 1 For Each item In m_Ranges If item Is r Then m_Ranges.Remove idx Exit Sub End If idx = idx + 1 Next End Sub Public Function Contains(s As String) As Boolean Dim r As cRange ' 明确声明变量类型,避免变体类型的潜在问题 For Each r In m_Ranges If r.Contains(s) Then Contains = True Exit Function End If Next Contains = False End Function
cRange类模块(无需修改,保持原样即可)
' CLASS MODULE - cRange ' Member variables Private m_Low As String Private m_High As String ' Properties Property Get Low() As String Low = m_Low End Property Property Get High() As String High = m_High End Property Property Let Low(s As String) m_Low = s End Property Property Let High(s As String) m_High = s End Property ' Methods Public Function Contains(s As String) As Boolean If Val(s) >= Val(m_Low) And Val(s) <= Val(m_High) Then Contains = True Else Contains = False End If End Function
额外说明
- 调用Sub方法时,除非需要强制求值(比如传递表达式的结果),否则不要给单个对象参数加括号;如果是Function方法需要接收返回值,才需要加括号。
- 对于VBA集合的Remove方法,记住它只接受**索引(整数)或键(字符串)**作为参数,无法直接删除对象,必须通过遍历找到对应位置。
内容的提问来源于stack exchange,提问作者Helloguys




