How to add headers to a multicolumn listbox in an Excel userform using VBA

匿名 (未验证) 提交于 2019-12-03 01:33:01

问题:

Is it possible to set up the headers in a multicolumn listbox without using a worksheet range as the source?

The following uses an array of variants which is assigned to the list property of the listbox, the headers appear blank.

Sub testMultiColumnLb()     ReDim arr(1 To 3, 1 To 2)      arr(1, 1) = "1"     arr(1, 2) = "One"     arr(2, 1) = "2"     arr(2, 2) = "Two"     arr(3, 1) = "3"     arr(3, 2) = "Three"       With ufTestUserForm.lbTest         .Clear         .ColumnCount = 2         .List = arr     End With      ufTestUserForm.Show 1 End Sub

回答1:

No. I create labels above the listbox to serve as headers. You might think that it's a royal pain to change labels every time your lisbox changes. You'd be right - it is a pain. It's a pain to set up the first time, much less changes. But I haven't found a better way.



回答2:

Simple answer: no.

What I've done in the past is load the headings into row 0 then set the ListIndex to 0 when displaying the form. This then highlights the "headings" in blue, giving the appearance of a header. The form action buttons are ignored if the ListIndex remains at zero, so these values can never be selected.

Of course, as soon as another list item is selected, the heading loses focus, but by this time their job is done.

Doing things this way also allows you to have headings that scroll horizontally, which is difficult/impossible to do with separate labels that float above the listbox. The flipside is that the headings do not remain visible if the listbox needs to scroll vertically.

Basically, it's a compromise that works in the situations I've been in.



回答3:

I was looking at this problem just now and found this solution. If your RowSource points to a range of cells, the column headings in a multi-column listbox are taken from the cells immediately above the RowSource.

Using the example pictured here, inside the listbox, the words Symbol and Name appear as title headings. When I changed the word Name in cell AB1, then opened the form in the VBE again, the column headings changed.

The example came from a workbook in VBA For Modelers by S. Christian Albright, and I was trying to figure out how he got the column headings in his listbox :)



回答4:

There is very easy solution to show headers at the top of multi columns list box. Just change the property value to "true" for "columnheads" which is false by default.

After that Just mention the data range in property "rowsource" excluding header from the data range and header should be at first top row of data range then it will pick the header automatically and you header will be freezed.

if suppose you have data in range "A1:H100" and header at "A1:H1" which is the first row then your data range should be "A2:H100" which needs to mention in property "rowsource" and "columnheads" perperty value should be true

Regards, Asif Hameed



回答5:

I like to use the following approach for headers on a ComboBox where the CboBx is not loaded from a worksheet (data from sql for example). The reason I specify not from a worksheet is that I think the only way to get RowSource to work is if you load from a worksheet.

This works for me:

  1. Create your ComboBox and create a ListBox with an identical layout but just one row.
  2. Place the ListBox directly on top of the ComboBox.
  3. In your VBA, load ListBox row1 with the desired headers.
  4. In your VBA for the action yourListBoxName_Click, enter the following code:

    yourComboBoxName.Activate` yourComboBoxName.DropDown`
  5. When you click on the listbox, the combobox will drop down and function normally while the headings (in the listbox) remain above the list.



回答6:

Here is my approach to solve the problem:

This solution requires you to add a second ListBox element and place it above the first one.

Like this:

Then you call the function CreateListBoxHeader to make the alignment correct and add header items.

Result:

Code:

  Public Sub CreateListBoxHeader(body As MSForms.ListBox, header As MSForms.ListBox, arrHeaders)             ' make column count match             header.ColumnCount = body.ColumnCount             header.ColumnWidths = body.ColumnWidths          ' add header elements         header.Clear         header.AddItem         Dim i As Integer         For i = 0 To UBound(arrHeaders)             header.List(0, i) = arrHeaders(i)         Next i          ' make it pretty         body.ZOrder (1)         header.ZOrder (0)         header.SpecialEffect = fmSpecialEffectFlat         header.BackColor = RGB(200, 200, 200)         header.Height = 10          ' align header to body (should be done last!)         header.Width = body.Width         header.Left = body.Left         header.Top = body.Top - (header.Height - 1) End Sub

Usage:

Private Sub UserForm_Activate()     Call CreateListBoxHeader(Me.listBox_Body, Me.listBox_Header, Array("Header 1", "Header 2")) End Sub


回答7:

Another variant on Lunatik's response is to use a local boolean and the change event so that the row can be highlighted upon initializing, but deselected and blocked after a selection change is made by the user:

Private Sub lbx_Change()      If Not bHighlight Then          If Me.lbx.Selected(0) Then Me.lbx.Selected(0) = False      End If      bHighlight = False  End Sub

When the listbox is initialized you then set bHighlight and lbx.Selected(0) = True, which will allow the header-row to initialize selected; afterwards, the first change will deselect and prevent the row from being selected again...



回答8:

Here's one approach which automates creating labels above each column of a listbox (on a worksheet).

It will work (though not super-pretty!) as long as there's no horizontal scrollbar on your listbox.

Sub Tester() Dim i As Long  With Me.lbTest     .Clear     .ColumnCount = 5     'must do this next step!     .ColumnWidths = "70;60;100;60;60"     .ListStyle = fmListStylePlain     Debug.Print .ColumnWidths     For i = 0 To 10         .AddItem         .List(i, 0) = "blah" & i         .List(i, 1) = "blah"         .List(i, 2) = "blah"         .List(i, 3) = "blah"         .List(i, 4) = "blah"     Next i  End With  LabelHeaders Me.lbTest, Array("Header1", "Header2", _                      "Header3", "Header4", "Header5")  End Sub  Sub LabelHeaders(lb, arrHeaders)      Const LBL_HT As Long = 15     Dim T, L, shp As Shape, cw As String, arr     Dim i As Long, w      'delete any previous headers for this listbox     For i = lb.Parent.Shapes.Count To 1 Step -1         If lb.Parent.Shapes(i).Name Like lb.Name & "_*" Then             lb.Parent.Shapes(i).Delete         End If     Next i      'get an array of column widths     cw = lb.ColumnWidths     If Len(cw) = 0 Then Exit Sub     cw = Replace(cw, " pt", "")     arr = Split(cw, ";")      'start points for labels     T = lb.Top - LBL_HT     L = lb.Left      For i = LBound(arr) To UBound(arr)         w = CLng(arr(i))         If i = UBound(arr) And (L + w) 


回答9:

Why not just add Labels to the top of the Listbox and if changes are needed, the only thing you need to programmatically change are the labels.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!