VBA许多按钮指向相同的_Click子

时间:2011-02-01 09:11:55

标签: excel vba

我在表单上有一堆TextBox-Button对。单击按钮时,我想将文本框的值插入数据库。名称TextBoxes和Buttons遵循命名标准,例如Value1Tb - Value1Cmd和Value2Tb - Value2Cmd。

我的问题是,因为我想为每个按钮做同样的事情,我希望有可能写一个Sub像:

Private Sub AnyButton_Click(sender As CommandButton)
  Dim tb As TextBox
  Set tb = GetTBByName(s.Name)
  PutValueToDatabase(s.Name,tb.Text)
End Sub

但我找不到将Button的Click-event指向与标准Name_Click()不同的子的方法。

任何人都知道解决这个问题的方法,这不涉及我写50个左右的Name_Click()个潜艇吗?

6 个答案:

答案 0 :(得分:5)

如果您可以使用表单控件而不是ActiveX,因为看起来好像您可能正在使用它,那么Chris的解决方案似乎很好。

但是,如果你需要ActiveX CommandButtons,那么你就无法(因为VBA编译器会告诉你,“程序声明不匹配......”)在click事件的回调中有参数,你无法提高来自多个对象的事件,虽然你当然知道哪个按钮引发了事件(因为关系是1 CommandButton = 1 Sub)。

所以...我会选择类似的东西:

Private Sub Value1Cmd_Click()
    Call TheMethod(Value1Cmd)
End Sub    

Private Sub Value2Cmd_Click()
    Call TheMethod(Value2Cmd)
End Sub


Private Sub TheRealMethod(sender As CommandButton)
    ' Do your thing '
    Dim tb As TextBox
    Set tb = GetTBByName(s.Name)
    PutValueToDatabase(s.Name,tb.Text)
    ' Etcetera... '
End Sub

每个按钮需要一个存根,所以一些复制和粘贴开始,但随后很容易维护,因为所有_Click事件回调都指向相同的方法......

编辑: E.g。

Sub AutoWriteTheStubs()
    Dim theStubs As String
    Dim i As Long
    For i = 1 To 10
        theStubs = theStubs & "Private Sub Value" & CStr(i) & "Cmd_Click()" & vbCrLf _
                   & "    Call TheMethod(Value" & CStr(i) & "Cmd)" & vbCrLf _
                   & "End Sub" & vbCrLf & vbCrLf
    Next i
    Debug.Print theStubs
End Sub

答案 1 :(得分:2)

似乎你想要的是获得点击按钮的名称。如果您要创建这样的按钮:

(其中'i'在循环中递增)

Set btn = Sheet1.Buttons.Add( , , , ,)
With btn
  .OnAction = "btnSub"
  .Caption = "Upadate"
  .Name = "btn" & CStr(i) & "Cmd"
End With

然后为所有按钮定义通用的“private sub btnSub()”,您至少可以获得使用Application.Caller单击的按钮的名称。类似的东西:

Private Sub btnSub()
    Dim ButtonName As String
    ButtonName = Application.Caller
    MsgBox ("Hello:" & ButtonName)
End Sub

希望它有所帮助!

答案 2 :(得分:1)

我有同样的情况,我只是为每个按钮都有一个click事件,它是我想要调用的函数的包装器。如果需要,这还允许您传递特定于工作表的参数。

示例:

Public Sub StoreButton_Click()

' Store values for transaction sheet 3/27/09 ljr

Call StoreTransValues(ActiveSheet)

End Sub

答案 3 :(得分:1)

我决定做出这个答案,因为我正在做类似的事情,我确认它有效。

您可以将OLEobjects存储在任意大小的Collection中,其中包含Custom Class个包含OLE对象和关联以及您需要的事件的对象。因此,您可以完全避免任何代码存根。

  1. 创建Custom Class以绑定Button和TextBox对。
  2. 声明Button对象WithEvents
  3. 在类模块中的公开按钮事件处理程序中包含您的回调。
  4. Public中添加Standard Module例程,通过跨越表单控件来初始化CollectionCustom Class个对象。您还可以将此控件Add以编程方式用作'reBuild'选项。 Collection可以在包含所有管理例程的另一个类模块中,但需要在Standard Module中进行实例化和加载。
  5. 在标准模块中放置一个公共例程,以接收您需要的任何上下文的回调。如果它可以实现更好的封装,那么这也可以在工作表模块中。您可以使用后期绑定来引用回调或CallByName。
  6. 您需要记住,每次添加控件时,表单的模块都会重新编译,因此您必须小心放置代码。

    我的应用程序直接在Worksheet Surface上有控件,所以我不能将Collection Class放入,或者从Worksheet模块中获取Collection的任何初始化。这相当于自我修改代码,并且它会擅长停止。

    我通过血腥的理想主义(不一定是好事)梦想着这个想法,但是,当然,我不是第一个想到它的人,因为你可以看到here。 @Tim Williams在他的回答中解释道。你也可以谷歌VBA控制阵列事件看到很多类似的例子,包括@SiddharthRout的优秀article。与VB6类比,他使用Array代替Collection来获得相同的结果。

    我稍后会尝试发布一些代码。我的应用程序有点不同,所以需要做很多工作才能减少它,但原理是一样的。

    要记住的另一件事是VBE真的很难与这种类型的东西挣扎,所以不要担心它是否会加载你的处理器。重新启动VBE后,一切都会好的。

答案 4 :(得分:-1)

我刚刚发布了(开源)Event Centralizer for MSForms

引用:" MSForms的Event Centralizer是一个VBA编程工具,在为UserForms中发生的事件编写处理程序时允许进行各种自定义分组。

使用适用于MSForms的Event Centralizer,可以很容易地让所有TextBox在Enter事件发生时以相同的方式作出反应,或者除了一个之外的所有文本框或只有具有特定Tag值的那些反应。

由于其事件日志系统,MSForms的Event Centralizer是一个强大的学习和调试帮助。"

我无法在这里解释它是如何工作的。我尝试在site上进行。

答案 5 :(得分:-2)

将事件设置为=FunctionName(parameter)

有点晚了,但这可能有助于其他人:

如果你有一个名为OpenDocumentById(docID as integer)的函数,那么调用该函数的每个控件都将具有以下内容:

cmd1' on点击事件:

=OpenDocumentById([DocID])

cmd2' on点击事件:

=OpenDocumentById([DocID])

等...