Actions for multiple similar dynamically created command buttons

爱⌒轻易说出口 提交于 2019-12-14 03:59:32

问题


I am writing a program in Excel VBA that will basically start with one textbox and one command button, and the command button will create a new textbox and command button underneath it, and that command button will in turn create a new textbox and command button, and so on. Hope you followed that mess.

I can create the initial button no problem (it has to be dynamically created so it has the opportunity to be deleted later). My problem is then with creating the click() event handler. I need all the click() events to do the same thing, but name the new Objects relative to its own name. This is all blowing my mind, I would really appreciate a little help.

Feel free to ask for specific information, but I haven't really been able to wrap my head around the topic well enough to write some test code yet.


回答1:


Create a custom class module called CEventClass (Insert - Class Module, F4 to change the name). Type this code into the class module

'These are declared WithEvents so the events are
'exposed to us
Public WithEvents cmdEvent As MSForms.CommandButton
Public WithEvents tbxEvent As MSForms.TextBox


'This will fire for any control
'assigned to cmdEvent
Private Sub cmdEvent_Click()

    MsgBox cmdEvent.Caption

End Sub

'This will fire for any control
'assigned to tbxEvent
Private Sub tbxEvent_Change()

    If Len(tbxEvent.Text) < 6 Then
        tbxEvent.BackColor = vbYellow
    Else
        tbxEvent.BackColor = vbWhite
    End If

End Sub

Now create a Userform with no controls on it. Put this code in the form's code module

'These will keep the class instances in
'scope for as long as the form is loaded
Private mEventButtons As Collection
Private mEventTexts As Collection

Private Sub UserForm_Initialize()

    Dim cmd As MSForms.CommandButton
    Dim txt As MSForms.TextBox
    Dim clsEventClass As CEventClass

    Set mEventButtons = New Collection
    Set mEventTexts = New Collection

    'Create two commandbuttons
    Set cmd = Me.Controls.Add("Forms.CommandButton.1", "FirstName")
    cmd.Top = 10
    cmd.Left = 10
    cmd.Caption = "First"
    'Create a new instance of CEventClass and
    'assign the button to cmdEvent
    Set clsEventClass = New CEventClass
    Set clsEventClass.cmdEvent = cmd
    mEventButtons.Add clsEventClass

    Set cmd = Me.Controls.Add("Forms.CommandButton.1", "SecondName")
    cmd.Top = 50
    cmd.Left = 10
    cmd.Caption = "Second"
    Set clsEventClass = New CEventClass
    Set clsEventClass.cmdEvent = cmd
    mEventButtons.Add clsEventClass

    'Create two textboxes and assign them to new instances
    'of the class
    Set txt = Me.Controls.Add("Forms.TextBox.1", "ThirdName")
    txt.Top = 10
    txt.Left = 150
    Set clsEventClass = New CEventClass
    Set clsEventClass.tbxEvent = txt
    mEventTexts.Add clsEventClass

    Set txt = Me.Controls.Add("Forms.TextBox.1", "FourthName")
    txt.Top = 50
    txt.Left = 150
    Set clsEventClass = New CEventClass
    Set clsEventClass.tbxEvent = txt
    mEventTexts.Add clsEventClass

End Sub

Now when you run the form, those two events will fire if you click/change the control.

You may note that there is no AfterUpdate event for the textbox. That event is not actually a textbox event, but an event of the control container for the textbox, so you can't expose it this way. That's one reason I prefer to create all the controls at design time and hide or unhide them as needed. I still might use WithEvents for some controls just so I don't have to repeat code so much. But for things like TextBox_AfterUpdate, I just create all the event procedures at design time.

Update:

If you want the event to create new buttons, you have to do a couple more things. First, you have to expose the collection outside of the userform. You add this to your Userform module

Public Property Get EventButtons() As Collection
    Set EventButtons = mEventButtons
End Property

Then you change your commandbutton event code to create a new button

Private Sub cmdEvent_Click()

    Dim cmd As MSForms.CommandButton
    Dim clsEventClass As CEventClass

    Set cmd = cmdEvent.Parent.Controls.Add("Forms.CommandButton.1", cmdEvent.Caption & "1")
    cmd.Top = cmdEvent.Top + 40
    cmd.Left = cmdEvent.Left
    cmd.Caption = cmdEvent.Caption & "1"
    Set clsEventClass = New CEventClass
    Set clsEventClass.cmdEvent = cmd
    cmdEvent.Parent.EventButtons.Add clsEventClass

End Sub

This creates a new button 40 points below whichever was clicked. You don't say what your logic is for naming or positioning, so I assume you can work that out. Use cmdEvent.Parent to get a reference to the Userform.



来源:https://stackoverflow.com/questions/24558214/actions-for-multiple-similar-dynamically-created-command-buttons

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!