Вы находитесь на странице: 1из 4

In this article, you will find code for adding new controls to excel userfom, for adding

items to comboboxes and to create an array of values from a range of cells.

There are many situations that requires a dynamic userform, to add new comboboxes,
textboxes as other controls. The challenge is to control the position of the new controls, and
relocate the existing controls, to avoid overlappings.

Let's take a look at both situations: in first image, there are no extra controls in form, in the
second image, i added 2 extra lines, each line contains 3 controls (2 comboboxes and a
textbox):

Single Condition

Multiple Conditions

I am a fan of Excel Defined Tables, so this example contains 3 sheets, each with it's own
defined table.

For automation purposes, to make the code shorter and flexible, each table name is identical
to sheet name.

The scenario for building the form is simple: i have 3 tables, i need to be able to search in one
or more columns of the table from the selected worksheet. By default, the form will have
controls for a single condition (where a condition contains a combo for Column Name,
another combo to select from criterias like "start with", "contains", and a textbox with the
value to search for.)
The Add Condition button from form will add another set of controls, to set a new condition
for filtering the table.

Important note:
The code for applying filters is basic, just for demo purposes, you cannot apply more than 1
criteria for the same column; if you apply more than 1 criteria for the same column, only the
last criteria will be applied. The filter can apply multiple conditions to different columns
only!

Before explaining the code, you can download the workbook:

Download sample file: Add New Controls to


UserForm.xlsm
The code for adding new controls to the userform used in
this demo workbook:
Private Sub AddButton_Click()
Dim NextTopValue As Double, SpaceBetween As Double
Dim NewTextBox As MSForms.TextBox, NewCombo1 As ComboBox, NewCombo2 As
ComboBox

SpaceBetween = 6 'set the space between lines


NextTopValue = AddCondition1.Height + SpaceBetween

Me.Height = Me.Height + NextTopValue 'increase the height of the form


with default control height plus the space height
ResetButton.Visible = True 'we can display the reset button, this way
you can reload the default form

'move down these 2 buttons, otherwise the new controls will be placed
over them:
Generate.Top = Generate.Top + NextTopValue
CancelReport.Top = CancelReport.Top + NextTopValue

'add combo for the new condition table headers:


Set NewCombo1 = Me.Controls.Add("Forms.ComboBox.1", "AddCondition" &
(NewSet), True)
With NewCombo1
.Top = AddCondition1.Top + NextTopValue * (NewSet - 1)
.Left = AddCondition1.Left
.Width = AddCondition1.Width
.Height = AddCondition1.Height
.MatchRequired = True
End With
FillCombo NewCombo1, ArrCells 'fill combo with table headers

'add combo for the new condition criterias:


Set NewCombo2 = Me.Controls.Add("Forms.ComboBox.1", "Criteria" &
(NewSet), True)
With NewCombo2
.Top = Criteria1.Top + NextTopValue * (NewSet - 1)
.Left = Criteria1.Left
.Width = Criteria1.Width
.Height = Criteria1.Height
.MatchRequired = True
End With
FillCombo NewCombo2, Arr 'fill combo with criterias

'add a textbox for the new condition search value:


Set NewTextBox = Me.Controls.Add("Forms.TextBox.1", "Val" & (NewSet),
True)
With NewTextBox
.Top = Val1.Top + NextTopValue * (NewSet - 1)
.Left = Val1.Left
.Width = Val1.Width
.Height = Val1.Height
End With

'increase the NewSet number for the next line


NewSet = NewSet + 1
End Sub

The code is fairly simple, the .Top value for each new control is calculated based on the
NewSet number and the .Top value of the default control. Because we already have a default
condition line 1, the form will be initialized with NewSet value set to 2.

Because we have 3 tables, when you select another worksheet in userform, the column names
of that sheet table will be filled in all Field combos, using a simple procedure, that will extract
all column names from the table and add them to the field combos.

The selection of Worksheet is monitored by that combo's _Change event, which will activate
the selected sheet, and also will change all header names from Field combos:

Private Sub ComboBox1_Change()


Dim Ctl As Control, Cell As Range, i As Integer
On Error Resume Next

Application.Goto Worksheets(ComboBox1.Text).Cells(1, 1)
ClearFilters_Click
ReDim ArrCells(1 To
Worksheets(ComboBox1.Text).ListObjects(ComboBox1.Text).HeaderRowRange.Colum
ns.Count)
i = 1

For Each Cell In


Worksheets(ComboBox1.Text).ListObjects(ComboBox1.Text).HeaderRowRange
ArrCells(i) = Cell
i = i + 1
Next Cell

For Each Ctl In Me.Controls


If Ctl.Name Like "AddCondition*" Then FillCombo Ctl, ArrCells
Next

On Error GoTo 0
End Sub

The array created will be passed to the next procedure, that will add all items to ALL combos
with a name similar to "AddCondition*".
Private Sub FillCombo(CBox As ComboBox, Values As Variant)
CBox.Clear
Dim i As Integer
For i = LBound(Values) To UBound(Values)
CBox.AddItem Values(i)
Next
CBox.ListIndex = 0 'display the first item
End Sub

This procedure accepts an array of values to be added for the specified combo, the
comboboxes will display the first item.

Using defined tables will eliminate the problem of locating headers row in each sheet, your
tables can be located anywhere in sheet, this is only one of the many advantages of working
with tables.

I will definitely write more about tables, there are lots of amazing things that can be done
using defined tables...

Have fun :)

Вам также может понравиться