Using .AddItem With Different Comboboxes in Excel VBA Userform - vba

I have a userform with a lot of comboboxes. I am trying to use .AddItem when the userform is intialized, with no success.
Here is what I have tried so far:
Sub Userform_Initialize()
Dim cCont As MSForms.ComboBox
For Each cCont In Me.Controls
cCont.AddItem "Item Added"
Next cCont
End Sub
I usually get a runtime error 13 "type mismatch" come up. Not sure if that has anything to do with the button I have on the userform as well.
How do I loop through a userform and use .AddItem to each combobox? Once I get the code on how to do this, I'll wrap it in an If statement to only add it to certain comboboxes with certain words in the name, if that helps for context.
Thanks in advance,
-Anthony

Anthony,
You are trying to call the AddItem method on each control on the form. But not all controls provide the AddItem method. You need to check out whether a particular control is combobox or not. And only if the control is combobox you may call the AddItem method.
How do I loop through a userform and use .AddItem to each combobox?
It is not clear where you need to loop through. Could you be more specific?

The best way to add controls to a userform that I have found is to follow this procedure.
Dim NewComboBox as Control
Set NewComboBox = Me.Controls.Add("Forms.ComboBox.1")
With NewComboBox
'Inside of this part you can put .name or any other property in the
'activex controls properties part, .left .top .width and .height determine the size of the box
.Name = Whatever Name You Desire
End With
Put this in your userform_initialize() event and you should be good to go.

You code works fine for me adding two combo boxes to a userform. Only thing I can think of is the correct references are not enabled for some reason.

Related

Set userform width from a module by looping through userforms

Been having a very frustrating problem that I can't seem to find a solution for anywhere - help would be greatly appreciated!
I know how to change the width of a userform from within the userform itself (Me.Width).
The problem is that I am writing a module that will format userforms dynamically. The module is passed a form and it does some manipulations on that form. So far everything works as long as I'm referring to objects on the form.
But I'm now trying to refer to the form itself, and when I try to change the width (of the form, not of a control on the form) I get the error: "Object doesn't support this property or method".
I've tried declaring it as both a UserForm and an Object and all of the other code works in both cases, but resizing the width doesn't. I can see in the immediate window that width isn't available, which is obviously why the code won't execute.
Here's the code that I've tried without succses:
Sub frmLoadLayoutTest()
frmLoadLayout frmTest
frmTest.Show
End Sub
Private Sub frmLoadLayout(frmActive As Object) 'Also tried (frmActive as UserForm)
'Setting the width of a control works
frmActive.Controls("labelTest").Width = 100
'Setting the width of the form itself doesn't work
frmActive.Width = 100
End Sub
If anyone can provide an elegant solution, that would be fantastic. Alternatively, is there a way I can refer to the userform by name? (Something like Userform(frm1.name).Width = 100)
Thanks in advance!
Try this:
Sub frmLoadLayoutTest()
Dim frm As frmTest
Set frm = New frmTest '<<< create an instance of the form
frmLoadLayout frm '<<< pass in the instance
frm.Show '<<< show the instance
End Sub
Private Sub frmLoadLayout(frm As Object)
With frm
.Controls("labelTest").Width = 100
.Width = 300
End With
End Sub
See also why it's good practice to avoid the "default instance" and create your own explicit instance of a form before using it:
https://rubberduckvba.wordpress.com/2017/10/25/userform1-show/

Is there a way to add to a combobox list using a textbox and button?

I'm looking for a way to add items to a combobox list without adding the item to the code directly.
UserForm Image
Private Sub UserForm_Initialize()
With ComboBox2
.AddItem ".020"
.AddItem ".030"
.AddItem ".032"
.AddItem ".040"
End With
With ComboBox3
.AddItem "THK"
.AddItem "DIA"
.AddItem "TUBE"
.AddItem "FORGING"
End With
End Sub
I'd like the user to be able to add an Item into the dropdown list without going into the code. Is there a way to add an .AddItem to the combobox?
Unlike ListBoxes, ComboBoxes allow a user to type a new entry directly into the comboBox field. That's the simplest solution, no extra code required!
If, for some reason, you want to make this more complicated, you can add a text field and a command button. After the user types a new entry in the text field, they click on the button which runs this macro:
Private Sub CommandButton1_Click()
ComboBox3.AddItem TextBox1.value
End Sub

