提问人:BiGXERO 提问时间:5/15/2012 最后编辑:ashleedawgBiGXERO 更新时间:6/28/2018 访问量:29644
将事件处理程序分配给在 VBA 中动态创建的用户窗体上的控件
Assign event handlers to controls on user form created dynamically in VBA
问:
我在互联网上找到了很多资源,它们几乎可以做我想做的事情,但不完全是。我有一个命名的范围“日列表”。对于 dayList 中的每一天,我想在用户窗体上创建一个按钮,该按钮将运行当天的宏。我能够动态添加按钮,但不知道如何将daycell.text从命名范围传递到按钮,传递到事件处理程序,传递到宏:S 这是我必须创建用户表单的代码:
Sub addLabel()
ReadingsLauncher.Show vbModeless
Dim theLabel As Object
Dim labelCounter As Long
Dim daycell As Range
Dim btn As CommandButton
Dim btnCaption As String
For Each daycell In Range("daylist")
btnCaption = daycell.Text
Set theLabel = ReadingsLauncher.Controls.Add("Forms.Label.1", btnCaption, True)
With theLabel
.Caption = btnCaption
.Left = 10
.Width = 50
.Top = 20 * labelCounter
End With
Set btn = ReadingsLauncher.Controls.Add("Forms.CommandButton.1", "runButton", True)
With btn
.Caption = "Run Macro for " & btnCaption
.Left = 80
.Width = 80
.Top = 20 * labelCounter
' .OnAction = "btnPressed"
End With
labelCounter = labelCounter + 1
Next daycell
End Sub
为了解决上述问题,我目前提示用户输入他们想要运行的日期(例如 Day1)并将其传递给宏,它可以工作:
Sub B45runJoinTransactionAndFMMS()
loadDayNumber = InputBox("Please type the day you would like to load:", Title:="Enter Day", Default:="Day1")
Call JoinTransactionAndFMMS(loadDayNumber)
End Sub
Sub JoinTransactionAndFMMS(loadDayNumber As String)
xDayNumber = loadDayNumber
Sheets(xDayNumber).Activate
-Do stuff
End Sub
因此,对于我的每个 runButtons,它都需要显示 daycell.text,并运行一个宏,该宏使用相同的文本作为参数来选择要执行其操作的工作表。
任何帮助都会很棒。我看到了动态编写 vba 代码来处理宏的响应,但我相信一定有某种方式可以通过传递参数更优雅地完成,只是不确定如何。提前非常感谢!
答:
在工作表上捕获点击的示例。将其放在工作表模块中:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' e.g., range(A1:E1) is clicked
If Not Application.Intersect(Target, Range("A1:E1")) Is Nothing Then
MsgBox "You clicked " & Target.Address
End If
End Sub
评论
cells(dayCell, 6
Sub intersectCallingMacro() Range("D8").Select 'used for testing only Set target = ActiveCell If Not Application.Intersect(target, Range("A1:M100")) Is Nothing Then Call testIntersect(ActiveCell.Value) End If End Sub Sub testIntersect(dayString As String) Dim xDayString As String xDayString = dayString Sheets(xDayString).Activate End Sub
我知道您现在已经接受了适合您的解决方案,并且比下面的解决方案简单得多,但如果您有兴趣,这将是您问题的更直接的答案。
您需要创建一个类来处理按钮单击,因此每次单击按钮时,它都会使用类中的事件,您只需要执行此操作一次,然后为每个按钮创建一个新实例。为了防止这些类超出范围并丢失,它们需要存储在类级声明中。在下面,我稍微移动了您的代码。
在类模块中(我称之为 cButtonHandler)
Public WithEvents btn As MSForms.CommandButton
Private Sub btn_Click()
MsgBox btn.Caption
End Sub
使用“事件”,因为它允许您将大多数事件用于控件。我已将按钮生成代码移动到用户窗体中,如下所示:
Dim collBtns As Collection
Private Sub UserForm_Initialize()
Dim theLabel As Object
Dim labelCounter As Long
Dim daycell As Range
Dim btn As CommandButton
Dim btnCaption As String
'Create a variable of our events class
Dim btnH As cButtonHandler
'Create a new collection to hold the classes
Set collBtns = New Collection
For Each daycell In Range("daylist")
btnCaption = daycell.Text
Set theLabel = ReadingsLauncher.Controls.Add("Forms.Label.1", btnCaption, True)
With theLabel
.Caption = btnCaption
.Left = 10
.Width = 50
.Top = 20 * labelCounter
End With
Set btn = ReadingsLauncher.Controls.Add("Forms.CommandButton.1", "runButton", True)
With btn
.Caption = "Run Macro for " & btnCaption
.Left = 80
.Width = 80
.Top = 20 * labelCounter
'Create a new instance of our events class
Set btnH = New cButtonHandler
'Set the button we have created as the button in the class
Set btnH.btn = btn
'Add the class to the collection so it is not lost
'when this procedure finishes
collBtns.Add btnH
End With
labelCounter = labelCounter + 1
Next daycell
End Sub
然后,我们可以从一个单独的例程中调用 useform:
Sub addLabel()
ReadingsLauncher.Show vbModeless
End Sub
许多 VBA 书籍中都没有特别详细地介绍 VBA 中的类(通常您需要阅读 VB6 书籍才能理解),但是一旦您了解了它们以及它们的工作原理,它们就会变得非常有用:)
希望这会有所帮助
编辑 - 解决其他查询
若要引用集合中的对象,可以通过键或索引来完成。若要使用密钥,需要在将项添加到集合时添加它,因此:
collBtns.Add btnH
会变成
collBtns.Add btnH, btnCaption
因此,密钥必须是唯一的。然后,您可以参考如下:
'We refer to objects in a collection via the collection's key
'Or by it's place in the collection
'So either:
MsgBox collBtns("Monday").btn.Caption
'or:
MsgBox collBtns(1).btn.Caption
'We can then access it's properties and methods
'N.B you won't get any intellisense
collBtns("Monday").btn.Enabled = False
如果需要,您还可以向类添加其他属性/方法,例如:
Public WithEvents btn As MSForms.CommandButton
Private Sub btn_Click()
MsgBox btn.Caption
End Sub
Public Property Let Enabled(value As Boolean)
btn.Enabled = value
End Property
然后将访问:
collBtns("Monday").Enabled = False
这有帮助吗?为了进一步阅读,我会向你指出 Chip Pearson 的网站,他在大多数主题上都有很棒的东西 http://www.cpearson.com/excel/Events.aspx
请记住,VBA 是基于 VB6 的,因此不是一个成熟的 OO 语言,例如,它不支持正常意义上的继承,只支持接口继承
希望这对:)有所帮助
评论
daylist