Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 在事件处理程序中触发进入和退出事件_Excel_Vba - Fatal编程技术网

Excel 在事件处理程序中触发进入和退出事件

Excel 在事件处理程序中触发进入和退出事件,excel,vba,Excel,Vba,大家好 我有一个表单,需要在其中动态添加和删除一些文本框和标签控件 要添加的每个控件也将有3个事件:在按下键时进行一些验证,在上输入和退出时进行一些其他操作。问题是事件Enter和Exit似乎在事件处理程序类模块中不起作用 同一个项目有其他事件处理程序模块,它们工作得很好(但它们没有Enter或Exit事件) 事件处理程序类模块中的代码如下所示。我不会在表单模块中发布代码,因为它工作正常,只是事件处理程序中的Enter和Exit事件 您知道有什么方法可以触发动态添加的文本框的Enter和Exit

大家好

我有一个表单,需要在其中动态添加和删除一些
文本框
标签
控件

要添加的每个控件也将有3个事件:在按下
键时进行一些验证,在
上输入
退出
时进行一些其他操作。问题是事件
Enter
Exit
似乎在事件处理程序类模块中不起作用

同一个项目有其他事件处理程序模块,它们工作得很好(但它们没有
Enter
Exit
事件)

事件处理程序类模块中的代码如下所示。我不会在表单模块中发布代码,因为它工作正常,只是事件处理程序中的
Enter
Exit
事件

您知道有什么方法可以触发动态添加的
文本框的
Enter
Exit
事件的操作吗?

编辑:我的目标是在
文本框
对焦和失去对焦时制作一些很酷的过渡动画。此动画已与预先存在的控件一起出现;这是一个在进入和退出事件时触发的函数(GotFocus和LostFocus很好,但也不可用)


不幸的是,事件处理程序类方法公开的事件列表不包括
Enter
Exit
事件。您可以看到IDE中有哪些可用的事件


如果不了解您的项目,就很难推荐任何替代方案。

好吧,也许有点棘手,但我回答我的问题是为了记录我在这个问题上的转变

其他研究员的回答否定了我对事件处理程序类模块中的功能性
Enter
Exit
事件的期望,因此,下面是我所做的,它似乎起到了作用

