【问题标题】:Getting an object from array member in class VBA从 VBA 类中的数组成员中获取对象
【发布时间】:2018-10-27 20:56:08
【问题描述】:

我有一个名为 cSchedule 的类对象,它包含一个成员 pTimeline,它是一个 cDay 对象数组。我正在尝试使用 pTimeline 的 Get 属性在特定索引处返回 cDay 对象,但出现以下错误“运行时错误'438':对象不支持此属性或方法” .

我从我的主模块调用这个函数,如下所示

Dim TestDay As cDay
Set TestDay = TestSchedule.Timeline(1)

我已验证 TestSchedule 包含所有正确的数据,所以问题在于我如何尝试在 pTimeline 的特定索引处获取对 cDay 对象的引用。

' Class Module: cSchedule

Private pTimeline() As cDay
Private pFitness As Double
Private pMap As Collection
'Number of units the timeline is divided into. E.g if weeks, pNumTimeUnits should be 52*numYears
Private pNumTimeUnits As Integer


''''''''''''''''''''''
' Timeline property
''''''''''''''''''''''
Public Property Get Timeline(Optional argIndex As Variant) As Variant
    If IsMissing(argIndex) Then
        Timeline = pTimeline
    Else
        Dim selectedDay As Variant
        selectedDay = pTimeline(argIndex).Copy
        Set Timeline = selectedDay
    End If
End Property
Public Property Let Timeline(Optional argIndex As Variant, arrValue As Variant)
    Dim arrLength As Integer
    Dim intIndex As Integer

    ' Resize array if incoming list of activities is greater than current
    arrLength = (UBound(arrValue) - LBound(arrValue) + 1)
    If arrLength <> pNumTimeUnits Then
        ReDim Preserve pTimeline(arrLength)
        pNumTimeUnits = arrLength
    End If
    pTimeline = arrValue
End Property

谁能提供洞察我做错了什么以及从包含对象数组的类成员中获取对象的正确方法是什么?

【问题讨论】:

  • Set TestDay = TestSchedule.Timeline.Item(1) 能改进吗??
  • 您应该包含cDay 类。您几乎还应该尽可能地明确键入变量。
  • @Gary'sStudent 我相信 .Item 仅用于集合,而我使用的是数组,所以我认为这不会有帮助

标签: excel vba


【解决方案1】:

恐怕你的代码有点不对劲。

其中一个问题是您在同一个属性中返回了数组和类,这无论如何都不是很好的做法,但也会迫使您将属性作为 Variant 返回,有时需要使用关键字进行分配Set 因为返回的值有时是一个对象。

更好的方法可能是拥有两个属性:一个获取和设置数组,另一个获取该数组的单个成员。您的 cSchedule 类的缩写版本可能如下所示:

Option Explicit

Private pTimelines() As cDay
Private pTimeline() As cDay
Private pNumTimeUnits As Long

Public Property Get Timelines() As Variant
    Timelines = pTimelines
End Property

Public Property Let Timelines(RHS As Variant)
    pTimelines = RHS
    pNumTimeUnits = UBound(RHS) - LBound(RHS) + 1
End Property

Public Property Get TimelineAt(idx As Long) As cDay
    Set TimelineAt = pTimelines(idx)
End Property

其次,您的Timeline 设置例程可能没有按照您的想法进行。即使您使用 Redim Preserve 调整数组大小,后面的行 pTimeline = arrValue 也会覆盖并且实际上会调整数组大小。因此,您在该行上方的所有代码都是多余的。

最后,我怀疑引发错误的代码在selectedDay = pTimeline(argIndex).Copy 行中。如果没有看到您的 cDay 类,我们不能肯定地说,但是如果 Copy 函数返回 cDay 类,那么您将需要 Set 关键字 - 同样,这是您遇到的问题之一,如果你使用Variants 太频繁了。

就我个人而言,我会将pTimelines 定义为Collection,但无论如何,下面显示了一些示例模块代码来向您展示上述内容如何工作:

Dim testSchedule As cSchedule
Dim t() As cDay
Dim i As Long

Set testSchedule = New cSchedule

ReDim t(51)
For i = 0 To 51
    Set t(i) = New cDay
    t(i).TheDate = DateAdd("w", i, DateSerial(2018, 1, 1))
Next

testSchedule.Timelines = t

Debug.Print testSchedule.TimelineAt(0).TheDate

出于本演示的目的,我编写了如下cDay 类,但此示例未实现MyCopy 函数:

Option Explicit

Private pTheDate As Date

Public Property Get TheDate() As Date
    TheDate = pTheDate
End Property

Public Property Let TheDate(RHS As Date)
    pTheDate = RHS
End Property

Public Function MyCopy() As cDay
    Set MyCopy = New cDay
    MyCopy.TheDate = pTheDate
End Function

【讨论】:

  • 谢谢@Ambie,我通过将它分成两个属性解决了这个问题——Get TimelineAt 做得很好。与使用 MyCopy() 函数相比,我意识到这是一种更好的方法,因为我只需要对该对象的引用,而无需经历创建副本的麻烦。
猜你喜欢
  • 1970-01-01
  • 2015-04-03
  • 2018-03-21
  • 2011-10-12
  • 2021-05-10
  • 1970-01-01
  • 1970-01-01
  • 2021-03-27
  • 2019-11-12
相关资源
最近更新 更多