Search code examples
excelvbacomboboxuserform

Adding item in combobox when combobox is created on click event


I am trying to add items in comboBox. I know how to do this, with myBox.AddItem "words" However I have an issue to implement this to my code as I create the comboBox on click event :

Private Sub CommandButton2_Click()
    Dim editBox As MSForms.Control
    Dim testBox As ComboBox
    Static i
    Set editBox = Me.Controls.Add("Forms.ComboBox.1")
    i = i + 1
    With editBox
        .Name = "cmBox" & i
        .Top = i * editBox.Height + 10
        .Left = 130
    End With
End Sub

Do you have any suggestions ? Thank you


Solution

  • Assuming the items are known at the time you're creating the controls, ...you can do that in the handler directly. Just set testBox to your editBox reference:

    Set testBox = editBox 'basically cast from MSForms.Control to MSForms.ComboBox
    testBox.Add "test1"
    testBox.Add "test2"
    

    On the other hand, if the items are not known at the time you're creating the controls, you have a problem:

    Dim testBox As ComboBox
    

    The object is locally-scoped, and goes out of scope as soon as the click handler exits.

    You need to hold on to it. Move that declaration to module-level (and qualify it, for consistency):

    Private testBox As MSForms.ComboBox
    

    Then you can invoke testBox.Add.... the problem is that you're going to be adding more than one control, so you can't just have one field like this. Have a Collection instead:

    Private dynamicControls As Collection
    
    Private Sub UserForm_Initialize()
        Set dynamicControls = New Collection
    End Sub
    

    Now when you create a dynamic control, add it to the collection with a key:

    Set editBox = Me.Controls.Add("Forms.ComboBox.1")
    '...
    dynamicControls.Add editBox, editBox.Name
    

    If you need to handle events for these dynamic controls, you'll need a different setup though, with an instance of a custom class for each dynamic control:

    'Class1
    Option Explicit
    Private WithEvents box As MSForms.ComboBox
    
    Private Sub box_Change()
        '...
    End Sub
    
    Public Property Get Control() As MSForms.ComboBox
        Set Control = box
    End Property
    
    Public Property Set Control(ByVal value As MSForms.ComboBox)
        Set box = value
    End Property
    

    Then when you create a dynamic control, you add it to a new instance of that class instead:

    Set editBox = Me.Controls.Add("Forms.ComboBox.1")
    '...
    Dim dynamicHandler As Class1
    Set dynamicHandler = New Class1 'todo rename that class
    Set dynamicHandler.Control = editBox
    dynamicControls.Add dynamicHandler, editBox.Name
    

    Now when you're ready to add items to a given box, retrieve the control from the dynamicControls collection:

    With dynamicControls("cmBox1")
        .Add "test1"
        .Add "test2"
    End With