Excel 通过控件的类触发输入字段行为
我提出了一个符合David Zemens指示和BrakNicku指导的方案 问题是我想使用的事件之一是Enter。在类中,我没有此事件的选项。是否有办法将其添加到类中或以某种方式触发控件的Enter事件 我尝试了课堂上的大多数活动,但没有一个是我所需要的 快速背景:我使用Enter事件为焦点字段设置帮助文本。因此,每次用户输入一个字段时,我都会有一个帮助文本框,其中会填充帮助文本 我无法共享工作簿。假设您的userform(Userform1)如下所示 我将演示两个控件的Excel 通过控件的类触发输入字段行为,excel,vba,Excel,Vba,我提出了一个符合David Zemens指示和BrakNicku指导的方案 问题是我想使用的事件之一是Enter。在类中,我没有此事件的选项。是否有办法将其添加到类中或以某种方式触发控件的Enter事件 我尝试了课堂上的大多数活动,但没有一个是我所需要的 快速背景:我使用Enter事件为焦点字段设置帮助文本。因此,每次用户输入一个字段时,我都会有一个帮助文本框,其中会填充帮助文本 我无法共享工作簿。假设您的userform(Userform1)如下所示 我将演示两个控件的Enter事件文本框和
Enter事件
<代码>文本框和组合框
确保将命令按钮1
放在用户表单的第一位。或者,将其设置为TabIndex
为0
。这是因为当用户窗体加载时,命令按钮首先聚焦,您可以测试文本框
和组合框
的输入
将其粘贴到类模块中。我的班级模块名是Class1
Option Explicit
Public WithEvents Usrfrm As UserForm1
Const MyMsg As String = "Hiya there. Did you just try to sneak into the "
Private Sub Usrfrm_OnEnter(ctrl As msforms.Control)
Select Case True
Case TypeName(ctrl) Like "ComboBox"
'Call Usrfrm.Combobox_List(ctrl)
MsgBox MyMsg & "combobox?", vbCritical, "Aha!"
Case TypeName(ctrl) Like "TextBox"
MsgBox MyMsg & "textbox?", vbCritical, "Aha!"
End Select
End Sub
将其粘贴到userform代码区域
Option Explicit
Public Event OnEnter(ctrl As msforms.Control)
Private prevCtl As msforms.Control
Private mycls As Class1
Private IsfrmUnloaded As Boolean
Private Sub CommandButton1_Click()
Unload Me
End Sub
Private Sub UserForm_Layout()
Call spyWhatsGoingOn
End Sub
Private Sub spyWhatsGoingOn()
Set mycls = New Class1
Set mycls.Usrfrm = Me
IsfrmUnloaded = False
Set prevCtl = Me.ActiveControl
RaiseEvent OnEnter(Me.ActiveControl)
Do While IsfrmUnloaded = False
If Not prevCtl Is Nothing Then
If Not prevCtl Is Me.ActiveControl Then
RaiseEvent OnEnter(Me.ActiveControl)
Me.ActiveControl.SetFocus
End If
End If
Set prevCtl = Me.ActiveControl
DoEvents
Loop
End Sub
演示
这里是另一个解决方案(在MAC上不起作用)
打开记事本,复制下面的代码,并将其粘贴到新的txt文件中
将其保存到CatchEvents.cls
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "CatchEvents"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
#If VBA7 And Win64 Then
Private Declare PtrSafe Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" (ByVal punk As stdole.IUnknown, _
ByRef riidEvent As GUID, ByVal fConnect As Long, ByVal punkTarget As stdole.IUnknown, ByRef pdwCookie As Long, _
Optional ByVal ppcpOut As LongPtr) As Long
#Else
Private Declare Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" (ByVal punk As stdole.IUnknown, ByRef riidEvent As GUID, _
ByVal fConnect As Long, ByVal punkTarget As stdole.IUnknown, ByRef pdwCookie As Long, Optional ByVal ppcpOut As Long) As Long
#End If
Private EventGuide As GUID
Private Ck As Long
Private ctl As Object
'All Other Control-Events also possible
Public Sub MyEnter()
Attribute MyEnter.VB_UserMemId = -2147384830
Select Case TypeName(ctl)
Case "TextBox": MsgBox "Your code for " & ctl.Name & " here!"
Case Else: MsgBox "You entered no TextBox but another control (" & ctl.Name & ")!"
End Select
End Sub
Public Sub ConnectAllEvents(ByVal Connect As Boolean)
With EventGuide
.Data1 = &H20400
.Data4(0) = &HC0
.Data4(7) = &H46
End With
ConnectToConnectionPoint Me, EventGuide, Connect, ctl, Ck, 0&
End Sub
Public Property Let Item(Ctrl As Object)
Set ctl = Ctrl
Call ConnectAllEvents(True)
End Property
Public Sub Clear()
If (Ck <> 0) Then Call ConnectAllEvents(False)
Set ctl = Nothing
End Sub
现在,任何控件的每个Enter事件都将被捕获,因此您必须相应地采取行动。
用户表单上的每个事件都可以通过这种方式捕获。因此我采用的方法是:我已经有了捕获
Change
event()的类模块。由于我无法访问类中的Enter
事件,因此我使用该类中的KeyUp
和MouseDown
事件为每个控件设置帮助。通过这种方式,用户可以通过单击某个字段或用Tab键指向该字段:显示所选控件的帮助输入哪个控件的事件?文本框?如果是,则可以使用tb\u Enter()
。如果它是工作表中的ActiveX控件,则可以使用tb\u GotFocus()
。类似的回复可以在Hi@SiddharthRout找到:谢谢你的回复。我确实尝试了tb\u Enter()
(因为它是一个表单控件),但不幸的是,当我在表单中输入文本框字段时,它没有触发。我使用的是tbu Change
,效果非常好。我能想到的唯一原因是Change
在类中的事件列表中,而Enter
不在类中。是否有办法添加Enter
事件,以便在用户输入文本框字段时触发该事件?然后,我可以对表单中的所有其他字段类型(即Comobox、optionbuttons等)使用相同的逻辑。您确定它是表单控件吗<代码>文本字段对工作表禁用。我想你的工作表上可能有一个ActiveX控件,我有点困惑。您的控件是在用户窗体上还是在工作表中?Enter
不会为带有事件的触发MSForms.TextBox
,这很难解决。您好,Siddharth,我尝试实现此解决方案,但它似乎陷入了Do而IsfrmUnloaded=False
在spywhatsgoongon
sub中的循环中。不确定它是否会退出该循环,因为我们没有将IsfrmUnloaded
设置为TRUE。。或者我遗漏了什么?你复制了我上面发布的代码吗?baove代码经过尝试和测试。因此,我创建了一个名为frmEvents
的新类,并将您的类中的代码粘贴到这个类中。我将with events
更改为Public with events Usrfrm作为frmNewProductExtension
(frmNewProductExtension是我表单的名称)。然后,我将剩下的代码粘贴到表单中,并将Private mycls更改为Class1
,将Private mycls更改为frmEvents
。这似乎正确吗?在对代码进行任何更改之前,请创建一个新的excel文件,并按照我的说明进行操作。检查上述代码是否有效。一旦你看到了它的工作原理,然后花一些时间去理解代码的作用,并最终在你的代码中实现它:)将会做什么。如果我有任何问题,我会给你回复,但谢谢你的帮助mateHi EvR:thecls
文件;看起来它本质上是一个类。该代码不能放在类
模块中吗?我有点不愿意依赖工作簿之外的文件,因为此工作簿正在全球范围内使用,这意味着每当有人想要使用该文件时,他们也必须拥有cls
文件是的,它是一个类,但您必须导入它(一次)这是因为隐藏属性不能在类中直接复制,但只需在文件中复制一次。这个答案对我来说很有用,不会占用处理器。谢谢EvR
Private AllControls() As New CatchEvents 'on top
Private Sub UserForm_Initialize()
ReDim AllControls(Controls.Count - 1)
For j = 0 To Controls.Count - 1
AllControls(j).Item = Controls(j)
Next
End Sub