在 Visual Basic 编辑器 (F5) 中运行用户窗体与使用 Show 打开它之间的区别?

问题描述 投票:0回答:1

我有一个用户表单(

form_Updaterow
),将一些脚本放在一起,以便在单击文本框时在标签中显示附加信息。

当我按 F5 运行用户表单时,它可以工作。当我使用

.Show
(从另一个表单或从宏)打开表单时,脚本不起作用。 跑步展示可以带来不同的结果吗?

这就是我(理论上)正在做的事情:

1.在表单的(

form_Updaterow
)中,我在初始化表单时为文本框定义了一个新集合。 (我添加了一个 MsgBox 以确认它运行此代码。)

Dim tbCollection As Collection
Dim cbCollection As Collection

Private Sub UserForm_Initialize()
MsgBox ("UserForm initialized")
    Sheets("DES").Activate
    Dim ctrl As MSForms.Control
    
    Dim obj_tb As clsTextBox
    Set tbCollection = New Collection
        For Each ctrl In Me.Controls
            If TypeOf ctrl Is MSForms.TextBox Then
                Set obj_tb = New clsTextBox
                Set obj_tb.Control = ctrl
                tbCollection.Add obj_tb
            End If
        Next ctrl
    Set obj_tb = Nothing
End Sub

2.在类模块中(

clsTextBox
):

Private WithEvents MyTextBox As MSForms.TextBox

Public Property Set Control(tb As MSForms.TextBox)
'MsgBox ("TextBox property set")
    Set MyTextBox = tb
End Property

Private Sub MyTextBox_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'MsgBox ("Call the provider")
    Call TheInfoProvider
End Sub

3.在模块 (

mod_Infos
) 中,我循环遍历文本框并识别已单击的文本框。 (因为某些文本框位于框架中,所以我必须添加 activename() 函数。否则我无法使其工作)。然后,我使用文本框的名称 ('txt_VARNAME') 来识别表中的指导文本 (
DatDic_DES
)。

Public Sub TheInfoProvider()
'MsgBox ("I'm the Info Provider")
For Each c In form_Updaterow.Controls

    If TypeName(c) = "TextBox" Or TypeName(c) = "ComboBox" Then
        MsgBox activename
        If c.Name = activename() Then
        
            varname = Split(c.Name, "_", 2)(1)
            
            Set DatDic = Worksheets("Data Dictionary").ListObjects("DatDic_DES")
            varnames = DatDic.ListColumns("Variable Name").Range
            tabrow = Application.Match(varname, varnames, 0)
            
            form_Updaterow.fr_varname.Visible = True
            form_Updaterow.lbl_varname.Caption = varname
            
            guidance = DatDic.ListColumns("Guidance").Range.Cells(tabrow)
            form_Updaterow.lbl_guidance.Caption = guidance
        End If
        
    End If
Next c
End Sub

Public Function activename() As String 'MSForms.Control
    Set ReallyActiveControl = form_Updaterow.ActiveControl
    On Error Resume Next
    Set ReallyActiveControl = ReallyActiveControl.ActiveControl
    activename = ReallyActiveControl.Name
End Function

当我使用 F5 运行表单 (

form_Updaterow
) 时,代码有效:我收到“UserForm 已初始化”消息,然后弹出一个包含单击文本框名称的窗口(多次,每个文本框一次)我的表格)。结果是标签 (
lbl_guidance
) 现在已更改为该文本框的指导文本。

但是,当我使用

.Show
加载表单时,例如使用下面的宏(也是当我从另一个表单加载时): 在显示表单之前,我收到“UserForm 已初始化”消息(到目前为止,一切都很好)。然后,当我单击文本框时,我再次收到相同的消息,然后是多个空消息框。

Public Sub Main()
    Dim frm As New form_Updaterow
    frm.Show vbModel
    Set frm = Nothing
End Sub

问题似乎出在识别 ActiveControl 上。

故障排除之所以如此具有挑战性,是因为当我按 F5 运行表单时和使用宏(或另一个用户表单中的按钮)

.Show
表单时,行为是不同的。我认为这将有助于理解加载表单的一种方式和另一种方式之间的根本区别。

我在 Office 365 版本 2408(内部版本 17928.20156 即点即用)和 VBA 7.1.1143 上使用 Excel

excel vba userform
1个回答
0
投票

感谢@TimWilliams 提供了最初问题的解决方案。无需调用

TheInfoProvider
并让它使用循环查找选定的 TextBox,而是直接将 TextBox 传递给它解决了该问题。不过,在更新指导标签时出现了另一个问题,在 @TimWilliams 建议使用
.Parent
(对框架中的文本框进行一些调整)后,这个问题得到了解决。

这是新的、完全有效的代码:

clsTextBox
课程模块中

Private Sub MyTextBox_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    TheInfoProvider MyTextBox
End Sub

mod_Infos
模块中(我注释掉了旧代码以显示差异)

Public Sub TheInfoProvider(c)
'MsgBox ("I'm the Info Provider")
'    For Each c In form_Updaterow.Controls
'
'        If TypeName(c) = "TextBox" Or TypeName(c) = "ComboBox" Then
'            MsgBox cargo.Name
'            If c.Name = cargo.Name Then
        Dim ancestry As Object
        Set ancestry = c.Parent
        If c.Parent.Name <> "form_Updaterow" Then
            Set ancestry = c.Parent.Parent
        End If
        varname = Split(c.Name, "_", 2)(1)
        Set DatDic = Worksheets("Data Dictionary").ListObjects("DatDic_DES")
        varnames = DatDic.ListColumns("Variable Name").Range
        tabrow = Application.Match(varname, varnames, 0)
        
        ancestry.fr_varname.Visible = True
        ancestry.lbl_varname.Caption = varname
        
        guidance = DatDic.ListColumns("Guidance").Range.Cells(tabrow)
        ancestry.lbl_guidance.Caption = guidance
'            End If
'
'        End If
'    Next c
End Sub

非常感谢您帮我解决这个问题!

© www.soinside.com 2019 - 2024. All rights reserved.