I would like to save the ComboBox1 & ComboBox2 values as variables which I could use in the module I return to once the Userform is correctly completed by the user however I am unsure how to do this.
Option Explicit
Private isCancelled As Boolean
Public Property Get Cancelled() As Boolean
Cancelled = isCancelled
End Property
Private Sub CancelButton1_Click()
isCancelled = True
Me.Hide
End Sub
Public Property Get Benefit() As String
Benefit = IIf(Me.ComboBox1.ListIndex = -1, vbNullString, Me.ComboBox1.Text)
End Property
Public Property Get Costdelivery() As String
Costdelivery = IIf(Me.ComboBox2.ListIndex = -1, vbNullString, Me.ComboBox2.Text)
End Property
Private Sub ComboBox1_Change()
ValidateForm
End Sub
Private Sub ComboBox2_Change()
ValidateForm
End Sub
Private Sub ValidateForm()
Me.Okbutton1.Enabled = (Benefit <> vbNullString And Costdelivery <> vbNullString)
End Sub
Private Sub UserForm_Activate()
ValidateForm
End Sub
Private Sub UserForm_Initialize()
'populate "Combo-Box with Boards
With Me.ComboBox1
.Clear ' clear previous items (not to have "doubles")
.AddItem "Very High"
.AddItem "High"
.AddItem "Medium"
.AddItem "Low"
End With
With Me.ComboBox2
.Clear ' clear previous items (not to have "doubles")
.AddItem "Very High"
.AddItem "High"
.AddItem "Medium"
.AddItem "Low"
End With
End Sub
Private Sub Okbutton1_Click()
Dim Ben As Long
Ben = Me.ComboBox1.Value ***ERROR
Dim Cost As Long
Cost = Me.ComboBox2.Value **** ERROR
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then
Cancel = True
isCancelled = True
Me.Hide
End If
End Sub
Ideally I would like to store the Low,Medium,High or Very high as values 9,10,11,12 as I will be using these as cell references in the module I return to after the userform is closed.
I understand I would need to state a public property my attempt which does not work is below;
Public Function ConfidenceChart()
Dim ben As Long, costd As Long
ben = UserForm4.ComboBox1.Text
If ben = "Low" Then ben = 9
If ben = "Medium" Then ben = 8
If ben = "High" Then ben = 7
If ben = "Very High" Then ben = 6
costd = UserForm4.ComboBox2.Text
If costd = "Low" Then costd = 12
If costd = "Medium" Then costd = 13
If costd = "High" Then costd = 14
If costd = "Very High" Then costd = 15
End Function
Excel controls allow you to link controls to cells. In this way, you can store the values of the controls for later use.
Userform controls use the ControlSource property to establish this link. In my Demo below I create two named ranges on a setting page (named after the controls' names for easy reference) and set the controls ControlSource property to the named range.
Addendum
#Mat'sMug pointed out that the OP needed to store a value from a lookup list base on the selection from a ComboBox. This can also be achieved using named ranges.
Private Sub UserForm_Initialize()
'populate "Combo-Box with Boards
With Me.ComboBox1
.RowSource = "List1"
.ColumnCount = 2
.ColumnWidths = "0 pt;49.95 pt"
End With
With Me.ComboBox2
.RowSource = "List2"
.ColumnCount = 2
.ColumnWidths = "0 pt;49.95 pt"
End With
End Sub
You will need to change some of the properties of the ComboBoxes.
Private Sub UserForm_Initialize()
'populate "Combo-Box with Boards
With Me.ComboBox1
.RowSource = "List1"
.ColumnCount = 2
.ColumnWidths = "0 pt;49.95 pt"
.ControlSource = "ComboBox1"
End With
With Me.ComboBox2
.RowSource = "List2"
.ColumnCount = 2
.ColumnWidths = "0 pt;49.95 pt"
.ControlSource = "ComboBox2"
End With
End Sub
Ben and Cost are locals, they're only visible from within the Click handler.
It's not the forms' job to know where these values need to end up - the form is only there to collect user input.
You already have Benefit and CostDelivery properties that the caller is able to access.
Use them!
With New UserForm1 'whatever the name of that form is
.Show
If Not .Cancelled Then
Sheet1.Range("A1").Value = .Benefits
Sheet1.Range("B1").Value = .CostDelivery
End If
End With
If you need them to be numeric values, then you're not populating your comboboxes correctly.
Nowhere you're mapping "Very High" to 12, the comboboxes only know about the strings.
To do that you need to change this:
With Me.ComboBox1
.Clear ' clear previous items (not to have "doubles")
.AddItem "Very High"
.AddItem "High"
.AddItem "Medium"
.AddItem "Low"
End With
And assign Me.ComboBox1.List to a 2D array. Or a Range, if you have one that looks like this:
A B
15 Very High
14 High
13 Medium
12 Low
You could have a this helper method:
Private Sub PopulateFromRange(ByVal control As MSForms.ComboBox, ByVal source As Range, Optional ByVal valueColumn As Long = 1, Optional ByVal hasHeader As Boolean = True)
With control
.ColumnCount = source.Columns.Count
.ColumnWidths = GetColumnWidths(source)
.ListWidth = IIf(control.Width > source.Width, control.Width, source.Width)
.List = source.Range(source.Rows(IIf(hasHeader, 2, 1)).EntireRow, source.Rows(source.Rows.Count).EntireRow).Value
.BoundColumn = valueColumn
End With
End Sub
Private Function GetColumnWidths(ByVal source As Range) As String
Dim cols As Long
cols = source.Columns.Count
Dim widths()
ReDim widths(1 To cols)
Dim col As Long
For col = 1 To cols
widths(col) = source(, col).Width
Next
GetColumnWidths = Join(widths, ",")
End Function
(taken from this post specifically about populating combobox and listbox controls from ranges)
And populate your comboboxes like this:
PopulateFromRange Me.ComboBox1, DataSheet.Range("A1:B5")
PopulateFromRange Me.ComboBox2, DataSheet.Range("D1:E5")
Assuming you have a DataSheet worksheet with ranges [A1:B5] and [D1:E5] respectively containing the text and corresponding numeric value for each item.
Related
I'm having trouble with combo box's specifically when a user clicks one of the options in the dropdown menu the text is entered into the document but if they made an error and select another option in the combo box it inputs the the text from both times (the error and right answer). How can I set it up so it will get rid of the text from the error.
The code is below:
Private Sub UserForm_Initialize()
With ComboBox1
.AddItem "F1"
.AddItem "G2"
.AddItem "R3"
.AddItem "G4"
End With
End Sub
Private Sub ComboBox1_Change()
Dim ComboBox1 As Range
Set ComboBox1 = Doc1.Bookmarks("bmc1").Range
ComboBox1.Text = Me.ComboBox1.Value
Set ComboBox1 = Doc2.Bookmarks("bmc1").Range
ComboBox1.Text = Me.ComboBox1.Value
End Sub
Your problem is that you are creating a new instance of the bookmark bmc1 every time you call the Change() function, and so a new bookmark is created, and this is where the new text is inserted.
Make the bookmark into a Public variable, and initialize it in the Initialize() function.
Public CBR As Range
Private Sub ComboBox1_Change()
CBR.Text = Me.ComboBox1.Value
End Sub
Private Sub UserForm_Initialize()
Set CBR = ActiveDocument.Bookmarks("bmc1").Range
With ComboBox1
.AddItem "F1"
.AddItem "G2"
.AddItem "R3"
.AddItem "G4"
End With
End Sub
I created a userform where is a comboBox
Depending which result user chooses, new comboBoxes will appear with new choices to choose from.
Below is the latest test I tried.
How do I make it so that when user changes the value in the new comboBox it will execute a premade function/sub
Code in Form
Dim WB As Workbook
Dim structSheet As Worksheet
Dim tbCollection As Collection
Private Sub UserForm_Activate()
Dim ignoreList(3) As String
ignoreList(0) = "main"
ignoreList(1) = "configurator"
ignoreList(2) = "create structure"
Set WB = Excel.ActiveWorkbook
For Each sheet In WB.Worksheets
If Not isInTable(ignoreList, sheet.Name) Then
supercode_box.AddItem sheet.Name
End If
Next
End Sub
Private Sub supercode_box_Change()
If Not sheetExists(supercode_box.text) Then Exit Sub
Set structSheet = WB.Worksheets(supercode_box.text)
'Dim obj As clsControlBox
topPos = 10
leftPos = 54
ID = 1
' For ID = 1 To 2
Set ComboBox = createProductForm.Controls.add("Forms.ComboBox.1")
With ComboBox
.Name = "comboBoxName"
.Height = 16
.Width = 100
.Left = leftPos
.Top = topPos + ID * 18
.AddItem "test"
.Object.Style = 2
End With
Set tbCollection = New Collection
tbCollection.add ComboBox
'Next ID
End Sub
code in class1 module
Private WithEvents MyTextBox As MSForms.controlBox
Public Property Set Control(tb As MSForms.controlBox)
Set MyTextBox = tb
MsgBox ("did it get here?")
End Property
Public Sub comboBoxName_Change()
MsgBox ("start working ffs")
End Sub
Public Sub comboBoxName()
MsgBox ("?? maybe this?")
End Sub
Judging on your code, the easiest way is to write the value you need in a separate worksheet.
Then make a check, whether it is changed and if it is changed, write the new value and fire the procedure that you want.
In short, something like this:
Sub TestMe()
If Worksheets("Special").Cells(1, 1) = WB.Worksheets(supercode_box.Text) Then
Call TheSpecificSub
End If
Worksheets("Special").Cells(1, 1) = WB.Worksheets(supercode_box.Text)
End Sub
I've developed a user form for the letters we use at work that auto fill the document after required data has been entered.
At this current point in time - when you hit OK the data will be entered and the data will fill the form. Some users are just trying to keep entering information over the top of the already filled form and stacking previously entered data into the letter.
Question: How do I get the user form to replace entered data rather than add entered data.
So if I enter the name as John Wayne, complete my letter and decide to write another letter on the same open document - how do I reopen my macro, populate the data and then overwrite all the previous information of the previous letter.
Option Explicit
Private Sub CheckBox1_Click()
Dim en As Boolean
en = Not CheckBox1.Value
EnableControls Array(TBLPGN, TBLPFN), en
If CheckBox1.Value = True Then ComboBoxLodge.Value = "Applicant"
If CheckBox1.Value = False Then ComboBoxLodge.Value = "Lodging parent"
End Sub
'utility sub: enable/disable controls
Private Sub EnableControls(cons, bEnable As Boolean)
Dim con
For Each con In cons
With con
.Enabled = bEnable
.BackColor = IIf(bEnable, vbWhite, RGB(200, 200, 200))
End With
Next con
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
Private Sub cmdClear_Click()
tbForm.Value = Null
tbFN.Value = Null
tbGN.Value = Null
tbDOB.Value = Null
cbLT.Value = Null
tbPN.Value = Null
tbissue.Value = Null
tbexpiry.Value = Null
tbLTD.Value = Null
tbNarrative.Value = Null
tbPRR.Value = Null
cbRecommendation.Value = Null
CheckBox1.Value = False
ComboBoxLodge.Value = Null
End Sub
Private Sub cmdOk_Click()
Dim useAforB As Boolean
useAforB = CheckBox1.Value
Application.ScreenUpdating = False
With ActiveDocument
.Bookmarks("Lodge").Range.Text = ComboBoxLodge.Value
.Bookmarks("Form").Range.Text = tbForm.Value
.Bookmarks("Form2").Range.Text = tbForm.Value
.Bookmarks("AGN").Range.Text = tbGN.Value
.Bookmarks("AFN").Range.Text = tbFN.Value
.Bookmarks("LGN").Range.Text = IIf(useAforB, _
tbGN.Value, TBLPGN.Value)
.Bookmarks("RGN").Range.Text = IIf(useAforB, _
tbGN.Value, TBLPGN.Value)
.Bookmarks("LFN").Range.Text = IIf(useAforB, _
tbFN.Value, TBLPFN.Value)
.Bookmarks("RFN").Range.Text = IIf(useAforB, _
tbFN.Value, TBLPFN.Value)
.Bookmarks("DOB").Range.Text = tbDOB.Value
.Bookmarks("LT").Range.Text = cbLT.Value
.Bookmarks("PN").Range.Text = tbPN.Value
.Bookmarks("PN2").Range.Text = tbPN.Value
.Bookmarks("PN3").Range.Text = tbPN.Value
.Bookmarks("PN4").Range.Text = tbPN.Value
.Bookmarks("Issued").Range.Text = tbissue.Value
.Bookmarks("Expiry").Range.Text = tbexpiry.Value
.Bookmarks("LTD").Range.Text = tbLTD.Value
.Bookmarks("LTD2").Range.Text = tbLTD.Value
.Bookmarks("Narrative").Range.Text = tbNarrative.Value
.Bookmarks("PRR").Range.Text = tbPRR.Value
.Bookmarks("Recommendation").Range.Text = cbRecommendation.Value
End With
Application.ScreenUpdating = True
Unload Me
End Sub
Private Sub Tbform_Change()
tbForm = UCase(tbForm)
End Sub
Private Sub Tbfn_Change()
tbFN = UCase(tbFN)
End Sub
Private Sub Tblpfn_Change()
TBLPFN = UCase(TBLPFN)
End Sub
Private Sub Tbpn_Change()
tbPN = UCase(tbPN)
End Sub
Private Sub UserForm_Initialize()
With cbLT
.AddItem "lost"
.AddItem "stolen"
End With
With cbRecommendation
.AddItem "I believe there is an entitlement to have the l/t flag turned off as the applicant has not contributed to the loss of Passport number: "
.AddItem "I believe there is no entitlement to have the l/t flag turned off as the applicant has contributed to the loss of Passport number: "
End With
With ComboBoxLodge
.AddItem "Lodging parent"
.AddItem "Applicant"
End With
With CheckBox1
CheckBox1.Value = True
End With
lbl_Exit:
Exit Sub
End Sub
Public Sub AutoOpen()
frmminute.Show
End Sub
Sub CallUF()
Dim oFrm As frmminute
Set oFrm = New frmminute
oFrm.Show
Unload oFrm
Set oFrm = Nothing
lbl_Exit:
Exit Sub
End Sub
Sub AutoNew()
CallUF
lbl_Exit:
Exit Sub
End Sub
new code currently getting a runtime error:
Private Sub CommandButtonOk_Click()
Dim useAforB As Boolean
useAforB = CheckBox1.Value
Application.ScreenUpdating = False
With ActiveDocument
Call UpdateBookmark("Title", ComboBoxTitle.Value)
Call UpdateBookmark("GN", TextBoxGN.Value)
Call UpdateBookmark("FN", TextBoxFN.Value)
Call UpdateBookmark("FN2", TextBoxFN.Value)
Call UpdateBookmark("Street", TextBoxStreet.Value)
Call UpdateBookmark("suburb", TextBoxSuburb.Value)
Call UpdateBookmark("postcode", TextBoxpostcode.Value)
Call UpdateBookmark("state", ComboBoxState.Value)
Call UpdateBookmark("street2", .Range.Text = IIf(useAforB, _
TextBoxStreet.Value, TextBoxStreet2.Value))
Call UpdateBookmark("Suburb2", .Range.Text = IIf(useAforB, _
TextBoxSuburb.Value, TextBoxSuburb2.Value))
Call UpdateBookmark("State2", .Range.Text = IIf(useAforB, _
ComboBoxState.Value, ComboBoxState2.Value))
Call UpdateBookmark("PostCode2", .Range.Text = IIf(useAforB, _
TextBoxpostcode.Value, TextBoxPostcode2.Value))
Call UpdateBookmark("CD", TextBoxCD.Value)
Call UpdateBookmark("MPN", TextboxMPN.Value)
Call UpdateBookmark("MPN2", TextboxMPN.Value)
Call UpdateBookmark("MPN3", TextboxMPN.Value)
Call UpdateBookmark("MPN4", TextboxMPN.Value)
Call UpdateBookmark("MPN5", TextboxMPN.Value)
Call UpdateBookmark("MPDD", TextBoxMPDD.Value)
Call UpdateBookmark("NPN", TextBoxNPN.Value)
Call UpdateBookmark("NPDD", TextBoxNPDD.Value)
End With
Application.ScreenUpdating = True
Unload Me
End Sub
Sub UpdateBookmark(BookmarkToUpdate As String, TextAtBookmark As String)
Dim BookmarkRange As Range
Set BookmarkRange = ActiveDocument.Bookmarks(BookmarkToUpdate).Range
BookmarkRange.Text = TextAtBookmark
ActiveDocument.Bookmarks.Add BookmarkToUpdate, BookmarkRange
After reading through your question, I realised what you wanted to do was updating the bookmark at the word document.
Private Sub cmdOk_Click()
Dim useAforB As Boolean
useAforB = CheckBox1.Value
Application.ScreenUpdating = False
Call UpdateBookmark("Lodge", ComboBoxLodge.Value)
Call UpdateBookmark("Form", tbForm.Value)
'Do for the rest.....
Application.ScreenUpdating = True
Unload Me
End Sub
Sub UpdateBookmark(BookmarkToUpdate As String, TextAtBookmark as string)
Dim BookmarkRange As Range
Set BookmarkRange = ActiveDocument.Bookmarks(BookmarkToUpdate).Range
BookmarkRange.Text = TextAtBookmark
ActiveDocument.Bookmarks.Add BookmarkToUpdate, BookmarkRange
End Sub
Say you have aUserForm with TextBox1, TextBox3, TextBox3 and an OK Button.
To only allow the UserForm to close if all three TextBox have data I would use the following script assigned to the OK Button:
Private Sub CommandButton1_Click()
If Len(TextBox1.Value) >= 1 And _
Len(TextBox2.Value) >= 1 And _
Len(TextBox3.Value) >= 1 Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
Is there another way to do this besides an If statement?
Direct User Before Errors Are Made
Preferable to informing a user after an invalid action has been made is to prevent the user from performing that invalid action in the first place[1]. One way to do this is to use the Textbox_AfterUpdate event to call a shared validation routine that controls the Enabled property of your OK button, and also controls the display of a status label. The result is a more informative interface that only allows valid actions, thereby limiting the nuisance of msgbox popups. Here's some example code and screenshots.
Private Sub TextBox1_AfterUpdate()
RunValidation
End Sub
Private Sub TextBox2_AfterUpdate()
RunValidation
End Sub
Private Sub TextBox3_AfterUpdate()
RunValidation
End Sub
Private Sub RunValidation()
If Len(TextBox1.Value) = 0 Or Len(TextBox2.Value) = 0 Or Len(TextBox3.Value) = 0 Then
CommandButton1.Enabled = False
Label1.Visible = True
Else
CommandButton1.Enabled = True
Label1.Visible = False
End If
End Sub
Private Sub CommandButton1_Click()
Me.Hide
End Sub
The If Statement
As far as the If statement is concerned, there are a ton of ways that can be done, but I think anything other than directly evaluating TextBox.Value leads to unnecessary plumbing and code complexity, so I think it's hard to argue for anything other than the If statement in the OP. That being said, this particular If statement can be slightly condensed by capitalizing on its numeric nature, which allows for
Len(TextBox1.Value) = 0 Or Len(TextBox2.Value) = 0 Or Len(TextBox3.Value) = 0
to be replaced with
Len(TextBox1.Value) * Len(TextBox2.Value) * Len(TextBox3.Value) = 0
Although that doesn't gain you much and is arguably less readable code, it does allow for a condensed one liner, especially if the textboxes are renamed...
If Len(TB1.Value) * Len(TB2.Value) * Len(TB3.Value) = 0 Then
.Value vs .Text
Lastly, in this case, I think .Value should be used instead of .Text. .Text is more suited for validating a textbox entry while its being typed, but in this case, you're looking to validate a textbox's saved data, which is what you get from .Value.
More User feedback - Colorization
I almost forgot, I wanted to include this example of how to include even more user feedback. There is a balance between providing useful feedback and overwhelming with too much. This is especially true if the overall form is complicated, or if the intended user has preferences, but color indication for key fields is usually beneficial. A lot of applications may present the form without color at first and then colorize it if the user is having trouble.
Private InvalidColor
Private ValidColor
Private Sub UserForm_Initialize()
InvalidColor = RGB(255, 180, 180)
ValidColor = RGB(180, 255, 180)
TextBox1.BackColor = InvalidColor
TextBox2.BackColor = InvalidColor
TextBox3.BackColor = InvalidColor
End Sub
Private Sub TextBox1_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub TextBox2_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub TextBox3_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub RunValidation(ByRef tb As MSForms.TextBox)
If Len(tb.Value) > 0 Then
tb.BackColor = ValidColor
Else
tb.BackColor = InvalidColor
End If
If Len(TextBox1.Value) * Len(TextBox2.Value) * Len(TextBox3.Value) = 0 Then
CommandButton1.Enabled = False
Label1.Visible = True
Else
CommandButton1.Enabled = True
Label1.Visible = False
End If
End Sub
Private Sub CommandButton1_Click()
Me.Hide
End Sub
As I said in my comment, that is an ok way to do it. But i'll post this just so you have an example of another way. This would allow you to evaluate what is going into the text boxes as they are set.
Option Explicit
Dim bBox1Value As Boolean
Dim bBox2Value As Boolean
Dim bBox3Value As Boolean
Private Sub TextBox1_Change()
If Trim(TextBox1.Text) <> "" Then
bBox1Value = True
End If
End Sub
Private Sub TextBox2_Change()
If Trim(TextBox2.Text) <> "" Then
bBox2Value = True
End If
End Sub
Private Sub TextBox3_Change()
If Trim(TextBox3.Text) <> "" Then
bBox3Value = True
End If
End Sub
Private Sub CommandButton1_Click()
If bBox1Value = True And bBox2Value = True And bBox3Value = True Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
You can use a loop:
Private Sub CommandButton1_Click()
Dim n as long
For n = 1 to 3
If Len(Trim(Me.Controls("TextBox" & n).Value)) = 0 Then
MsgBox "Please Complete All Fields!"
Exit Sub
End If
Next n
Me.Hide
End Sub
You can use the below code
Private Sub CommandButton1_Click()
If Trim(TextBox1.Value & vbNullString) = vbNullString And _
Trim(TextBox2.Value & vbNullString) = vbNullString And _
Trim(TextBox3.Value & vbNullString) = vbNullString Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
I got the answer from this question
VBA to verify if text exists in a textbox, then check if date is in the correct format
I have 4+ ComboBoxes on a user form. When they fire, they fire the same event. What I am trying to do is find out which ComboBox triggered the event. The ComboBoxes are created depending on how many components there are. The code generating the ComboBoxes is shown below:
For j = 0 To UBound(ComponentList) - 1
'Set Label
num = j + 1
Set control = UserForm1.Controls.Add("Forms.Label.1", "ComponentLabel" & CStr(num) & ":", True)
With control
.Caption = "Component " & CStr(num)
.Left = 30
.Top = Height
.Height = 20
.Width = 100
.Visible = True
End With
'set ComboBox
Set combo = UserForm1.Controls.Add("Forms.ComboBox.1", "Component" & num & ":", True)
With combo
.List = ComponentList()
.Left = 150
.Top = Height
.Height = 20
.Width = 50
.Visible = True
Set cButton = New clsButton
Set cButton.combobox = combo
coll.Add cButton
End With
Height = Height + 30
Next j
This works well and I can get the value the user selected, BUT I can not find which ComboBox has been used. This code below is the event that it fires (clsButton):
Public WithEvents btn As MSForms.CommandButton
Public WithEvents combobox As MSForms.combobox
Private combolist() As String
Private Sub btn_Click()
If btn.Caption = "Cancel" Then
MsgBox "Cancel"
Unload UserForm1
Variables.ComponentSelectionError = False
ElseIf btn.Caption = "Enter" Then
MsgBox "enter"
Unload UserForm1
Variables.ComponentSelectionError = True
End If
End Sub
Private Sub combobox_Click()
MsgBox combobox.Value
End Sub
This bit of code above was kindly worked on by Doug Glancy to get the events working with the code generated ComboBoxes.
How do I get the ComboBox that triggered the event? i.e. the name or some other form of identification.
I have managed to finally answer my own question after searching over 500 webpages (took a long time)
this is what i used and it works and fires when the certain comboboxes are clicked:
Private Sub combobox_Click()
MsgBox combobox.Value
If combobox = UserForm1.Controls("Component0") Then
MsgBox "Success1"
End If
If combobox = UserForm1.Controls("Component1") Then
MsgBox "Success2"
End If
End Sub
hopefully this can be used for other people who need it.
Within the class .Name will not appear in the intellisense list for the combobox as MSForms.ComboBox does not actually have a name property itself (take a look at it in the F2 object browser), rather that property is provided by the Control base class:
Private Sub combobox_Click()
MsgBox combobox.Value
MsgBox combobox.Name '// no hint but still works
'//cast to a Control to get the formal control interface with .Name
Dim ctrl As Control: Set ctrl = combobox
MsgBox ctrl.Name
End Sub
Maybe reference back to btn.Combobox again? Similar to how you assigned the combobox to the button in the first place, but then in reverse:
set combobox = btn.Combobox
Is there a reason you don't just add a property to your custom class and set that property when you register in the Collection?
For j = 0 To UBound(ComponentList) - 1
'Set Label
num = j + 1
Set control = UserForm1.Controls.Add("Forms.Label.1", "ComponentLabel" & CStr(num) & ":", True)
With control
.Caption = "Component " & CStr(num)
.Left = 30
.Top = Height
.Height = 20
.Width = 100
.Visible = True
End With
'set ComboBox
Set combo = UserForm1.Controls.Add("Forms.ComboBox.1", "Component" & num & ":", True)
With combo
.List = ComponentList()
.Left = 150
.Top = Height
.Height = 20
.Width = 50
.Visible = True
Set cButton = New clsButton
'*******EDIT********
with cButton
.combobox = combo
.Indx = j
end With 'cButton
'*******************
coll.Add cButton
End With
Height = Height + 30
Next j
Class Module
Public WithEvents btn As MSForms.CommandButton
Dim WithEvents mCombobox As MSForms.comboBox
Private combolist() As String
'*******EDIT********
Public Indx As Long
Property Let comboBox(cb As MSForms.comboBox)
Set mCombobox = cb
End Property
'*******************
Private Sub btn_Click()
If btn.Caption = "Cancel" Then
MsgBox "Cancel"
Unload UserForm1
Variables.ComponentSelectionError = False
ElseIf btn.Caption = "Enter" Then
MsgBox "enter"
Unload UserForm1
Variables.ComponentSelectionError = True
End If
End Sub
Private Sub mCombobox_Click()
'*******EDIT********
MsgBox "Combobox " & Indx & Chr(9) & mComboBox.Value
'*******************
End Sub
Since you require many to one mapping of the events, I assume you have a common call-back in your actual code, so you could also do this...
In a Standard Module
Public Sub cbCallBack(ocb As clsButton)
MsgBox ocb.Indx
End Sub
In clsButton (replacing the event handler)
Private Sub mCombobox_Click()
cbCallBack Me
End Sub