基本思路如下:我正在尝试触发一些函数,这些函数可以在控件之间生成令人愉快的过渡动画,因此我可以假设,当用户手动从一个控件切换到另一个控件时,我只需要使用它们:(a)(如果代码自动填充任何内容,我将不使用动画,只通过特定代码放置结束标记);以及(b)当这些输入控件可选择时(即have
TabStop=True

用户通过单击控件并按
Tab
Shift+Tab
手动从一个控件切换到另一个控件。我可以通过
KeyUp
(对我来说比
KeyDown
更有效),
MouseDown
(无需尝试
MouseUp
)在事件处理程序类模块中跟踪这些事件,然后单击(在命令按钮控件中)

我的表单有12个带有TabStop(5个文本框、5个组合框和2个命令按钮)的静态控件,可以动态创建5个(3个文本框和2个组合框)

因此,我创建了3个事件处理程序类模块(用于命令按钮、组合框和文本框)来跟踪伪进入和伪退出事件。事实上,当用户单击某个控件或按下tab或shift+tab时,这些事件处理程序会侦听(毕竟,这些是手动转到另一个控件的方法)。为了知道用户是否转到了另一个控件,或者他是否只是单击了他已经在其中的控件,我定义了两个全局对象变量,分别称为
oActiveControl
OPPreviousControl
,作为标记。如果单击/选项卡的控件与
oActiveControl
不同,这意味着用户具有nged控件,因此我需要更新我的令牌。

这真的很好(在这可怜的4个小时内;没有经过严格测试)。下面是代码:

''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''' ANY MODULE ''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''

Public oActiveControl As MSForms.Control, oPreviousControl As MSForms.Control



''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''' USER FORM MODULE '''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Sub UserForm_Initialize()
' On loading the UserForm, we are going to create the event handlers for the static controls.
    Dim oControl As MSForms.Control
    Dim oEvHandlerExitText As EvHndlExitTxt
    Dim oEvHandlerExitCombo As EvHndlExitCbx
    Dim oEvHandlerExitButton As EvHndlExitBtn
    Dim colEventHandlers as Collection

    Set colEventHandlers = New Collection
    
    ' Loop to create the event handlers and store them in a collection
    For Each oControl In Me.Controls
        Select Case TypeName(oControl)
        Case "TextBox"
            If oControl.TabStop = True Then
                Set oEvHandlerExitText = New EvHndlExitTxt
                Set oEvHandlerExitText.TextBox = oControl
                colEventHandlers.Add oEvHandlerExitText
            End If
            
        Case "ComboBox"
            If oControl.TabStop = True Then
                Set oEvHandlerExitCombo = New EvHndlExitCbx
                Set oEvHandlerExitCombo.ComboBox = oControl
                colEventHandlers.Add oEvHandlerExitCombo
            End If
            
        Case "CommandButton"
            If oControl.TabStop = True Then
                Set oEvHandlerExitButton = New EvHndlExitBtn
                Set oEvHandlerExitButton.Button = oControl
                colEventHandlers.Add oEvHandlerExitButton
            End If
            
        End Select
    Next oControl
End Sub


Private Sub UserForm_AddControl(ByVal Control As MSForms.Control)
' Whenever we add a control to the UserForm, if it is a Combobox, Textbox
' or Button, we are also creating their event handlers.

    Select Case TypeName(Control)
    Case "TextBox"
        If Control.TabStop = True Then
            Dim oEvHandlerExitText As EvHndlExitTxt
            Set oEvHandlerExitText = New EvHndlExitTxt
            Set oEvHandlerExitText.TextBox = Control
            colEventHandlers.Add oEvHandlerExitText
        End If
        
    Case "ComboBox"
        If Control.TabStop = True Then
            Dim oEvHandlerExitCombo As EvHndlExitCbx
            Set oEvHandlerExitCombo = New EvHndlExitCbx
            Set oEvHandlerExitCombo.ComboBox = Control
            colEventHandlers.Add oEvHandlerExitCombo
        End If
        
    Case "CommandButton"
        If Control.TabStop = True Then
            Dim oEvHandlerExitButton As EvHndlExitBtn
            Set oEvHandlerExitButton = New EvHndlExitBtn
            Set oEvHandlerExitButton.Button = Control
            colEventHandlers.Add oEvHandlerExitButton
        End If
        
    End Select
End Sub

Private Sub UserForm_Terminate()
' On unloading the form, we need to dump the global token variables
    Set oActiveControl = Nothing
    Set oPreviousControl = Nothing
End Sub



''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''' CLASS MODULE EvHndlExitBtn ''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''

Option Explicit

Private WithEvents moBtn As MSForms.CommandButton

Public Property Set Button(ByVal oBtn As MSForms.CommandButton)
    Set moBtn = oBtn
End Property

' The command buttons have no transitions, so there are no functions in pseudo-Enter nor
' pseudo-Exit events. This class module is here only to detect clicks or tabs which leaves
' other controls.

Private Sub moBtn_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 9 Or KeyCode = 16 Then ' 9 = Tab, 16 = Shift + Tab
        If oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
        Set oActiveControl = moBtn
    End If
End Sub

Private Sub moBtn_Click()
    If oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
    Set oActiveControl = moBtn
End Sub



''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''' CLASS MODULE EvHndlExitTxt ''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''

Option Explicit

Private WithEvents moTxtBox As MSForms.TextBox

Public Property Set TextBox(ByVal oTxtBox As MSForms.TextBox)
    Set moTxtBox = oTxtBox
End Property

Private Sub moTxtBox_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 9 Or KeyCode = 16 Then ' 9 = Tab, 16 = Shift + Tab
        If Not oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
        Set oActiveControl = moTxtBox

        If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
        ' Here is the pseudo-Enter event from the TextBox reached via Tab/Shift+Tab:
            ' Instructions... (these instructions will have to be repeated below, so
            ' Instructions...  consider creating a function if there are many of them.)
                
            If Not oPreviousControl Is Nothing Then
            ' Here is the pseudo-Exit event from the previous control:
                ' Instructions... (Use oPreviousControl to refer the control which lost focus.
                ' Instructions...  Will have to be repeated below also)
            End If
        End If
    End If
End Sub

Private Sub moTxtBox_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If Not oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
    Set oActiveControl = moTxtBox

    If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
    ' Here is the pseudo-Enter event from the TextBox reached via mouse clicking:
        ' Instructions... (these instructions where repeated above, so consider
        ' Instructions...  creating a function if there are many of them.)
            
        If Not oPreviousControl Is Nothing Then
        ' Here is the pseudo-Exit event from the previous control:
            ' Instructions... (Use oPreviousControl to refer the control which lost focus.
            ' Instructions...  Was repeated above also)
        End If
    End If
End Sub



''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''' CLASS MODULE EvHndlExitCbx ''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''

Option Explicit

Private WithEvents moCmbBox As MSForms.ComboBox

Public Property Set ComboBox(ByVal oCmbBox As MSForms.ComboBox)
    Set moCmbBox = oCmbBox
End Property

Private Sub moCmbBox_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 9 Or KeyCode = 16 Then
        If Not oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
        Set oActiveControl = moCmbBox
        
        If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
        ' Here is the pseudo-Enter event from the ComboBox reached via Tab/Shift+Tab:
            ' Instructions... (these instructions will have to be repeated 4 times, so
            ' Instructions...  consider creating a function if there are many of them.)
            
            If Not oPreviousControl Is Nothing Then
            ' Here is the pseudo-Exit event from the previous control:
                ' Instructions... (Use oPreviousControl to refer the control which lost focus.
                ' Instructions...  Will have to be repeated below also)
            End If
        End If
    End If
End Sub

Private Sub moCmbBox_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If Not oActiveControl Is Nothing Then oPreviousControl = oActiveControl
    Set oActiveControl = moCmbBox
    
    If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
    ' Here is the pseudo-Enter event from the ComboBox reached via mouse clicking:
        ' Instructions... (these instructions where repeated above, so consider
        ' Instructions...  creating a function if there are many of them.)
            
        If Not oPreviousControl Is Nothing Then
        ' Here is the pseudo-Exit event from the previous control:
            ' Instructions... (Use oPreviousControl to refer the control which lost focus.
            ' Instructions...  Was repeated above also)
        End If
    End If
End Sub
为了节省代码,我改编了Gary McGill对这个问题的雄伟回答:

谢谢,克里斯·尼尔森和瓦里塔斯!你的解释对我帮助很大!如果有人对这个问题有更简洁的答案,请在这里发布。
编辑:再次感谢Chris注意到我在比较对象时看不到的问题!

我编辑了这个问题来解释我想做什么。我的目标是调用一个函数,当文本框获得或失去焦点时,该函数会进行愉快的转换。的确,你是对的,在它们的文本框之前创建的事件过程不会发生re.它以前是有效的。现在我记下了我的答案。我将为您寻找更好的答案。我没有找到方法以您选择的方法(看起来是正确的)使Enter事件可用。因此,我建议您创建所需的控件及其事件过程,并将它们隐藏在初始化事件中,使它们在需要时可见。每当我使用此方法时,我都会禁用它们,有时会将它们移到一边并/或调整其大小。但最近我没有费事,也没有产生不良影响。它似乎一度不可见你可以直接点击它们。好的,这可能会起作用。谢谢!我正在尝试一些边缘仍在修整的解决方案,如果一切顺利,这将是一个更经济的代码,我将很快描述。如果它不起作用,我将尝试这种方式。看看这里:对于退出-进入和其他活动:哇!这将是我希望从e开始!我不会在这个项目中更改它,因为我的变通方法非常适合我的应用程序,但是当我需要再次动态地输入和退出事件时,它将是这种方式。谢谢!很高兴看到你有一个适合你的解决方案。一个小问题:你说出于某种原因,控件对象之间的比较不起作用,但是工作d和他们的名字你试过了吗?如果不是的话,oActiveControl是moCxTexto,那么
?对,我在比较对象!Duh!真的谢谢你,伙计!
''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''' ANY MODULE ''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''

Public oActiveControl As MSForms.Control, oPreviousControl As MSForms.Control



''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''' USER FORM MODULE '''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Sub UserForm_Initialize()
' On loading the UserForm, we are going to create the event handlers for the static controls.
    Dim oControl As MSForms.Control
    Dim oEvHandlerExitText As EvHndlExitTxt
    Dim oEvHandlerExitCombo As EvHndlExitCbx
    Dim oEvHandlerExitButton As EvHndlExitBtn
    Dim colEventHandlers as Collection

    Set colEventHandlers = New Collection
    
    ' Loop to create the event handlers and store them in a collection
    For Each oControl In Me.Controls
        Select Case TypeName(oControl)
        Case "TextBox"
            If oControl.TabStop = True Then
                Set oEvHandlerExitText = New EvHndlExitTxt
                Set oEvHandlerExitText.TextBox = oControl
                colEventHandlers.Add oEvHandlerExitText
            End If
            
        Case "ComboBox"
            If oControl.TabStop = True Then
                Set oEvHandlerExitCombo = New EvHndlExitCbx
                Set oEvHandlerExitCombo.ComboBox = oControl
                colEventHandlers.Add oEvHandlerExitCombo
            End If
            
        Case "CommandButton"
            If oControl.TabStop = True Then
                Set oEvHandlerExitButton = New EvHndlExitBtn
                Set oEvHandlerExitButton.Button = oControl
                colEventHandlers.Add oEvHandlerExitButton
            End If
            
        End Select
    Next oControl
End Sub


Private Sub UserForm_AddControl(ByVal Control As MSForms.Control)
' Whenever we add a control to the UserForm, if it is a Combobox, Textbox
' or Button, we are also creating their event handlers.

    Select Case TypeName(Control)
    Case "TextBox"
        If Control.TabStop = True Then
            Dim oEvHandlerExitText As EvHndlExitTxt
            Set oEvHandlerExitText = New EvHndlExitTxt
            Set oEvHandlerExitText.TextBox = Control
            colEventHandlers.Add oEvHandlerExitText
        End If
        
    Case "ComboBox"
        If Control.TabStop = True Then
            Dim oEvHandlerExitCombo As EvHndlExitCbx
            Set oEvHandlerExitCombo = New EvHndlExitCbx
            Set oEvHandlerExitCombo.ComboBox = Control
            colEventHandlers.Add oEvHandlerExitCombo
        End If
        
    Case "CommandButton"
        If Control.TabStop = True Then
            Dim oEvHandlerExitButton As EvHndlExitBtn
            Set oEvHandlerExitButton = New EvHndlExitBtn
            Set oEvHandlerExitButton.Button = Control
            colEventHandlers.Add oEvHandlerExitButton
        End If
        
    End Select
End Sub

Private Sub UserForm_Terminate()
' On unloading the form, we need to dump the global token variables
    Set oActiveControl = Nothing
    Set oPreviousControl = Nothing
End Sub



''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''' CLASS MODULE EvHndlExitBtn ''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''

Option Explicit

Private WithEvents moBtn As MSForms.CommandButton

Public Property Set Button(ByVal oBtn As MSForms.CommandButton)
    Set moBtn = oBtn
End Property

' The command buttons have no transitions, so there are no functions in pseudo-Enter nor
' pseudo-Exit events. This class module is here only to detect clicks or tabs which leaves
' other controls.

Private Sub moBtn_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 9 Or KeyCode = 16 Then ' 9 = Tab, 16 = Shift + Tab
        If oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
        Set oActiveControl = moBtn
    End If
End Sub

Private Sub moBtn_Click()
    If oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
    Set oActiveControl = moBtn
End Sub



''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''' CLASS MODULE EvHndlExitTxt ''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''

Option Explicit

Private WithEvents moTxtBox As MSForms.TextBox

Public Property Set TextBox(ByVal oTxtBox As MSForms.TextBox)
    Set moTxtBox = oTxtBox
End Property

Private Sub moTxtBox_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 9 Or KeyCode = 16 Then ' 9 = Tab, 16 = Shift + Tab
        If Not oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
        Set oActiveControl = moTxtBox

        If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
        ' Here is the pseudo-Enter event from the TextBox reached via Tab/Shift+Tab:
            ' Instructions... (these instructions will have to be repeated below, so
            ' Instructions...  consider creating a function if there are many of them.)
                
            If Not oPreviousControl Is Nothing Then
            ' Here is the pseudo-Exit event from the previous control:
                ' Instructions... (Use oPreviousControl to refer the control which lost focus.
                ' Instructions...  Will have to be repeated below also)
            End If
        End If
    End If
End Sub

Private Sub moTxtBox_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If Not oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
    Set oActiveControl = moTxtBox

    If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
    ' Here is the pseudo-Enter event from the TextBox reached via mouse clicking:
        ' Instructions... (these instructions where repeated above, so consider
        ' Instructions...  creating a function if there are many of them.)
            
        If Not oPreviousControl Is Nothing Then
        ' Here is the pseudo-Exit event from the previous control:
            ' Instructions... (Use oPreviousControl to refer the control which lost focus.
            ' Instructions...  Was repeated above also)
        End If
    End If
End Sub



''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''' CLASS MODULE EvHndlExitCbx ''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''

Option Explicit

Private WithEvents moCmbBox As MSForms.ComboBox

Public Property Set ComboBox(ByVal oCmbBox As MSForms.ComboBox)
    Set moCmbBox = oCmbBox
End Property

Private Sub moCmbBox_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 9 Or KeyCode = 16 Then
        If Not oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
        Set oActiveControl = moCmbBox
        
        If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
        ' Here is the pseudo-Enter event from the ComboBox reached via Tab/Shift+Tab:
            ' Instructions... (these instructions will have to be repeated 4 times, so
            ' Instructions...  consider creating a function if there are many of them.)
            
            If Not oPreviousControl Is Nothing Then
            ' Here is the pseudo-Exit event from the previous control:
                ' Instructions... (Use oPreviousControl to refer the control which lost focus.
                ' Instructions...  Will have to be repeated below also)
            End If
        End If
    End If
End Sub

Private Sub moCmbBox_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If Not oActiveControl Is Nothing Then oPreviousControl = oActiveControl
    Set oActiveControl = moCmbBox
    
    If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
    ' Here is the pseudo-Enter event from the ComboBox reached via mouse clicking:
        ' Instructions... (these instructions where repeated above, so consider
        ' Instructions...  creating a function if there are many of them.)
            
        If Not oPreviousControl Is Nothing Then
        ' Here is the pseudo-Exit event from the previous control:
            ' Instructions... (Use oPreviousControl to refer the control which lost focus.
            ' Instructions...  Was repeated above also)
        End If
    End If
End Sub