VB VarUserMemId

VB_VarUserMemId(用于模块范围变量)和 VB_UserMemId(用于过程)属性在 VBA 中主要用于两件事。

指定类的默认成员

Collection 封装的 List 类需要具有 Item 属性,因此客户端代码可以执行以下操作:

For i = 1 To myList.Count 'VBA Collection Objects are 1-based
    Debug.Print myList.Item(i)
Next

但是在 Item 属性上将 VB_UserMemId 属性设置为 0,客户端代码可以执行以下操作:

For i = 1 To myList.Count 'VBA Collection Objects are 1-based
    Debug.Print myList(i)
Next

在任何给定的类中,只有一名成员可以合法地拥有 VB_UserMemId = 0。对于属性,请在 Get 访问器中指定属性:

Option Explicit
Private internal As New Collection

Public Property Get Count() As Long
    Count = internal.Count
End Property

Public Property Get Item(ByVal index As Long) As Variant
Attribute Item.VB_Description = "Gets or sets the element at the specified index."
Attribute Item.VB_UserMemId = 0
'Gets the element at the specified index.
    Item = internal(index)    
End Property

Public Property Let Item(ByVal index As Long, ByVal value As Variant)
'Sets the element at the specified index.    
    With internal
        If index = .Count + 1 Then
            .Add item:=value
        ElseIf index = .Count Then
            .Remove index
            .Add item:=value
        ElseIf index < .Count Then
            .Remove index
            .Add item:=value, before:=index
        End If
    End With
End Property

使用 For Each 循环结构创建一个可迭代的类

使用魔术值 -4VB_UserMemId 属性告诉 VBA 该成员产生一个枚举器 - 允许客户端代码执行此操作:

Dim item As Variant
For Each item In myList
    Debug.Print item
Next

实现此方法的最简单方法是在内部/封装的 Collection 上调用隐藏的 [_NewEnum] 属性 getter; 标识符需要括在方括号中,因为前导下划线使其成为非法的 VBA 标识符:

Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_Description = "Gets an enumerator that iterates through the List."
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40" 'would hide the member in VB6. not supported in VBA.
'Gets an enumerator that iterates through the List.
    Set NewEnum = internal.[_NewEnum]    
End Property