我在表单上有一堆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()
个潜艇吗?
答案 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对象和关联以及您需要的事件的对象。因此,您可以完全避免任何代码存根。
Custom Class
以绑定Button和TextBox对。 WithEvents
。Public
中添加Standard Module
例程,通过跨越表单控件来初始化Collection
个Custom Class
个对象。您还可以将此控件Add
以编程方式用作'reBuild'选项。 Collection可以在包含所有管理例程的另一个类模块中,但需要在Standard Module
中进行实例化和加载。您需要记住,每次添加控件时,表单的模块都会重新编译,因此您必须小心放置代码。
我的应用程序直接在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])
等...