How to make the Combobox item list dynamic? - vba

I am using a 'Generate' button on my worksheet. When I click on the button, a popup (form) come, which contains two comboboxes. Basis the selection in the first combobox, the second combobox option list is populated.
For the first combobox, when I hardcode the item values it works fine. The form code is as follows:
Private Sub UserForm_Initialize()
With ComboBox_DL
.AddItem "DL1"
.AddItem "DL2"
End With
End Sub
I tried to make this item list dynamic by fetching the combobox item values from a column the in the excel worksheet using the following form code:
Private Sub UserForm_Initialize()
With ComboBox_DL
For Each c In ActiveSheet.Range(Range("AE"), Range("AE").End(xlDown))
.AddItem c.Value
Next
End With
End Sub
But the above code throws error: Run time error '1004': Method 'Range' of object '_Global' failed
I modified the code adding sheet details:
With ComboBox_DL
For Each c In ThisWorkbook.Worksheets("Business_Input_Data").Range(Range("AE"), Range("AE").End(xlDown))
.AddItem c.Value
Next
It still throws the same error.
Can someone help please? Also, I want to know how to look up the values corresponding to the selection in combobox1 and populate the list in combobox2?

If your combobox entries are a list on a worksheet, you don't need to use VBA to fill them at all. Instead, you can create a Dynamic Named Range, and use that as the Rowsource for the combobox.
Say your list starts on Sheet3, cell A1. Go to Formulas | Name Manager to create a named range. Give it a useful name like "Combo", then put the following formula into RefersTo: =OFFSET(Sheet3!$A$1,0,0,COUNTA(Sheet3!$A:$A),1) Save and close the Named Ranges dialogue.
In the properties of your combobox, look for the line "RowSource". Set it to =Combo, or whatever name you used for your named range.
Any changes to the list, including lengthening or shortening it, will now be reflected immediately and automatically in the combo box.
EDITED TO ADD:
To use the value selected in the first combobox to determine what list is used in a second combobox, we'll need to do two things.
The first is to create named ranges for all the possible selections in the first list:
In the image, column A is the source for our first combo box; the other columns contain the possible sources for the second combo box.
We then just need to put a little bit of code in the Change event for the first combobox:
Private Sub ComboBox1_Change()
Me.ComboBox2.Value = ""
Me.ComboBox2.RowSource = "=" & Me.ComboBox1.Value
End Sub
This code will trigger whenever ComboBox1 is changed. First it clears any existing value in ComboBox2, then it will set the row source property of ComboBox2 to a combination of the = symbol and whatever value was selected in the first box. Since those values are also named ranges, the second box will now use the selected named range as its list source.
If you needed to, you could add more levels of cascading options, with different named ranges for each one. More than a couple of levels may become unmanageable, though - at which point we may want to look at another method.

Havent tested this as i have not created the userform to test under same conditions, but should work subject to minor alterations.
Dim n As Long
n = Sheets("Business_Input_Data").Cells(Rows.Count, "AE").End(xlUp).Row
With ComboBox_DL
For Each c In ThisWorkbook.Worksheets("Business_Input_Data").Range("AE" & n)
.AddItem c.Value
Next

you're missing the row index in "AE"
furthermore use always explicit worksheet qualification in any Range reference
Private Sub UserForm_Initialize()
Dim c As Range
With ComboBox_DL
For Each c In For Each c In ThisWorkbook.Worksheets("Business_Input_Data").Range(ThisWorkbook.Worksheets("Business_Input_Data").Range("AE1"), ThisWorkbook.Worksheets("Business_Input_Data").Range("AE1").End(xlDown))
.AddItem c.Value
Next
End With
End Sub
but more elegant solutions are:
Private Sub UserForm_Initialize()
With ThisWorkbook.Worksheets("Business_Input_Data")
ComboBox_DL.RowSource = .Range("AE1", .Range("AE1").End(xlDown)).Address
End With
End Sub
Private Sub UserForm_Initialize()
With ThisWorkbook.Worksheets("Business_Input_Data")
ComboBox_DL.List = .Range("AE1", .Range("AE1").End(xlDown)).Value
End With
End Sub
where:
the former binds your ComboBox list to the range values whose address is given as ComboBox RowSource property
the latter takes the values of the given range as Combobox values

This is a solution to dynamically update the comboBox with emails in one column range.
Dim c As Range
ComboBox1.Value = ""
ComboBox1.Clear
For Each c In Sheets("emails").Range("F5:F5000")
If c Like "*#*" Then
ComboBox1.AddItem c
End If
Next
The 'ComboBox.Value' Set the initial value.
The 'ComboBox.Clear' Clears the previous rows in the comboBox.

Related

Copy text from cells based on a different cells answer

