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

所有,我在VBA中设置了一个类模块结构来添加具有多个里程碑的计划,但是我对它很陌生。 我做了以下几点:

  • 名为“计划”的类模块包含“名称”属性(string)和“里程碑”属性(类里程碑)。
  • 这个里程碑类模块是称为“里程碑”的类模块的对象的集合。
  • “里程碑”类具有“名称”属性和“值”属性。

所以在我的模块中,我现在指定一个具体计划的里程碑:

Plan.Milestones.Add "MilestoneA", Cells(i, 5) Plan.Milestones.Add "MilestoneB", Cells(i, 7) ... 

到现在一切都很好。 现在对于MilestoneC,我想知道MilestoneA的价值。 如何获得名为“MilestoneA”的Milestone的价值。

我知道下面的代码会给我答案,但我不想硬编码'项目(1)'(我想使用的名称):

 Plan.Milestones.Item(1).Value 

在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 

plan class使用Milestone类的dictionary ,并将key设置为“Milestone_x”,并将该项设置为milestone class

那么你可以说Plan.Milestones("Milestone99")

您的Milestones类是一个集合类 。 按照惯例,集合类有一个Item属性,它是类的默认成员 。 你不能在VBA中简单地指定一个类的默认成员,但这不是不可能的。

导出代码文件,在记事本中打开它。 find您的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 

UserMemId = 0是什么使该属性类的默认成员 – 请注意,只有一个成员在类中可以具有该值。

不要保存和closures。

你会想让你的集合类也工作于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 

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

现在这个代码是合法的:

 Dim ms As Milestone For Each ms In Plan.Milestones Debug.Print ms.Name, ms.Value ', ms.DateDue, ... Next 

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

由于您使用string键填充集合(至less这就是您的Add方法似乎在做什么),因此客户端代码可以使用索引或键来检索项目。

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

 Set milestoneA = Plan.Milestones("Milestone A").Value 

请注意,当添加到内部集合时,您的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 

为Milestones类添加一个属性,返回基于名称的里程碑:

 Property Get SelectByName(strMilestoneName as string) as clsMilestone Dim vIndex 'Add code here to find the index of the milestone in question vIndex = ???????? Set SelectByName = prvt_Milestones(Index) End Property 

要么

编辑项目属性以允许通过索引或名称进行select:

 Property Get Item(Index As Variant) As clsMilestone If isNumeric(Index) then Set Item = prvt_Milestones(Index) Else 'Find Item based on Name Dim vIndex vIndex = ????? Set Item = prvt_Milestones(vIndex) End If End Property