i am trying to have VBA create a user form and based off of what selection you choose populate more selections.
the following code is my initial user form and i have it adding Comboboxes Based on whatever selection is chosen.
Private Sub UserForm_Initialize()
ComboBox1.AddItem "Selection1"
ComboBox1.AddItem "Selection2"
ComboBox1.AddItem "Selection3"
ComboBox1.FontSize = 13
End Sub
But i have it going to comboboxchange to do so
Private Sub ComboBox1_Change()
'Here i have some Working Code That Adds another ComboBox
Dim MsgType As Control
Set MsgType = UserForm2.Controls.Add("Forms.ComboBox.1")
With MsgType
.Height = 25
.Width = 300
.Top = 75
.Left = 20
.FontSize = 13
.Name = "vmtype"
.AddItem "Selection1"
.AddItem "Selection2"
Debug.Print .Value
End With
EndSub
I now need to have a private sub refer to this combo box just as "Private Sub ComboBox1_Change()" had. that way i can add more items depending on that selection.
What i have so far is the following.
Private Sub ComboBox2_Change()
Dim Notetype As String
Notetype = ComboBox1.Value
Debug.Print Notetype
End Sub
But it is not actually refering to the newly created Combo Box any idea how i can Fix this?
Use WithEvents to listen for dynamically added controls.
Here is a simple example where you are just adding a single control:
Private WithEvents vmtype As MSForms.ComboBox
Private Sub vmtype_Change()
Debug.Print MsgType
End Sub
Private Sub ComboBox1_Change()
Set vmtype = UserForm2.Controls.Add("Forms.ComboBox.1")
With vmtype
.Height = 25
.Width = 300
.Top = 75
.Left = 20
.FontSize = 13
.Name = "vmtype"
.AddItem "Selection1"
.AddItem "Selection2"
End With
End Sub
Consider using a custom class when adding many control. See my post: Responding to Events of Dynamically added Controls
Related
I add a new page in Multipage1 programmatically
Private Sub CommandButton3_Click()
Dim i As Integer
i = MultiPage1.Pages.Count
MultiPage1.Pages.Add.Caption = "Guarantee " & i
Then I would like my new page containing 3 ComboBoxes and the ComboBox1 will list the item in the table on my worksheet name "LeftTB", here is the code.
For r = 1 To 3
Set myCB = MultiPage1.Pages(i).Controls.Add("Forms.ComboBox.1", "ComboBox" & r, 1)
With myCB
.Width = 150
.Height = 18
Select Case r
Case Is = 1
.Left = 54
.Top = 156
'add item to combobox1
Dim rng, cl As Range
'LeftTB is the name of Table contain Data
Set rng = Range("LeftTB")
For Each cl In rng
.AddItem cl.Value
Next cl
Case Is = 2
.Left = 252
.Top = 156
Case Is = 3
.Left = 54
.Top = 180
End Select
End With
Next r
End Sub
It works fine to add value in ComboBox1 by this code. For the item in ComboBox 2, it depends on the value of the ComboBox1 as the code below.
Private Sub ComboBox1_Change()
Dim rng, cl As Range
'The CenterTB is the table in my worksheet with two columns. The first column (SubD) contains the same data as table "LeftTB" and the next column is the item I would like to add to ComboBox2
Set rng = Range("CenterTB[SubD]")
For i = 1 to me.MultiPage1.Pages.Count
me.MultiPage1.Pages(i).Controls("ComboBox2").Clear
For Each cl In rng
If cl.Value = me.MultiPage1.Pages(i).Controls("ComboBox1").Text Then
me.MultiPage1.Pages(i).Controls("ComboBox2").AddItem cl.Offset(0, 1).Value
End If
Next cl
Next i
End Sub
However, it does not work when ComboBox1 is programmatic. I have no idea to detect the change procedure of Combobox1 when it is programmatic.
Can someone provide me the solution?
When creating controls on the fly, VBA does not automatically create their Events!
There are two ways to do that. To create a events wrapper class, or simpler, in case of a known number of controls to be added (your case) to previously declare the controls in a specific way:
Put the next declaration on top of the form code module (in the declarations area):
Option Explicit
Private WithEvents ComboBox1 As MSForms.ComboBox
Private WithEvents ComboBox2 As MSForms.ComboBox 'possible to use its events, too
Private WithEvents ComboBox3 As MSForms.ComboBox 'possible to use its events, too
Then you should adapt your code, in a way to set the above declared variables as what you want/need them to be. So, please adapt your code in the next way:
Private Sub btCreateCmb_Click()
Dim myCB As MSForms.ComboBox, r As Long
For r = 1 To 3
Set myCB = MultiPage1.Pages(i).Controls.Add("Forms.ComboBox.1", "ComboBox" & r, 1)
With myCB
.Width = 150
.Height = 18
Select Case r
Case Is = 1
Set ComboBox1 = myCB 'added to Set your first combo
.Left = 54
.Top = 156
'add item to combobox1
Dim rng, cl As Range
'LeftTB is the name of Table contain Data
Set rng = Range("LeftTB")
For Each cl In rng
.AddItem cl.Value
Next cl
Case Is = 2
Set ComboBox2 = myCB 'added to Set your second combo
.Left = 252
.Top = 156
Case Is = 3
Set ComboBox3 = myCB 'added to Set your third combo
.Left = 54
.Top = 180
End Select
End With
Next r
End Sub
Only now, the combo events will be triggered (if their code exists in the form code module). Please, firstly use the next short code example:
Private Sub ComboBox1_Change()
MsgBox "Changed 1..."
End Sub
If you exactly followed the above suggestions, It should be surely triggered!
Now, you can put in its event code whatever you need...
Please, test it and send some feedback.
The following code will open a userform (examples) in which I have a commmandbutton which adds a new Combobox. I can name the combobox and can retrive the name in the immediate window, but I am unable to accecs the change command of the added combobox(es) or retrive the acces to their input.
In would like to do things upon change of this added combobox. I am able to do it for 1 box using the set "newgene1" = .... but than it on reclickit this first box will get lost.
Option Explicit
Dim Counter As Integer
Private WithEvents newgene1 As MSForms.ComboBox
Private WithEvents newgene2 As MSForms.ComboBox
Dim Generanger As Range
Private Sub UserForm_Initialize()
Set Generanger = ThisWorkbook.ActiveSheet.Range("A1", Range("A1").End(xlDown)) 'list of data
Generanger.Select
Counter = 1
cboGenelist.RowSource = Generanger.Address
End Sub
--------------------------------------------------------------------
Private Sub cboGenelist_Change()
MsgBox (cboGenelist.Text)
End Sub
--------------------------------------------------------------------
Private Sub cmdAddgene_Click()
UserForm1.Height = UserForm1.Height + 20
UserForm1.Controls.Add("Forms.comboBox.1", "newgene" & Counter) = "select"
With Me.Controls("newgene" & Counter)
.Left = 20
.Top = UserForm1.Height - 50
.RowSource = Generanger.Address
.Font.Name = "Trebuchet MS"
.Font.Size = 12
End With
Debug.Print Me.Controls("newgene" & Counter).Name
Counter = Counter + 1
End Sub
--------------------------------------------------------------------
Private Sub newgene1_Change()
MsgBox (newgene.Text)
End Sub
--------------------------------------------------------------------
Private Sub newgene2_Change()
MsgBox (newgene2.Text)
End Sub
recently I found a very useful article about “How to add Events to dynamically created Controls in Excel using VBA class module”. I tried it in my project and it worked perfectly for just one textbox at a time. Actually I have to create multiple textboxes dynamically using VBA "For Next Loop" and attach the same event to all of them explicitly. but only the last created textbox gets the event.
Would you please help?
userform:
Private Sub UserForm_Initialize()
' Create and add the textboxes.
Dim i As Integer
For i = 0 To 4
Set tbPin = Me.Controls.Add("Forms.TextBox.1")
With tbPin
.Top = 8 + (i * 20)
.Left = 10
.Width = 130
.Name = "thePin"
End With
Set objMyEventClass.tbEvents = tbPin ' Attach an event to the textbox.
Next
' Create and add the button control.
Dim btEx As MSForms.CommandButton
Set btEx = Me.Controls.Add("Forms.CommandButton.1")
With btEx
.Top = Me.Height - 60
.Left = 10
.Width = 130
.Height = 25
.Caption = "Submit"
End With
Set objMyEventClass.btEvents = btEx ' Attach at event to the button.
End Sub
class module:
Option Explicit
Public WithEvents tbEvents As MSForms.TextBox
Public WithEvents btEvents As MSForms.CommandButton
Private Sub tbEvents_Change()
If Len(UserForm1.tbPin) > 6 Then
MsgBox "Max 6 digits only"
With UserForm1.tbPin
.Text = ""
.SetFocus
End With
End If
End Sub
Private Sub btEvents_click()
If Trim(UserForm1.tbPin) <> "" Then
Call showMyPin(UserForm1.tbPin)
End If
End Sub
Private Sub showMyPin(pin As String)
MsgBox "You have entered " & pin
End Sub
I have a workbook with the following modules of code:
Class Module: clsComboBox
Option Explicit
Private WithEvents MyComboBox As MSForms.ComboBox
Public Property Set cmboControl(cmboBox As MSForms.ComboBox)
Set MyComboBox = cmboBox
End Property
Private Sub MyComboBox_Change()
If MyComboBox.Value = "2" Then
MsgBox "I will be so happy if this ever runs"
End If
End Sub
UserForm: UserForm1 (contains a single button, CommandButton1)
Option Explicit
Private Sub CommandButton1_Click()
Dim ctlcombobox As ComboBox
Dim clsobject As clsComboBox
Set ctlcombobox = Me.Controls.Add("Forms.ComboBox.1", "ComboBox1", True)
Set clsobject = New clsComboBox
Set clsobject.cmboControl = ctlcombobox
With ctlcombobox
.Top = 100
.Left = 5
.Width = 200
.Height = 25
.Visible = True
.List = Array("1", "2")
End With
End Sub
I am trying to overwrite the combobox_change event with every new combobox I create on the fly. However, the code is not working. When "2" is selected on the comboBox, nothing happens. What am I doing wrong?
example workbook:
https://www.dropbox.com/s/ctr51lote86fbox/test%20combo%20box.xlsm?dl=0
Edit
Thanks, Tim, for the answer. I did have to create a variable-length array to hold all of my comboboxes that I create on the fly in memory. (The original question was about a single combobox but in my actual worksheet, I am creating an unknown number at runtime).
Dim clsobject As clsComboBox
This needs to be a global variable: in your current code it goes out of scope as soon as CommandButton1_Click exits. It needs to persist if you want to capture later events.
Exactly as Tim says - just move that one line of code:
Option Explicit
Dim clsobject As clsComboBox
Private Sub CommandButton1_Click()
Dim ctlcombobox As ComboBox
Set ctlcombobox = Me.Controls.Add("Forms.ComboBox.1", "ComboBox1", True)
Set clsobject = New clsComboBox
Set clsobject.cmboControl = ctlcombobox
With ctlcombobox
.Top = 100
.Left = 5
.Width = 200
.Height = 25
.Visible = True
.List = Array("1", "2")
End With
End Sub
I have a listbox in a userform in Excel 2007.
Some cells in my worksheet contain more than 10 rows (data with ALT ENTER).
I'm trying to clean and display the data. I don't want to change the column width to 1000, but I'd like to use a mouseover box to show all the cell data.
Is there another idea that would work?
With mouse over would be possible to do it but it is complicated I think. Here I have another simpler idea: on double click in list box a multi line text box with selected list item(s) data will be shown. This text box has the same position and size as the list box. On the user form click text box hides. Here is some sample code, to test it you need form with list box named "ListBox1":
Option Explicit
Public ListItemInfo As Control
Private Sub UserForm_Initialize()
Set ListItemInfo = Me.Controls.Add("Forms.TextBox.1", "ListItemInfo", False)
With Me.ListItemInfo
.Top = Me.ListBox1.Top
.Left = Me.ListBox1.Left
.Width = Me.ListBox1.Width
.Height = Me.ListBox1.Height
.MultiLine = True
End With
End Sub
Private Sub ListBox1_Change()
Me.ListItemInfo.text = GetSelectedItemsText
End Sub
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
SwitchListItemInfo
End Sub
Private Sub UserForm_Click()
SwitchListItemInfo
End Sub
Private Function GetSelectedItemsText() As String
Dim text As String
Dim i As Integer
For i = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(i) Then
text = text & Me.ListBox1.List(i) & vbNewLine
End If
Next i
GetSelectedItemsText = text
End Function
Private Sub SwitchListItemInfo()
If Me.ListItemInfo.text = "" Then Exit Sub
Me.ListItemInfo.Visible = Not Me.ListItemInfo.Visible
Me.ListBox1.Visible = Not Me.ListBox1.Visible
End Sub