Actions for multiple similar dynamically created command buttons

后端 未结 1 1475
半阙折子戏
半阙折子戏 2021-01-24 23:05

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 undern

相关标签:
1条回答
  • 2021-01-24 23:34

    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.

    0 讨论(0)
提交回复
热议问题