I use the following code to add headers above listboxes and comboboxes. It seems a bit like a sledgehammer to crack a nut but sometimes the nut has to be cracked, and all the other methods and tools that I have seen also fall into the category of sledgehammer.
To make this as simple as possible for myself I have defined a class called clsListBoxHeaders and I include that code below. Then suppose you have a ListBox with 3 columns you need to
- Tell the class which ListBox it is to work on
- Tell it what the headers are
- Tell it the column widths
To do this insert the following code in your user form
Dim lbHeaders As New clsListBoxHeaders
Set lbHeaders.ListBox = ListBox1
lbHeaders.Headers = "First Header;Second Header;Third Header"
lbHeaders.ColumnWidths = "40;50;60"
Note that the number of headers and the number of columnwidths must match exactly the number of columns in your listbox/combobox
To clear the header data use:
lbHeaders.Clear
If you want to format the labels (e.g. font) then you can access the labels as a variant array
lbHeaders.Labels
The class module code is as follows:
Option Explicit
' clsListBoxHeaders - Display header info above a ListBox or ComboBox
' To use this class in your project:
' Add a class module called clsListBoxHeaders and paste this code into it
' For each ListBox or ComboBox for which you wish to display column headers insert the following code in your userform:
' Dim lbHeaders As New clsListBoxHeaders
' Set lbHeaders.ListBox = ListBox1
' lbHeaders.Headers = "First Header;Second Header;Third Header"
' lbHeaders.ColumnWidths = "40;50;60"
'Note that the number of headers and the number of columnwidths must match exactly the number of columns in your listbox/combobox
' To clear the header data use:
' lbHeaders.Clear
Const LabelHeight As Integer = 10 ' Height of the header labels.
Const LabelOffset As Integer = 10 ' Offset to get the header to align correctly to first column in listbox
Private myListBox As Object
Private myParent As Object
Private lblHeaders() As MSForms.Label
Private sColumnWidths() As Single
Public Property Set ListBox(ListBox As Object)
Set myListBox = ListBox
Set myParent = ListBox.Parent
End Property
Public Property Let Headers(sHeaders As String)
Dim lLeft As Long, vHeaders As Variant
Dim iCol As Integer
With myListBox
vHeaders = Split(sHeaders, ";")
ReDim lblHeaders(.ColumnCount)
If UBound(sColumnWidths) = 0 Then
ReDim sColumnWidths(.ColumnCount)
For iCol = 1 To .ColumnCount
sColumnWidths(iCol) = .Width / .ColumnCount
Next
End If
lLeft = LabelOffset
For iCol = 1 To .ColumnCount
Set lblHeaders(iCol) = myParent.Controls.Add("Forms.Label.1")
With lblHeaders(iCol)
.Top = myListBox.Top - LabelHeight
.Left = lLeft + myListBox.Left
.Width = sColumnWidths(iCol)
.Height = LabelHeight
lLeft = lLeft + sColumnWidths(iCol)
.Visible = True
.Caption = vHeaders(iCol - 1)
.ZOrder fmZOrderFront
End With
Next
End With
End Property
Public Property Let ColumnWidths(ColumnWidths As String)
Dim vSplit As Variant
Dim lLeft As Long
Dim iCol As Integer
With myListBox
vSplit = Split(ColumnWidths, ";")
ReDim sColumnWidths(.ColumnCount)
For iCol = 1 To .ColumnCount
sColumnWidths(iCol) = vSplit(iCol - 1)
Next
lLeft = LabelOffset
If UBound(lblHeaders) > 0 Then
For iCol = 1 To .ColumnCount
With lblHeaders(iCol)
.Left = myListBox.Left + lLeft
.Width = sColumnWidths(iCol)
lLeft = lLeft + sColumnWidths(iCol) ' + LabelOffset
End With
Next
End If
End With
End Property
Public Property Get Labels() As Variant
Dim iCol As Integer
Dim vLabels As Variant
With myListBox
ReDim vLabels(.ColumnCount - 1)
For iCol = 1 To .ColumnCount
Set vLabels(iCol - 1) = lblHeaders(iCol)
Next
End With
Labels = vLabels
End Property
Public Sub Clear()
Dim i As Integer
For i = 1 To UBound(lblHeaders)
myParent.Controls.Remove lblHeaders(i).Name
Next
Class_Initialize
End Sub
Private Sub Class_Initialize()
ReDim lblHeaders(0)
ReDim sColumnWidths(0)
End Sub