Just playing around with an idea of making list boxes and combo boxes have the column width autoresize based on the content of those same column and thought I’d share a first run at the concept.
List box/Combo box Auto-resizing Columns Code
The concept is straight forward, run through the contents of the control and identify the longest entry in each column, then calculate the require width to display that ‘longest’ entry and resize the column to match (+ a little buffer).
Main Sub
Enum ResizeTechnique
ExplicitSizing = 1 'Based on required text size -> may go beyond the width of the listbox requiring scrollbars
SizeToFit = 2 'Percentage Ratio -> force everything within the width of the listbox, content may be cut-off
End Enum
'---------------------------------------------------------------------------------------
' Procedure : Control_AutoSizeColumns
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Auto-resize list box/combo box column to match the longest entry
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
' (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: None required
' Dependencies: String_Dimensions() & Enum ResizeTechnique
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' oCtrl : List box or Combo box control to resize to columns of
' lResizeTechnique : Resizing technique to apply
'
' Usage:
' ~~~~~~
' Control_AutoSizeColumns(Me.List0, ExplicitSizing)
'
'' Control_AutoSizeColumns(Me.Combo0, SizeToFit)
'
' Revision History:
' Rev Date(yyyy-mm-dd) Description
' **************************************************************************************
' 1 2024-03-29 Initial Release
'---------------------------------------------------------------------------------------
Sub Control_AutoSizeColumns(oCtrl As Access.Control, _
Optional lResizeTechnique As ResizeTechnique = ExplicitSizing)
On Error GoTo Error_Handler
Dim lNoCols As Integer
Dim lNoRows As Long
Dim lColCounter As Long
Dim lRowCounter As Long
Dim aMaxColEntries() As String
Dim lHeight As Long
Dim lWidth As Long
Dim sColWidths As String
Dim aCtrlColWidths() As String
Dim lTotalReqWidth As Long
Const lBuffer = 150
lNoCols = oCtrl.ColumnCount
lNoRows = oCtrl.ListCount
' Determine the biggest entries per column
' ****************************************************************************************
'Size the array
ReDim aMaxColEntries(lNoCols - 1, 0)
'Initialize the array with the 1st row values
For lColCounter = 0 To lNoCols - 1
aMaxColEntries(lColCounter, 0) = oCtrl.Column(lColCounter, lRowCounter)
Next lColCounter
'Process all the other rows
For lRowCounter = 1 To lNoRows - 1
For lColCounter = 0 To lNoCols - 1
'Debug.Print , Me.List0.Column(lColCounter, lRowCounter)
If Len(oCtrl.Column(lColCounter, lRowCounter)) > Len(aMaxColEntries(lColCounter, 0)) Then
aMaxColEntries(lColCounter, 0) = oCtrl.Column(lColCounter, lRowCounter)
End If
Next lColCounter
Next lRowCounter
aCtrlColWidths = Split(oCtrl.ColumnWidths, ";")
If UBound(aCtrlColWidths) <> lNoCols - 1 Then
Debug.Print "Number of data columns doesn't match number of column defined in the Column Widths"
Exit Sub
End If
If lResizeTechnique = ExplicitSizing Then
' Determine the require width to fit
' ****************************************************************************************
For lColCounter = 0 To lNoCols - 1
'Debug.Print lColCounter, aMaxColEntries(lColCounter, 0)
With oCtrl
If CLng(aCtrlColWidths(lColCounter)) = 0 Then
sColWidths = sColWidths & 0 & ";"
Else
Call String_Dimensions(lHeight, lWidth, aMaxColEntries(lColCounter, 0), .FontName, .FontSize, .FontWeight, .FontItalic, .FontUnderline, 0, 0)
sColWidths = sColWidths & lWidth + lBuffer & ";"
lTotalReqWidth = lTotalReqWidth + lWidth + lBuffer
End If
End With
'Debug.Print lWidth
Next lColCounter
Else
'Calculate Total Width Required
For lColCounter = 0 To lNoCols - 1
If CLng(aCtrlColWidths(lColCounter)) = 0 Then
lTotalReqWidth = lTotalReqWidth + 0
Else
With oCtrl
Call String_Dimensions(lHeight, lWidth, aMaxColEntries(lColCounter, 0), .FontName, .FontSize, .FontWeight, .FontItalic, .FontUnderline, 0, 0)
End With
lTotalReqWidth = lTotalReqWidth + lWidth + lBuffer
End If
Next lColCounter
For lColCounter = 0 To lNoCols - 1
If CLng(aCtrlColWidths(lColCounter)) = 0 Then
sColWidths = sColWidths & 0 & ";"
Else
With oCtrl
Call String_Dimensions(lHeight, lWidth, aMaxColEntries(lColCounter, 0), .FontName, .FontSize, .FontWeight, .FontItalic, .FontUnderline, 0, 0)
End With
sColWidths = sColWidths & (oCtrl.Width / lTotalReqWidth) * (lWidth + lBuffer) & ";"
End If
Next lColCounter
End If
oCtrl.ColumnWidths = sColWidths
If oCtrl.ControlType = acComboBox And lResizeTechnique = ExplicitSizing Then
oCtrl.ListWidth = lTotalReqWidth
Else
oCtrl.ListWidth = oCtrl.Width
End If
Error_Handler_Exit:
On Error Resume Next
Exit Sub
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Source: Control_AutoSizeColumns" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Sub
Helper Procedure(s)
The above requires a WizHook helper function to be able to calculate the height/width of the string of text based on the specified font.
'---------------------------------------------------------------------------------------
' Procedure : String_Dimensions
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Retrieve the height/width of a string based on a specified font
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
' (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: None required
' References:
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' lHeight : Variable to return the height with
' lWidth : Variable to return the width with
' sCaption : String to calculate the dimension of
' sFontName : Name of the font to calculate the dimension of
' lSize : Size of the font to calculate the dimension of
' lWeight : Weight of the font to calculate the dimension of
' bItalic : Is the font italicied
' bUnderline : Is the font underlined
' lCch : Average character width - leave 0
' lMaxWidthCch : How many character to consider the max char width - leave 0
'
' Revision History:
' Rev Date(yyyy-mm-dd) Description
' **************************************************************************************
' 1 2024-03-29 Initial Release
'---------------------------------------------------------------------------------------
Public Function String_Dimensions(ByRef lHeight As Long, _
ByRef lWidth As Long, _
ByVal sCaption As String, _
ByVal sFontName As String, _
ByVal lSize As Long, _
Optional ByVal lWeight As Long = 400, _
Optional bItalic As Boolean = False, _
Optional bUnderline As Boolean = False, _
Optional lCch As Long = 0, _
Optional lMaxWidthCch As Long = 0) As Double
On Error GoTo Error_Handler
Dim dx As Long
Dim dy As Long
Const lBuffer = 15
WizHook.Key = 51488399
WizHook.TwipsFromFont sFontName, lSize, lWeight, bItalic, bUnderline, lCch, sCaption, lMaxWidthCch, dx, dy
lHeight = dy + lBuffer
lWidth = dx + lBuffer
Error_Handler_Exit:
On Error Resume Next
Exit Function
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Source: String_Dimensions" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Function
Implementation Of The Code
Nothing could be easier! With the above, we can now auto-resize any list box/combo box with a single line of code.
Call Control_AutoSizeColumns(Me.List2)
Call Control_AutoSizeColumns(Me.List2, SizeToFit)
Beware
This code is a proof of concept, just playing around with an idea I had in my head, and has not been thoroughly tested.
For short lists of choices this will work perfectly, but for long lists it might be best to limit the iteration to try and limit the performance impact it may make on the loading of your form/report.
Also, in the above, I’ve hard-coded the list separator as ‘;’, but depending on your regional settings this may not be true and thus would need to be adjusted accordingly, or better yet should be implemented using the concepts elaborated in my internationalization article:

