Update ListBox RowSoure at runtime - excel

I am building an Excel workbook with a userform built with vba. I have a listbox control on it with multiple columns. I want the column headers to appear. So from what I read, I am forced to populate the listbox using the RowSource property. I tied the RowSource to a listobject. The userform also has buttons to add or remove rows in the listobject, which need to be repeated in the listbox. When I try to update the RowSource after a change in the listbox, Excel crashes and reopens every time.
I have a solution to work around this problem. If I populate the listbox using the List property, I can add and remove rows and everything works fine. But if I do use the List property, it is not possible to have column headers in the listbox. There is a solution for this too as suggested by Jonas_Hess in this post: How to add headers to a multicolumn listbox in an Excel userform using VBA. But I would of prefered to have the column headers in the listbox itself.
To reproduce the problem I built a simple form with a listbox and a button. I tied the RowSource of the listbox to a listobject. The listobject only has three rows and 1 column. The cell values are 1, 2, 3. The button's purpose is to add new rows to the listobject and update the listbox.
Here's the code:
Private Sub UserForm_Initialize()
ListBox1.RowSource = Worksheets(1).ListObjects(1).DataBodyRange.Address
End Sub
Private Sub cmdAdd_Click()
Dim Table As ListObject
Set Table = Worksheets(1).ListObjects(1)
Table.Resize Range(Cells(1, 1), Cells(Table.ListRows.Count + 2, 1))
Table.DataBodyRange(Table.ListRows.Count, 1).Value = Table.DataBodyRange(Table.ListRows.Count - 1, 1).Value + 1
ListBox1.RowSource = Empty
ListBox1.RowSource = Table.DataBodyRange.Address
End Sub
I am wondering if there is a way to add or delete rows of the RowSource property of a listbox in Excel VBA.

Following ProfoundlyOblivious suggestions, I tried the same code on a colleagues workstation. He has Excel 2016 32 bits on Windows 10 64 bits. Turns out Excel was crashing at the Table.Resize line for him. This gave me the idea to try and reassign the ListBox1.RowSource = Empty prior to messing to the ListObject. Everything worked fine. Excel did not crash when reassigning the RowSource, on both workstations.
Here's the modified code:
Private Sub UserForm_Initialize()
ListBox1.RowSource = Worksheets(1).ListObjects(1).DataBodyRange.Address
End Sub
Private Sub cmdAdd_Click()
Dim Table As ListObject
ListBox1.RowSource = Empty
Set Table = Worksheets(Feuil1.Index).ListObjects(1)
Table.Resize Worksheets(Feuil1.Index).Range(Worksheets(Feuil1.Index).Cells(1, 1), Worksheets(Feuil1.Index).Cells(Table.ListRows.Count + 2, 1))
Table.DataBodyRange(Table.ListRows.Count, 1).Value = Table.DataBodyRange(Table.ListRows.Count - 1, 1).Value + 1
ListBox1.RowSource = Table.DataBodyRange.Address
End Sub
I have cell A1 = Number, A2 = 1, A3 = 2, A4 = 3. Clicking the add button added a new value below the usedrange and in the ListBox.
It looks like using the ListObject.Resize method when it is linked to a RowSourceis not stable on all Excel versions and was the source of my problem.

Related

How to remove item from combobox in a userform?

I have a list of names in a sheet. I set these names as my RowSource for a combobox on a useform.
There are two Comboboxes involved. One starts full, the other starts empty.
I want when I click on a name from the first (full) combobox, said name to be added to the other combobox, and removed from the original combobox (and vice versa eventually).
I can't remove anything with RemoveItem.
I went the 'Menu.ListeAjoutAg.ListIndex' way to get my current selection's index ('Menu' is the UserForm and 'ListeAjoutAg' is the combobox), but it did not work.
Tried inputting through a variable I created real quick, 'b', but same result. No index number works. I checked and I only feed the function integers (0, 1, 3, 4...) that are correct and/or well within the scope of my list (about 45 names).
Private Sub ListeAjoutAg_Change()
a = Menu.ListeAjoutAg.Text
b = Menu.ListeAjoutAg.ListIndex
Menu.ListeRetirer.AddItem (a) ' goes fine till there
Menu.ListeAjoutAg.RemoveItem (b) 'and here it goes wrong
Menu.ListeRetirer.Enabled = True
Menu.ListeRetirer.Visible = True
End Sub
As already mentioned: You can't add or remove items from a Listbox if you have set the Rowsource property.
However, it is rather easy to fill a Listbox from a range - simply copy the cell values into an array and assign the array as List. See for example VBA Excel Populate ListBox with multiple columns
Put the following routine into your form and call it from the form Activate event.
Private Sub fillListBox(r As Range)
Me.ListeAjoutAg.Clear
Me.ListeAjoutAg.ColumnCount = r.Columns.Count
Dim data
data = r.Value
Me.ListeAjoutAg.List = data
End Sub
Private Sub UserForm_Activate()
Dim r As Range
' Replace this with the range where your data is stored.
Set r = ThisWorkbook.Sheets(1).Range("A2:C10")
fillListBox r
End Sub

