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