VBA类模块:使用另一个属性从对象获取属性

Han*_*ans 5 excel vba class object

总而言之,我正在VBA中建立一个类模块结构,以添加具有多个里程碑的计划,但是我对此并不陌生。我做了以下工作:

  • 一个名为“计划”的类模块,其中包含一个“名称”属性(字符串)和一个“里程碑”属性(里程碑类)。
  • 此里程碑类模块是称为“里程碑”的类模块的对象的集合。
  • “里程碑”类具有“名称”属性和“值”属性。

因此,在我的模块中,我现在为特定计划指定里程碑:

Plan.Milestones.Add "MilestoneA", Cells(i, 5)
Plan.Milestones.Add "MilestoneB", Cells(i, 7)
...
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好。现在,对于MilestoneC,我想知道MilestoneA的价值。如何获得名称为“ MilestoneA”的里程碑的值。

我知道以下代码会给我答案,但是我不想对'item(1)'进行硬编码(我想使用名称):

Plan.Milestones.Item(1).Value
Run Code Online (Sandbox Code Playgroud)

在clsMilestones类中:

Private prvt_Milestones As New Collection

Property Get Item(Index As Variant) As clsMilestone
    Set Item = prvt_Milestones(Index)
End Property

Sub Add(param_Name As String, param_Value As String)

    Dim new_milestone As clsMilestone
    Set new_milestone = New clsMilestone

    new_milestone.Name = param_Name
    new_milestone.Value = param_Value

    prvt_Milestones.Add new_milestone
End Sub
Run Code Online (Sandbox Code Playgroud)

Mat*_*don 7

你的Milestones班级是一个集合班级。按照惯例,集合类有一个Item属性,它是类的默认成员。您无法在 VBA 中轻松指定类的默认成员,但这并非不可能。

导出代码文件,在记事本中打开它。找到您的Public Property Get Item成员并添加一个VB_UserMemId属性 - 当您在那里时,您也可以添加一个VB_Description属性:

Public Property Get Item(ByVal Index As Variant) As Milestone
Attribute Item.VB_UserMemId = 0
Attribute Item.VB_Description = "Gets the item at the specified index, or with the specified name."
    Set Item = prvt_Milestones(Index)
End Property
Run Code Online (Sandbox Code Playgroud)

UserMemId = 0就是使该属性成为类的默认成员的原因- 请注意,该类中只有一个成员可以具有该值。

暂时不要保存并关闭。

您还需要使您的集合类也使用For Each循环,为此您需要一个NewEnum返回 的属性,该属性IUnknown具有许多属性和标志:

Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_Description = "Gets an enumerator that iterates through the collection."
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"    
    Set NewEnum = prvt_Milestones.[_NewEnum]
End Property
Run Code Online (Sandbox Code Playgroud)

请注意,您的内部封装Collection有一个名称以下划线开头的隐藏成员 - 这在 VBA 中是非法的,因此要调用它,您需要用方括号将其括起来。

现在这段代码是合法的:

Dim ms As Milestone
For Each ms In Plan.Milestones
    Debug.Print ms.Name, ms.Value ', ms.DateDue, ...
Next
Run Code Online (Sandbox Code Playgroud)

保存文件,关闭它,然后将其重新导入到您的项目中。

由于您使用字符串键填充集合(至少您的Add方法似乎是这样做的),因此客户端代码可以使用索引或键来检索项目。

现在这Item是类的默认成员,现在是合法的:

Set milestoneA = Plan.Milestones("Milestone A").Value
Run Code Online (Sandbox Code Playgroud)

请注意,您的Add方法需要Key在添加到内部集合时为参数指定一个值- 如果您希望项目以 为键Name,请将Name用作键:

Public Sub Add(ByVal Name As String, ByVal Value As Variant)
    Dim new_milestone As Milestone
    Set new_milestone = New Milestone

    new_milestone.Name = Name
    new_milestone.Value = Value

    prvt_Milestones.Add new_milestone, Name
End Sub
Run Code Online (Sandbox Code Playgroud)


Nat*_*Sav 4

使用中dictionary的类并将 设为“Milestone_x”,并将设为Milestoneplan classkeyitemmilestone class

然后你可以说Plan.Milestones("Milestone99")