mYnDstrEAm
mYnDstrEAm

Reputation: 789

How to create a ListBox with checkboxes in a Microsoft Access Form?

I'm new to Microsoft Access and would like to create a ListBox (or ListView) with checkboxes, however I can't find any native way for doing so.

My intention is to display a list of values and have some of the values checked depending on what value is selected in a ComboBox on the form.

Please note that I'm needing such a control for a form and not a table (for which there's this "multivalued lookup field"). (Besides if there's a way to create a subform with a table with just the multivalue-column that reacts to what's selected in the ComboBox.)
An ordinary list box with the "Multi Select" property set to "Simple" doesn't display checkboxes.
I also can't see the "ListStyle" property described here.
Maybe it's somehow possible to display two columns in the ListBox of which the first is rendered as checkbox?

Upvotes: 6

Views: 25870

Answers (3)

mYnDstrEAm
mYnDstrEAm

Reputation: 789

So got it working now with the help of Andre's answer:

First, as the ListView is dependent on the currently selected item of a table I'm populating it via the Form_Current event of the table. (Simply by Call Forms.Item("MainForm").PopulateListView)

Here's the working PopulateListView method (note that you need to reference Microsoft Windows Common Controls 6.0 first):

Public Sub PopulateListView()
    On Error GoTo ErrorHandler
    Dim intToCount As Integer
    Dim intCount1 As Integer
    Dim intCount2 As Integer
    Dim intToCount2 As Integer
    Dim intCount12 As Integer
    Dim intCount22 As Integer
    Dim NewLine As Object
    Dim db As Database
    Dim rs As Recordset
    Dim colNew As Object
    Dim s As String

    ' Clear the ListView control.
    Forms![MainForm].[SubForm].Form.[ctlListView].ListItems.Clear
    Forms![MainForm].[SubForm].Form.[ctlListView].ColumnHeaders.Clear

    ' Set Variables.
    Set db = CurrentDb    
    Set rs = db.OpenRecordset("SELECT A, B, IsChecked . . .")

    ' Set Column Headers.
    Set colNew = Forms![MainForm].[SubForm].Form.[ctlListView].ColumnHeaders.Add(, , "A", 2000)
    Set colNew = Forms![MainForm].[SubForm].Form.[ctlListView].ColumnHeaders.Add(, , "B", 4000)

    ' Set Total Records Counter.
    rs.MoveLast
    intToCount = rs.RecordCount
    rs.MoveFirst

    ' Loop through recordset and add Items to the control. Twice as a workaround to sort by checkbox.
    For intCount1 = 1 To intToCount
        If (rs(2).value = 1) Then
            If IsNumeric(rs(0)) Then
                s = Trim(Str(rs(0).value))
            Else
                s = Trim(rs(0).value)
            End If

            Set NewLine = Forms![MainForm].[SubForm].Form.[ctlListView].ListItems.Add(, , s)
            If IsNull(rs(1)) Then
                NewLine.ListSubItems.Add Text:=""
            Else
                NewLine.ListSubItems.Add Text:=rs(1).value
            End If
            NewLine.Checked = True
        End If
        rs.MoveNext
    Next intCount1

    ' Set Total Records Counter.
    rs.MoveLast
    intToCount2 = rs.RecordCount
    rs.MoveFirst

    For intCount12 = 1 To intToCount2
        If (rs(2).value = 0) Then
            If IsNumeric(rs(0)) Then
                s = Trim(Str(rs(0).value))
            Else
                s = Trim(rs(0).value)
            End If

            Set NewLine = Forms![MainForm].[SubForm].Form.[ctlListView].ListItems.Add(, , s)
            If IsNull(rs(1)) Then
                NewLine.ListSubItems.Add Text:=""
            Else
                NewLine.ListSubItems.Add Text:=rs(1).value
            End If
        End If
        rs.MoveNext
    Next intCount12
Exit Sub
ErrorHandler:
    ' Err 3021 = no current record. Err 2455 = happens at necessary first call of method and couldn't catch in code.
    If Err = 91 Or Err = 3021 Or Err = 2455 Then
       Resume Next
    Else
        If Err <> 94 Then
            ' Otherwise display the error message.
            MsgBox "Error: " & Err.Number & Chr(13) & Chr(10) & Err.Description & vbCrLf & "(PopulateListView)"
        End If
    End If
End Sub

Then for saving I'm using this:

For Each Item In Forms![MainForm].[SubForm].Form.[ctlListView].Object.ListItems
   If Item.Checked = True Then
     'Use Item here
   End If
Next

Upvotes: 1

Andre
Andre

Reputation: 27634

You can use the ListView control. It is located under ActiveX Controls, the full name is Microsoft ListView Control, version 6.0.

It has a separate set of properties: right-click -> ListViewCtrl object -> Properties, in there is the Checkboxes property.

To fill the listview with data, see e.g. ACC: Sample Function to Fill a ListView Control

More info: Using the ListView Control

Edit
To comfortably work with the Listview object model, set a reference to Microsoft Windows Common Controls 6.0 = C:\Windows\SysWOW64\MSCOMCTL.OCX on my Windows7 64bit.

Edit 2

I use a TreeView with checkboxes. Each Node has a Checked property, that checks or unchecks its checkbox. Where the Treeview has Nodes, the Listview has ListItems, but they have a Checked property too.

Simplified code for Treeview (without hierarchies):

Dim oTree As TreeView
Dim oNode As Node
Dim RS As Recordset

Set oTree = Me.myTreeView.Object
oTree.Nodes.Clear

Set RS = DB.OpenRecordset("My query to fill the treeview")  
Do While Not RS.EOF
    Set oNode = oTree.Nodes.Add(key:=RS!foo, Text:=RS!bar)
    oNode.Checked = (RS!someValue > 0)
    RS.MoveNext
Loop
RS.Close

Upvotes: 7

Gustav
Gustav

Reputation: 55806

You can't modify a listbox of Access like that, but you can customize a subform in datasheet view to mimic such a listbox.

To display more or less fixed values, create a small local table to be bound by the form and fill it with the values you need.

Upvotes: 2

Related Questions