%100 String Width Verification
If you truly want to validate things, instead of using the Len() to find the longest string entered, one would need to calculate the string width for every single value. That said, I chose not to do this above as this can have performance implications and I’ve found, generally speaking, the Len() approach to be acceptable. That said, below would be the 100% accurate approach if it should interest you.
'---------------------------------------------------------------------------------------
' Procedure : Control_AutoSizeColumns
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Auto-resize list box/combo box column to match the longest entry
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
' (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: None required
' Dependencies: String_Dimensions() & Enum ResizeTechnique
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' oCtrl : List box or Combo box control to resize to columns of
' lResizeTechnique : Resizing technique to apply
'
' Usage:
' ~~~~~~
' Control_AutoSizeColumns(Me.List0, ExplicitSizing)
'
'' Control_AutoSizeColumns(Me.Combo0, SizeToFit)
'
' Revision History:
' Rev Date(yyyy-mm-dd) Description
' **************************************************************************************
' 1 2024-03-29 Initial Release
'---------------------------------------------------------------------------------------
Sub Control_AutoSizeColumns(oCtrl As Access.Control, _
Optional lResizeTechnique As ResizeTechnique = ExplicitSizing)
On Error GoTo Error_Handler
Dim lNoCols As Integer
Dim lNoRows As Long
Dim lColCounter As Long
Dim lRowCounter As Long
Dim aMaxColEntries() As String
Dim lHeight As Long
Dim lWidth As Long
Dim sColWidths As String
Dim aCtrlColWidths() As String
Dim lTotalReqWidth As Long
Const lBuffer = 150
lNoCols = oCtrl.ColumnCount
lNoRows = oCtrl.ListCount
' Determine the biggest entries per column
' ****************************************************************************************
'Size the array
ReDim aMaxColEntries(lNoCols - 1, 0)
'Initialize the array with the 1st row values
For lColCounter = 0 To lNoCols - 1
With oCtrl
Call String_Dimensions(lHeight, lWidth, oCtrl.Column(lColCounter, 0), .FontName, .FontSize, .FontWeight, .FontItalic, .FontUnderline, 0, 0)
End With
aMaxColEntries(lColCounter, 0) = lWidth
Next lColCounter
'Process all the other rows
For lRowCounter = 1 To lNoRows - 1
For lColCounter = 0 To lNoCols - 1
With oCtrl
Call String_Dimensions(lHeight, lWidth, oCtrl.Column(lColCounter, lRowCounter), .FontName, .FontSize, .FontWeight, .FontItalic, .FontUnderline, 0, 0)
End With
If lWidth > aMaxColEntries(lColCounter, 0) Then
aMaxColEntries(lColCounter, 0) = lWidth
'Debug.Print lColCounter, lWidth
End If
Next lColCounter
Next lRowCounter
aCtrlColWidths = Split(oCtrl.ColumnWidths, ";")
If UBound(aCtrlColWidths) <> lNoCols - 1 Then
Debug.Print "Number of data columns doesn't match number of column defined in the Column Widths"
Exit Sub
End If
If lResizeTechnique = ExplicitSizing Then
' Determine the require width to fit
' ****************************************************************************************
For lColCounter = 0 To lNoCols - 1
With oCtrl
If CLng(aCtrlColWidths(lColCounter)) = 0 Then
sColWidths = sColWidths & 0 & ";"
Else
sColWidths = sColWidths & aMaxColEntries(lColCounter, 0) + lBuffer & ";"
lTotalReqWidth = lTotalReqWidth + aMaxColEntries(lColCounter, 0) + lBuffer
End If
End With
Next lColCounter
Else
'Calculate Total Width Required
For lColCounter = 0 To lNoCols - 1
If CLng(aCtrlColWidths(lColCounter)) = 0 Then
lTotalReqWidth = lTotalReqWidth + 0
Else
lTotalReqWidth = lTotalReqWidth + aMaxColEntries(lColCounter, 0) + lBuffer
End If
Next lColCounter
For lColCounter = 0 To lNoCols - 1
If CLng(aCtrlColWidths(lColCounter)) = 0 Then
sColWidths = sColWidths & 0 & ";"
Else
sColWidths = sColWidths & (oCtrl.Width / lTotalReqWidth) * (aMaxColEntries(lColCounter, 0) + lBuffer) & ";"
End If
Next lColCounter
End If
oCtrl.ColumnWidths = sColWidths
If oCtrl.ControlType = acComboBox And lResizeTechnique = ExplicitSizing Then
oCtrl.ListWidth = lTotalReqWidth
Else
oCtrl.ListWidth = oCtrl.Width
End If
Error_Handler_Exit:
On Error Resume Next
Exit Sub
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Source: Control_AutoSizeColumns" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Sub
You use the same Enum, helper function as the previous example and it is used in the exact same manner.
Comparison
I decided to do a quick test or 2 to truly evaluate the performance difference.
Using 10,000 records in a combo box, the 1st approach took 0.4785062 to load Vs. the 2nd approach taking 7.1207778, for a % diff of 174.813%.
Using 100 records in a combo box, the 1st approach took 0.0084455 to load Vs. the 2nd approach taking 0.0743012, for a % diff of 159.174%.
So, as you can see, there is a performance cost if you want 100% certitude in the width calculation.