Vba 单击类模块中的事件不触发

Vba 单击类模块中的事件不触发,vba,excel,class,events,Vba,Excel,Class,Events,我有一个用户表单,它显示逐行验证错误(在文本框中),我想用用户表单标签来补充这些错误,这些标签充当超链接,用户可以单击这些超链接直接转到有问题的单元格 我有一些代码可以动态地构建标签,并通过类模块添加了一个click事件,但我无法使它成为类模块中要触发的click事件 我确实从构建这种类型的标签并动态单击事件的工作代码中修改了这段代码,但该代码在用户表单启动时加载标签,并将每个类对象放置到一个集合中。我不知道这对我的解决方案是否有必要,但我玩了它,无法让它工作 下面是我在需要时在userform

我有一个用户表单,它显示逐行验证错误(在文本框中),我想用用户表单标签来补充这些错误,这些标签充当超链接,用户可以单击这些超链接直接转到有问题的单元格

我有一些代码可以动态地构建标签,并通过类模块添加了一个click事件,但我无法使它成为类模块中要触发的click事件

我确实从构建这种类型的标签并动态单击事件的工作代码中修改了这段代码,但该代码在用户表单启动时加载标签,并将每个类对象放置到一个集合中。我不知道这对我的解决方案是否有必要,但我玩了它,无法让它工作

下面是我在需要时在userform上放置标签的过程。如果需要验证,它将在另一个过程中运行。如果需要验证,则显示Userform,并用消息(以及现在创建的这个标签)填写

Sub PlaceLinkLabel(SayWhat As String, WhichSheet As String, WhichRange As String)

    Dim lblNew As MSForms.Label
    Set lblNew = frmValidationMessage.Controls.Add(bstrProgID:="Forms.Label.1", Name:=SayWhat, Visible:=True)

    With lblNew
        With .Font
            .Size = 10
            .Name = "Comic Sans MS"
        End With

        .Caption = SayWhat
        .Top = 55
        .Height = 15
        .Left = 465
        .Width = 100
    End With

    Dim clsLabel As UserFormLabelLinks
    Set clsLabel = New UserFormLabelLinks
    Set clsLabel.lbl = lblNew

    With clsLabel
        .WhichRange = WhichRange
        .WhichSheet = WhichSheet
    End With

    'not sure if this is needed or not
    'Dim pLabels As Collection
    'Set pLabels = New Collection
    'pLabels.Add clsLabel

End Sub
下面是
UserFormLabelLinks
class模块:

Option Explicit

Private WithEvents pLabel As MSForms.Label
Private sWhichRange As String
Private sWhichSheet As String

Public Property Set lbl(value As MSForms.Label)
    Set pLabel = value
End Property

Public Property Get WhichSheet() As String
    WhichSheet = sWhichSheet
End Property

Public Property Let WhichSheet(value As String)
    sWhichSheet = value
End Property

Public Property Get WhichRange() As String
    WhichRange = sWhichRange
End Property

Public Property Let WhichRange(value As String)
    sWhichRange = value
End Property


Private Sub pLabel_Click()

    MsgBox "hi" 'when i click label, this does not fire

    'Application.Goto ThisWorkbook.Worksheets(WhichSheet).Range(WhichRange), True
    'ActiveWorkbook.FollowHyperlink ("#" & WhichSheet & "!" & WhichRange)

End Sub

MSForms.Label
对象在
PlaceLinkLabel
退出后将退出作用域,
UserFormLabelLinks
对象引用也将退出作用域;因此,您正在创建一个标签,但这是一个“触发并忘记”事件,一旦到达
End Sub
,您就无法通过编程方式访问它,因此事件永远不会触发

您需要一个私有字段来保存
UserFormLabelLinks
对象引用(从而通过封装的
pLabel
字段保留
MSForms.Label
引用):

然后在以下步骤中删除此行:


换句话说,将该局部变量提升到一个字段中,以便在过程完成后将其保留。

另一种有效的方法:

放置
专用标签作为集合
放在存储
PlaceLinkLabel
的模块顶部

和使用

If pLabels Is Nothing Then Set pLabels = New Collection
pLabels.Add clsLabel

PlaceLinkLabel
module

的末尾,我就知道你会在这个模块上。非常感谢。在我发布问题后,我还发现了另一种方法,通过收集来实现。我也会给出这个答案,仅供参考。将引用存储在模块级集合中也可以保持它的存在。这样做的目的就是让对象引用比过程更长寿=)是的。当我发布问题并再次查看代码时,我立即理解了问题(保持对象在附近)。这就像只是问一个提供了答案的问题——这在生活中经常发生。#Rubberducked=)Upovoted,但将该收藏公开对我来说似乎是“危险的”!是的,很好。因为另一个过程模块可能会意外地正确访问该集合,并将其设置为“无”,或“清除”,或执行不允许执行的操作。并不是说任何一个理智的开发人员都会这么做,但为什么一开始就允许这样做呢?@Mat'sMug-有趣的是,当我使用你的方法并添加了多个标签时,只有最后添加的标签触发了代码。当我使用collection方法时,所有标签都触发了代码,这实际上非常有意义。更多为其他可能在这个问题上绊倒并可能添加多个标签的人发表此评论。FWIW我打开了一个-我们应该能够静态确定事件源超出范围,并对此发出警告=)@Mat'sMug-真棒。很高兴我的问题可能会改进某些软件:)
Dim clsLabel As UserFormLabelLinks
If pLabels Is Nothing Then Set pLabels = New Collection
pLabels.Add clsLabel