Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/27.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.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,我提出了一个符合David Zemens指示和BrakNicku指导的方案 问题是我想使用的事件之一是Enter。在类中,我没有此事件的选项。是否有办法将其添加到类中或以某种方式触发控件的Enter事件 我尝试了课堂上的大多数活动,但没有一个是我所需要的 快速背景:我使用Enter事件为焦点字段设置帮助文本。因此,每次用户输入一个字段时,我都会有一个帮助文本框,其中会填充帮助文本 我无法共享工作簿。假设您的userform(Userform1)如下所示 我将演示两个控件的Enter事件文本框和

我提出了一个符合David Zemens指示和BrakNicku指导的方案

问题是我想使用的事件之一是Enter。在类中,我没有此事件的选项。是否有办法将其添加到类中或以某种方式触发控件的Enter事件

我尝试了课堂上的大多数活动,但没有一个是我所需要的

快速背景:我使用Enter事件为焦点字段设置帮助文本。因此,每次用户输入一个字段时,我都会有一个帮助文本框,其中会填充帮助文本

我无法共享工作簿。

假设您的userform(Userform1)如下所示

我将演示两个控件的
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:the
cls
文件;看起来它本质上是一个类。该代码不能放在
模块中吗?我有点不愿意依赖工作簿之外的文件,因为此工作簿正在全球范围内使用,这意味着每当有人想要使用该文件时,他们也必须拥有
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