i am trying to create an order form that copies the customers address details that are in cells C8:C13, I have created a drop down in cell G15 that asks if the customers billing address is the same - yes or no, if the answer is yes I want to the data from c8:c13 to be copied into C16:C21
alternatively I could look to hide the rows C16:C21?
I tried initially to right an IF formula however it just returns true or false.
I think this might fix you problem.
Create a ActiveX ComboBox on whatever cell you want (let's stick with the same cell you wanted, so cell G15);
Open Visual Basic (Developer > Visual Basic);
Insert a module (Insert > Module)
Now lets insert the module code to populate the combobox:
Private Sub Workbook_Open()
With Sheet1.ComboBox1
' Clear values
.Clear
' Populate list
.AddItem "Yes"
.AddItem "No"
End With
End Sub
On your module put this code:
Sub copyThis()
'Defining the variables
Set adressBill = Range("C8:C13")
Set destBill = Range("C16:C21")
'If the combobox is Yes then copy
If Sheet1.ComboBox1.Value = "Yes" Then
adressBill.Select
Selection.Copy
destBill.Select
ActiveWorkbook.Worksheets("Sheet1").Paste
End If
End Sub
If you want to update the values whenever the combobox value changes just click Design Mode on the Developer tab, and select your combobox and click View Code and put this code in it:
Private Sub ComboBox1_Change()
'Calling the function whenever a value changes
Call copyThis
End Sub
Results:
This method is much easier than a formula (and probably safer aswell), since you can't reference a combobox object (directly) in a formula. Instead, you could use the LinkedCell property in the ComboBox.

Changing the Name of an Excel ActiveX ListBox

I have a set of ActiveX controls and subs that fit together like this:
User types into an ActiveX TextBox,
TextBox_Click triggers execution of 3 subs.
The first sub updates the value of a named range on a sheet; based on that updated value a table is created in excel using an offset function
The second sub copies the table range updated in 3 and paste.values into a range on the sheet (to eliminate formulas)
Here's where it is breaking down.
When I set the sheet up I create one ListBox (ListBox1). The third of the three subs mentioned in #2 above tests to see if ActiveX 'ListBox1' exists in the sheet. If not, the intention is the code will determine what the ListBox is called (LB1 or LB2 or LB2 etc), changes the name to 'ListBox1', and pastes the table from #4 above into ListBox1. Then a ListBox1_Click command could trigger a unique set of code to execute.
Right now I'm just testing switching between the names ListBox1 and ListBox2.
The idea is that as a user types into TextBox1 for example, ListBox1 updates at every keystroke. So type "g" and the list shows 20 names starting with the first "g" in the database sheet. Then type "ge" and the list shows 20 names starting with the first "ge" in the database sheet etc etc. The user clicks on a name and ListBox1_click does something unique. If the user was typing in TextBox2 they would see different data in the ListBox (which I would like to rename as ListBox2) and if they click a unique set of code is executed by ListBox2_Click.
The problem in #5 is the I get error 'Object doesn't support this property or method' the FIRST time I try to execute. The second time it is ok. If I do something else on the sheet and come back to it i get the error again.
Here is the code for #5 which is in a Module:
Sub PutListInListBox()
Dim OBJ As Object
On Error Resume Next
Set OBJ = ActiveSheet.OLEObjects("ListBox1")
On Error GoTo 0
If OBJ Is Nothing Then
ActiveSheet.ListBox2.Name = "ListBox1"
End If
ActiveSheet.ListBox1.Clear
ActiveSheet.ListBox1.List = Sheets("Search Criteria Control").Range("G1:G21").Value
End Sub
I have no idea what I'm doing wrong and any help is appreciated.
I hope I'm making this clear.
UPATED CODE
I have a bunch of ActiveX Lables and Text boxes so I used the first form you suggested to search for specific name Cases. I've been reading about it and can't see what I have wrong here. After typing in TB5, the LB doesn't update. I click back to Design Mode and can see that the name is still ListBox2.
Any ideas?
Private Sub TextBox5_Change()
Call UpdateValues(TextBox5.Value)
Call CopyTable
Dim OLEOBJ As OLEObject
For Each OLEOBJ In ActiveSheet.OLEObjects
Select Case OLEOBJ.Name
Case "ListBox1", "ListBox2", "ListBox3"
OLEOBJ.Name = "ListBox1"
OLEOBJ.ListFillRange = Sheets("Search Criteria Control").Range("G1:G21").Address(external:=True)
End Select
Exit For
Next
End Sub
I'll concentrate on your Code#5.
First, if you are changing the name of the ListBox Object, it is better to iterate the Object Collection it belongs to since you are not sure of it's name. Something like this:
Dim oleobj As OLEObject
Dim sh As Worksheet: Set sh = ActiveSheet
For Each oleobj In sh.OLEObjects
Select Case oleobj.Name
Case "LB1", "LB2", "ListBox1", "ListBox2" 'put the possible names here
oleobj.Name = "ListBox1" 'change it to the name you want
End Select
Exit For 'if you have more than 1 ListBox
Next
If you just want to change the name of an existing ListBox, then skip the checking.
For Each oleobj In sh.OLEObjects
oleobj.Name = "ListBox1"
Exit For 'if you have more than 1 ListBox
Next
Now, to assign values or list to it, you can directly assign the source Range, using ListFillRange Property after you've change its name.
oleobj.ListFillRange = Sheets("Search Criteria Control") _
.Range("G1:G21").Address(, , , True) 'add this line within the loop
Take note that you need not clear the previous list. It will automatically update. Since I'm not sure what you want to achieve entirely, I'll stop here. HTH though.

VBA listbox select worksheet by index

I have a form with listbox which dynamically provides a list of the worksheets in the current workbook (code below). I wish to take the selected Sheet and refer to it in a formula later in the process. From hours of playing around I cannot seem to accomplish this. I believe I read somewhere that you cannot take the string back to the sub and use it to refer to to an object. So I thought maybe I can create two listboxes
for sheet name
for sheet index
that I could pass the index number to and maybe use that in my formula to lookup items from the correct sheet.
For the life of my I cannot seem to find a way to connect the two since the items will always be changing; the code will be ran on multiple workbooks by multiple operators so the layout will most likely change between users. I can easily add the second list box with index #'s but I have a block on how to associate the name which will have meaning to the user and the index which I can pass back to the sub. I realize the "On click" procedure for the list box to associate the two but with the dynamic nature of the fields I cannot come up with the logic to put that into code.
For N = 1 To ActiveWorkbook.Sheets.Count
With ListBox1
.AddItem ActiveWorkbook.Sheets(N).Name
End With
Next N
Try this out.
Declare a public variable above the code for the UserForm, making it available throughout your workbook from any module or code.
Public listChoice As String
Using your code to get the sheet names for the ListBox rowsource.
Private Sub UserForm_Activate()
For n = 1 To ActiveWorkbook.Sheets.count
With ListBox1
.AddItem ActiveWorkbook.Sheets(n).name
End With
Next n
End Sub
Including an update event for the ListBox
Private Sub ListBox1_AfterUpdate()
listChoice = ListBox1.Text
End Sub
I included a test just to demonstrate that the result is still retained. You don't need this, it demonstrates the results on the screenshot.
Private Sub cmdTestChoice_Click()
MsgBox ("The choice made on the ListBox was: " & listChoice)
End Sub
edit: To access that sheet later, you can call it using something like this:
Some examples of different ways to access a cell, using .Range, or .Cells, with numbers or letters.
Using lRow & lCol as Long to set row and column numbers.
Sheets(listChoice).Cells(lRow, lCol).Value = TextBox1.Value 'Set cell on sheet from TextBox
TextBox2.Value = Sheets(listChoice).Range("A2").Value 'Set TextBox From Cell on Sheet
'Set a cell on another sheet using the selected sheet as a source.
Sheets("AnotherSheet").Cells(lRow, "D") = Sheets(listChoice).Range("D2")

Excel macro to create a command button and assign macro to the button

I am trying to build a main page for my costing model. On this page I have created a drop down list using a combo box and then I want to assign a macro that creates a list of different buttons/command buttons once an option is selected from the list. Then I want to build another macro that is assigned to those buttons which then take the user to another tab/sheet within the same workbook depending on the option they selected from the drop down.
Can someone please give me an idea as to what code I should be using, first to create a command button that refers to the selected option from the drop down and then assign a simple macro to that button which then takes me to the specified tab/sheet?
So far, I have got the following:
Option Explicit
Sub Select_Change()
With ThisWorkbook.Sheets("Main Page").Shapes("Select").ControlFormat
Select Case .List(.Value)
Case "Vehicle1": All_States1
Case "Vehicle2": All_States2
Case "Vehicle3": All_States3
Case "Vehicle4": All_States4
Case "Vehicle5": All_States5
Case "Vehicle6": All_States6
Case "Vehicle7": All_States7
End Select
End With
End Sub
I then tried to use the name All_States1 to create various buttons but it's not working properly, as all selected options are showing the same button and the button won't go away either. Also, I can't seem to assign a macro to the created button.
This is just an example of :
creating a Button
assigning a macro to it
.
Sub button_maker()
Dim r As Range
Set r = Selection
ActiveSheet.Buttons.Add(94.5, 75.75, 51, 27.75).Select
With Selection
.OnAction = "mooney"
.Characters.Text = "Bump"
End With
r.Select
End Sub
Sub mooney()
Range("A1").Value = Range("A1").Value + 3
End Sub
If I understand the problem correctly, you want to have a dropdown (combo box) on your sheet, and when a button is clicked you want to run a macro based on the selection. The following does that - see if it helps you.
First - create a combobox, and a range for the inputs (names in the combobox) and output (value selected). For example, you could call the input selectionIn and the result selectionOut.
Exact steps:
Wrote values of combobox selections in E1:E4 . Selected the four cells, then typed selectionIn in the name box (to the left of the formula bar). That creates a named range (there are other ways to create named ranges, but this is my preferred method).
Called cell F1 selectionOut
Created a combobox, and referenced these two ranges for its input and output:
Created a button, gave it the label "Go" and linked it to the action runIt.
Finally, I created the following code in a workbook module:
Sub runIt()
Dim whatToDo, makeName As Boolean
' look up the name of the combo based on the value:
whatToDo = Range("selectionIn").Cells([selectionOut].Value, 1)
MsgBox "have to do '" & whatToDo & "'"
makeName = False
Select Case whatToDo
Case "one"
' example of putting the code you need right in the select:
MsgBox "doing the first thing"
Case "two"
' example of calling a specific routine:
Call caseTwo
Case "three"
Application.Run "case" & whatToDo ' making the name of the function on the fly
Case "four"
makeName = True
End Select
If makeName Then
Dim nameToRun
nameToRun = "case" & whatToDo
Application.Run nameToRun
End If
End Sub
Sub caseTwo()
MsgBox "called the code for case two"
End Sub
Sub caseThree()
MsgBox "doing case three here"
End Sub
Sub caseFour()
MsgBox "even four can be done"
End Sub
This shows a few different ways to handle different cases depending on what was selected. Of course you can have a macro run every time the combobox selection is changed - but it sounds from your description like that is not what you want.
Let me know how you get on with this code example - I tried to keep it simple but show some options at the same time.
One alternative (which might be simpler) would be to have an array with the names of the functions that you want to call:
Sub otherMethod()
Dim functionList()
functionList = Array("caseOne", "caseTwo", "caseThree", "caseFour")
Application.Run functionList([selectionOut].Value - 1)
End Sub
That's certainly the most compact way I can think of to do this... you need the offset of -1 because the array index is base 0 (by default anyway) and the combobox returns 1 for the first selection. You could make your code more robust by writing
functionIndex = [selectionOut].Value + LBound(functionList) - 1
Application.Run functionList(functionIndex)
This ensures that if you change the base index of the functionList array to another value, it will all still work correctly.

Find cell location based on value then do something- User Forms VBA Excel

i have experience in programing, however, I am new to VBA. I have a user form that i am working on. This form has a Combo Box that has a list initialized to it. What i am trying to do is:
*Get the ID Number value inputted by the user from the ComboBox
*Take the value inputted by the user and find its match using a range of values from a worksheet (i.e. Worksheet.Range("ID_Number_List"))
*Once it obtains it's match get the location of the cell that it matches
* Off set the location of the cell by one column to get the Name that relates to the ID Number(Same Row) to set it to textBoxName.Value
*Off set it two columns to get the telefone number that relates to the ID Number and set it to textboxTele.value
I want this to happen as soon as a value is selected from the Combobox, so my question is does my code go in the combo box or does it go to the next text box? so as soon as the person tabs over to the next text box the code is automatically execute. i would like the code to fully execute without tabing over to the next box.
This code is not complete but here is what i have (i didnt add the off set part i just did a test execution):
Dim ORIValue As String
'get value from combo_box Set
ORIValue = COMBO_ORILIST.Value
Dim cLoc As Range
Dim cORIVal As Range
'worksheet with the ID information Dim ORISheetList As Worksheet
Set ORISheetList = Worksheets("ORI_LIST")
'
For Each cLoc In ORISheetList.Range("ORI_LIST")
'compare the input string from list- considering using Match function for this
If StrComp(cLoc, ORIValue, vbTextCompare) Then TextBAgencyName.Value = "test"
Else: Next cLoc
End If
Let me know what you think. If i have to rewrite everything i will.
Your code doesn't compile.
If you have a userform with a single combobox called ComboBox1, you need to put your cell-finding code in the form code as follows:
Private Sub ComboBox1_Change()
MsgBox "yep, this is where the code should go"
End Sub
I suspect using the rowsource property of the combobox in combination with the index of the selected value you probably don't need to actually perform a search for the selected value. Something like this might work:
Private Sub ComboBox1_Change()
MsgBox Range(ComboBox1.RowSource).Cells(ComboBox1.ListIndex + 1)
End Sub
Hope that helps.