excel vba listbox additem

I am running office 365 home on windows 10. I am programming Excel using VBA.
I have a data range in a worksheet row. I want the user to be able to select one item from this row of data. I am trying to populate ListBox or ComboBox with dta from the range row. Having read MS vba.reference documentation I decided to get my range data into an array and use listbox = myarray() and got "Object does not support this method or property." I tried looping through my data range and putting each item in using listbox.additem (mydata()) with the same result. On examination of the listbox prperties AddItem is not there. Seems they have been withdrawn or maybe never existed for Excel VBA.
Any suggestions?
If you are using Additem then you should only add a single item not an array. If you want to use an array you have to use List and the array should be one-dimensional
MyListBox.List=MyOneDArray
Personally I never use .List and an array with Listboxes because I found some circumstances in which it did not work as expected.
There are two ways you can do this:
loop through each item individually and use combobox.additem
Set the combobox.list = array (or variant)
See below for an example of both assuming you want to populate the data from cells A1 to A10 in 2 separate comboboxes:
Private Sub UserForm_Initialize()
Dim i As Integer
Dim arr As Variant
' looping through parameters 1-by-1
With UserForm1.ComboBox1
For i = 1 To 10
.AddItem ThisWorkbook.Sheets("Sheet1").Range("A" & i).Value
Next i
End With
' setting combobox list to arrauy
With UserForm1.ComboBox2
.List = ThisWorkbook.Sheets("Sheet1").Range("A1:A10").Value
End With
End Sub
Make sure to insert your code in the userform code and not the module code

How do I reference a listbox to a specific sheet?

I have an excel file with 2 worksheets (Sheet 1 and Sheet 2) and a userform with a listbox. The listbox should pull 2 columns from sheet 2 but it always pull the columns from sheet 1.
I am using the following code:
ListBox1.RowSource = “A2:B50“
I tried:
ListBox1.RowSource = “Sheet2!A2:B50“
but get an
Runtime error 380 code. Could not set the RowSource property. Invalid property value.
How do I fix that?
Following code just work fine for me.
Private Sub UserForm_Initialize()
Me.ListBox1.RowSource = "Sheet2!A2:B10"
End Sub
When open form shows like...

ComboBox list throgh Range in sheet

In userform I inserted ComboBox and i have to add list through Array following are the code. I want that whether it is possible that in ComboBox list will get from a Range in sheet (like in case of Data Validation)
Private Sub UserForm_Initialize()
ComboBox1.List = Array("Item1", "Item2", "Item3", "Item4")
End Sub
you can use the range in the sheet to create, even a named range, e.g.:
combobox1.list = range(cells(1,1),cells(100,1)).value
combobox2.list = sheets(1).range("NamedRange")
arr = array("1","2","3")
combobox3.list = arr
This is how you'd use a range to set the row source of a combo box. You can also do this in vba.
Me.combobox1.RowSource = "MyRange"
You can set this to a Table (ListObject) instead of a static range. Create a Table with your list of values, instead of just using a static range of cells. This way when you need to add to the list, you simply enter the new values, which are added to the Table. In my example, I have a Table named "Table1" and a column with the heading "Numbers". Then call this function:
Private Sub UserForm_Initialize()
ComboBox1.RowSource = "=Table1[Numbers]"
End Sub
You have to do this on the Iniitalize, since setting the RowSource from the ComboBox Properties will cause Excel to crash the first time you add an item to your list.
This gives you a list that you can edit without having to edit the code behind the UserForm.

Vba combobox using non-active sheet

I have a combobox to a userform and the its not an activesheet in excel so not sure how to go about it.
The sheet name is "DoNotPrint - Rate Index" and the values within that sheet to appear in the combobox are the columns C2:AS2.
Private Sub ComboBox1_Change()
Sheets("DoNotPrint - Rate Index").Range("C2:AS2") = ComboBox1.Value
End Sub
I tried this code and the combobox list isn't populating those column when the combobox list button is clicked.
The code you posted is for taking what's in the combobox and putting it on the sheet, when it's selected. But if I understand correctly your issue is you can't get the combobox populated. Because you are using a single row as your dataset and not a single column you will need to transpose your data.
Private Sub UserForm_Initialize()
ComboBox1.List = WorksheetFunction.Transpose(Sheet1.Range("C2:AS2"))
End Sub

Resources