VBA许多button指向相同的_Click子

我在窗体上有一堆TextBox-Button对。 当button被点击时,我想插入文本框的值到数据库中。 名称文本框和button遵循一个命名标准,例如Value1Tb-Value1Cmd和Value2Tb-Value2Cmd。

我的问题是,因为我想要为每个button做同样的事情,所以我希望可以写一个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事件指向与标准Name_Click()不同的子部分。

有人知道这个方法,这不涉及我写50左右不同的Name_Click()潜艇?

如果你可以使用表单控件而不是ActiveX,因为看起来好像你现在可能在那个时候,那么Chris的解决scheme似乎很好。

但是,如果您需要ActiveX CommandButtons,则无法(如VBA编译器会告诉您的“过程声明不匹配…”)在click事件的callback中包含参数,并且无法将事件从虽然你当然知道哪个button引发了事件(因为关系是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 

需要为每个button存根,所以一些复制和粘贴开始,但易于维护等,因为所有的_Click事件callback指向相同的方法…

编辑:例如

 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 

看来你想要的是获得点击button的名称。 如果你正在创build这样的button:

(其中'我'在循环中增加)

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

然后为所有的button定义一个通用的“private sub btnSub()”,你至less可以得到使用Application.Caller单击的button的名称。 就像是:

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

希望能帮助到你!

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

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

  1. 创build一个Custom Class来绑定Button和TextBox对。
  2. 用事件声明Button对象。
  3. 将您的callback包括在Class模块中暴露的button事件处理程序中。
  4. 将一个Public例程放在一个Standard Module ,通过跨越表单控件来初始化这些Custom Class对象的一个Collection 。 您也可以使用它来以编程方式Add控件作为“reBuild”选项。 Collection可以在所有pipe理例程中位于另一个Class Module中,但需要实例化并加载到Standard Module
  5. 把一个公共例程放在一个标准模块中,用你需要的任何上下文来接收callback。 这也可以在工作表模块,如果它使更好的封装。 您可以使用后期绑定来引用callback或CallByName。

您需要记住,每次添加控件时,表单模块都会重新编译,所以在放置代码时必须小心。

我的应用程序直接在Worksheet表面上有控件,所以我不能把Collection类放进去,或者从Worksheet模块获取Collection的任何初始化。 这将相当于自我修改的代码,它研究卓越停下来。

我通过stream血的理想主义(不一定是件好事)梦见了这个想法,当然,我不是第一个想到的人,因为你可以看到这里 。 @Tim Williams在他的回答中解释了这一点。 您也可以谷歌VBA控制arrays事件看到很多类似的例子,包括由@SiddharthRout 一篇优秀的文章 。 根据VB6的比喻,他使用一个Array而不是一个Collection来实现相同的结果。

我会稍后尝试发布一些代码。 我的应用程序有点不同,所以需要大量的工作来削减它,但原理是一样的。

另外要记住的是,VBE真的与这种types的事情斗争,所以不要担心,如果它加载你的处理器。 VBEclosures后重新开始,一切都会好起来的。

我有这样的情况,我只是有一个点击事件的每个button是封装到我想要调用的函数。 这也允许您在需要时传递特定于表单的参数。

例:

 Public Sub StoreButton_Click() ' Store values for transaction sheet 3/27/09 ljr Call StoreTransValues(ActiveSheet) End Sub 

我刚发布(开源) MSForms的事件集中器 。

引文:“MSForms的事件集中器是一个VBA编程工具,它允许在编写用户窗体中发生的事件的处理程序时进行各种自定义分组。

使用MSForms的事件集中器,很容易让所有的TextBox在Enter事件发生时或者除了一个之外的所有文本框都起同样的作用,或者只有具有特定Tag值的那些。

由于它的事件日志系统,MSForms事件集中器是一个强大的学习和debugging帮助。“

这里我不能解释它是如何工作的。 我试图在网站上做到这一点。

将事件设置为=FunctionName(parameter)

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

如果您有一个名为OpenDocumentById(docID as integer)的函数,则调用该函数的每个控件都将在事件中包含以下内容:

cmd1的点击事件:

 =OpenDocumentById([DocID]) 

cmd2的点击事件:

 =OpenDocumentById([DocID]) 

等等…