如何在 Microsoft Access 表单中创建带复选框的列表框?

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

我是 Microsoft Access 的新手,想创建一个带有复选框的 ListBox(或 ListView),但是我找不到这样做的任何本机方法。

我的目的是显示一个值列表,并根据在表单的组合框中选择的值检查一些值。

请注意,我需要这样一个表单控件,而不是 table(为此 "multivalued lookup field")。 (此外,如果有一种方法可以创建一个带有 table 的子表单,该子表单仅包含对 ComboBox 中所选内容做出反应的多值列。)
"Multi Select" 属性 设置为 "Simple" 的普通列表框不显示复选框。
我也看不到 "ListStyle" 属性 描述的 here.
也许以某种方式可以在 ListBox 中显示两列,其中第一列呈现为复选框?

您不能像这样修改 Access 的列表框,但您可以在数据表视图中自定义子窗体以模仿这样的列表框。

要显示或多或少的固定值,请创建一个小的本地 table 以受表单约束并用您需要的值填充它。

您可以使用ListView控件。它位于ActiveX Controls下,全称是Microsoft ListView Control, version 6.0.

它有一组单独的属性:右击->ListViewCtrl对象->属性,里面有Checkboxes属性.

要用数据填充列表视图,请参见例如ACC: Sample Function to Fill a ListView Control

更多信息:Using the ListView Control

编辑
要舒适地使用 Listview 对象模型,请在我的 Windows7 64 位上设置对 Microsoft Windows Common Controls 6.0 = C:\Windows\SysWOW64\MSCOMCTL.OCX 的引用。

编辑 2

我使用带复选框的 TreeView。每个 Node 都有一个 Checked 属性,用于选中或取消选中其复选框。 Treeview 有节点,Listview 有 ListItems,但它们也有 Checked 属性。

Treeview 的简化代码(无层次结构):

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

所以在 Andre 的回答的帮助下它现在可以工作了:

首先,由于 ListView 依赖于 table 的当前选定项,我通过 Form_Current 事件填充它 table。 (只需 Call Forms.Item("MainForm").PopulateListView

这是有效的 PopulateListView 方法(请注意,您需要先参考 Microsoft Windows Common Controls 6.0):

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

然后为了节省我使用这个:

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