You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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 GetLow,所以rs.Add (r)实际上是把r.Low的字符串值传给了Add方法,而不是cRange对象。

这就导致你的m_Ranges集合里存的不是cRange对象,而是字符串。第二次调用rs.Add (r)时,Add方法期望接收cRange类型的参数,但你传的是字符串,类型不匹配,直接触发了报错。同时后面的Contains方法遍历集合时,元素是字符串而非cRange对象,也会因为没有Contains方法而失败。

2. 次要问题:复用同一个cRange对象导致数据被覆盖

VBA的对象是引用类型,你在主程序里复用了同一个r变量,第一次Add后修改r.Lowr.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

火山引擎 最新活动