200 Buttons All Changing One TextBox - VBA Excel

I have a VBA Excel application with about 200ish buttons. I want them all to change one textbox called "Name" with the caption of the button pressed. I did blur some stuff from the image as these boxes are all real peoples name. How can I do this without having to create 200+ functions?
An example is let's say I have 3 buttons. The three values are foo1, foo2, and foo3. When I click any of the buttons, let's say I click foo2, I want the TextBox to update the value to foo2. I know how to do this but how do I do it without having to manually write a function for all 3 buttons. The textbox value will always be the button value. Now imagine it is 200+ buttons.
Thanks!
Here is how I'd approach it. First add a class module and call it buttonClass:
Option Explicit
Public WithEvents aCommandButton As msforms.CommandButton
Private Sub aCommandButton_Click()
MsgBox aCommandButton.Name & " was clicked"
End Sub
Then in your userform initiation event, use code similar to:
Dim myButtons() As buttonClass
Private Sub UserForm_Initialize()
Dim ctl As Object, pointer As Long
ReDim myButtons(1 To Me.Controls.Count)
For Each ctl In Me.Controls
If TypeName(ctl) = "CommandButton" Then
pointer = pointer + 1
Set myButtons(pointer) = New buttonClass
Set myButtons(pointer).aCommandButton = ctl
End If
Next ctl
ReDim Preserve myButtons(1 To pointer)
End Sub
This will wire up all of your command buttons to display their name on click. You can tweak the logic in the buttonClass to be fancier. Or you can tweak the logic in the initialize event to include on certain buttons (expanding on the "If" part).
Hope that helps!
If i was going to do this (and I'm not sure I would), I would create and populate each button through a loop, which also set up a link to one event handler which could determine what to do.
If each button is created manually and already exist, then I think you need to update them manually.
Another possibility, is to catch another higher-level event such as mouse click and then, from the information provided by that event, work out which button was pressed.

Excel - Change BackColor of UserForm TextBoxes and ComboBoxes with VBA

I am just learning VBA and have used some code from an older book (Excel 2010). It could be that Excel 2016 had some changes that make this code not work anymore.
I do not get a compile error for the class or the Subs. The behavior is that NOTHING happens. What is supposed to happen is that the BackColor of either a ComboBox or a TextBox should change color as if is in focus or leaves focus.
As I said, for some reason when I run the code nothing happens. No errors or warnings appear so it's as if the code is running and then just doing nothing.
Here is my code. The comments should make it clear. I am hoping someone can explain to me what is going on and why this code results in no color changes as the focus changes when I tab through the UserForm.
This first block of code is a stand alone Class Module called "clsCtlColor"
Public Event GetFocus()
Public Event LostFucus(ByVal strCtrl As String)
Private strPreCtr As String
'Base Class for chaging Backcolor of ComBoxes and TextBoxes when focus is changed.
Public Sub CheckActiveCtrl(objForm As MSForms.UserForm)
With objForm
If TypeName(.ActiveControl) = "ComboBox" Or _
TypeName(.ActiveControl) = "TextBox" Then
strPreCtr = .ActiveControl.Name
'On Error GoTo Terminate
Do
DoEvents
If .ActiveControl.Name <> strPreCtr Then
If TypeName(.ActiveControl) = "ComboBox" Or _
TypeName(.ActiveControl) = "TextBox" Then
RaiseEvent LostFucus(strPreCtr)
strPreCtr = .ActiveControl.Name
RaiseEvent GetFocus
End If
End If
Loop
End If
End With
Terminate:
Exit Sub
End Sub
The following Subs are in the UserForm Code
Option Explicit
Private WithEvents objForm As clsCtlColor
'*********************************************************************************************************************
'*Subs for managing the BackColor of comboxes and TextBoxes depending on focus.***************************************
'*********************************************************************************************************************
'initializes the Userform with the clsCtlColor class
Private Sub UserForm_Initialize()
Set objForm = New clsCtlColor
End Sub
'Changes the BackColor of the Active Control when the form is activated.
Private Sub UserForm_Activate()
If TypeName(ActiveControl) = "ComboBox" Or _
TypeName(ActiveControl) = "TextBox" Then
ActiveControl.BackColor = &H99FF33
End If
objForm.CheckActiveCtrl Me
End Sub
'Changes the BackColor of the Active Control when it gets the focus.
Private Sub objForm_GetFocus()
ActiveControl.BackColor = &H99FF33
End Sub
'Changes the BackColor back to white when the control loses focus.
Private Sub objForm_LostFocus(ByVal strCtrl As String)
Me.Controls(strCtrl).BackColor = &HFFFFFF
End Sub
'Clears the objForm when the form is closed.
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Set objForm = Nothing
End Sub
In the Class Module the is an On Error Statement that terminates the Sub when an error occurs. However, I commented it out and still, I see no compile errors. So, I can only conclude it is a runtime issue.
Any help would be much appreciated.
UPDATE:
If I use these two subs on a TextBox I get the effect I'm looking for:
Private Sub TextBox1_Enter()
TextBox1.BackColor = RGB(153, 255, 51)
End Sub
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
TextBox1.BackColor = RGB(255, 255, 255)
End Sub
What I hate about this is that my UserForm has over one hundred TextBoxes and I would need to write these two subs for each TextBox - so like 200++ Subs!
I am still trying to get the above more general approach to work.
One thing I noticed is that if I change the RGB values in the two subs above to Hex values, they no longer work. I tried changing the hex color values in the more general approach to RGB but it made no difference.
Yet Another Update:
It was pointed out that I had a typo in the class LostFucus. I changed that in two places to LostFocus. However, the code still does not work. Then the question was whether or not my code is in the userform module. It is. Then I tried an experiment. I created a new Workbook and imported the code into a brand new class and userform. I added three textboxes. Abracadabra! It worked! However, it does not work in the form I want it to work in. I have scoured the properties for the form itself and the text boxes and I can see nothing different between my form and the dummy form.
This must be something very simple I am over looking!
After a great deal of head scratching and screaming at my poor monitor I finally found the solution but as of now, I am totally disappointed in Microsoft for the weirdness of working with UserForms. Here is what fixed the problem:
I had not yet set the tab order!
I realized the tab order had my form opening with the first tab stop being set for a TextBox in a MultiPage on my form. I set the tab order so that the first TextBox is active on the UserForm and everything works with the coloring on the main body of the form.
Here is where the weirdness begins, in my opinion.
When the last TextBox on the main body of the form is reached and tab is pressed, the multi-page itself is selected. Only after you hit tab a second time is the first TextBox within the MultiPage selected and then the colors are not applied as they are in the main body of the form at all. The same scenario holds true for Frames as well. Also, there does not appear to be a good way to simply tab from the end of page 1 to the beginning of page 2.
It's very disappointing to me because I would have thought that this is not the way it is. I ASSUMED I could set up 1000 TextBoxes, use the Frames and the Multipage to organize things (SO I COULD MAINTAIN THE WINDOW AT ONE SIZE AND NOT HAVE TO SCROLL THE FORM UP AND DOWN) and then set a tab order that would navigate ALL of the TextBoxes regardless of what organizing container they are in. I assumed it would be this way because it MAKES SENSE! I want to click into the first TextBox and simply never touch my mouse until the form is completely filled out. Otherwise, there really is no point in this effort of making a UserForm! I could point and click around in the spreadsheet without the hassle of designing a form and writing code!
What a bummer!
I suppose I can "make it so!" by writing a bunch of code to jump the selection from container to container...MICROSOFT - It should not be this wonky and stupid!

LinkedCell to Checkbox calling onAction Subroutine in VBA?

I have a great number of checkboxes calling a subroutine whenever a checkbox is ticked/unticked. Now I would like to get the address to the linked cell of the checkbox that called the sub. I've tried
Application.Caller.LinkedCell
but I get "Object required" error, I guess because Application.Caller returns a string.
Is there some way I can get the address of the linkedCell?
Thank you for any help!
This assumes you are using a Checkbox from the Forms menu, as I don't think Application.Caller recognizes an ActiveX control. It uses the oddly-named ControlFormat property of a Shape (A Checkbox is a Shape):
Sub GetLinkedCell()
Dim shp As Shape
Dim chk As ControlFormat
Set shp = ThisWorkbook.Worksheets(1).Shapes(Application.Caller)
Set chk = shp.ControlFormat
MsgBox chk.LinkedCell
End Sub