参考列表框按字段名称列

时间:2018-02-18 16:15:12

标签: ms-access listbox access-vba

我有一个MS Access表单,其中选择列表框项目可确定应用程序的其他方面的行为。

我有一个包含ID和描述的表以及与应用程序其他方面的设置相对应的其他几个字段;此表是列表框的Row Source

配置列表框,使前两列(ID& Description)可见,其余列的宽度设置为0 - 列表框的Column Widths属性为因此像:

1cm;5cm;0cm;0cm;0cm;0cm;0cm;0cm;0cm;0cm;0cm;0cm;0cm

在我的应用程序中,我然后使用以下表达式引用其余字段:

MyListBox.Column(n)

但是,这在很大程度上依赖于表中字段的顺序,如果我决定将另一个字段添加到表中,我必须:

  • 增加列表框列数
  • 将另一个零添加到以分号分隔的列宽度
  • 可能会更改各种Column(n)语句中使用的标识符,具体取决于表中添加新字段的位置。

我使用这种方法的原始原因是为了避免重复打开RecordSet以获取与从列表框中选择的项目相关联的附加字段的值。

有没有办法按字段名称而不是按列号引用列表框字段?

(或者有更好的方法来完成这项任务吗?)

3 个答案:

答案 0 :(得分:1)

通过引用其字段名称从列表框/组合框获取值

我有一个包含30多个列的列表框,但是只有少数可见。当选择列表框中的一行时,我需要从所选行的列中获取值并将其显示在其他字段中,或使用它们启用/禁用其他控件。多年来,有许多人支持此应用程序,有时会以新顺序添加或重新定位列。这会导致像这样的引用的破坏:

        txtFlow_Peak = lstPOC_ID.Column(27)
        txtFlow_Avg = lstPOC_ID.Column(29)

很难调试像这样编写的代码并跟踪每个列的位置。

我有一个想法是按名称而不是按列位置来引用每一列,并且我创建了一个函数来使代码更具可读性和可写性。

        txtFlow_Peak = GetColumnValueFromName(lstPOC_ID, "Flow_Peak")
        txtFlow_Avg = GetColumnValueFromName(lstPOC_ID, "Flow_Avg")
  

是否可以通过字段名称而不是字段名称来引用列表框字段   按列号?

我相信此功能或其中使用的方法可以解决您的问题。如果您尝试解决不存在的列名,错误处理程序将为您显示可用的字段名。

Public Function GetColumnValueFromName(ctl As Control, ColumnName As String) As String
' Pass in a listbox/combobox control and a column name and return the value from that column.
' This lets you address a column by its name instead of the index which can be awkward
' if there are a lot of columns.
' This code is expecting a control that is bound to a Table/Query.
' Ben S. - 11/8/2019

    On Error GoTo ErrorHandler

    Dim strMsg As String
    Dim fld As Field

    If ctl.Recordset Is Nothing Then
        ' Recordset is not loaded.
    ElseIf ctl.ListIndex = -1 Then
        ' No current row.
    Else
        'Debug.Print ctl.Name; Tab(20); "Column " & ColumnName & " (" & ctl.Recordset.Fields(ColumnName).OrdinalPosition & ") = '" & ctl.Column(ctl.Recordset.Fields(ColumnName).OrdinalPosition) & "'"

        GetColumnValueFromName = ctl.Column(ctl.Recordset.Fields(ColumnName).OrdinalPosition)  
    End If

Exit_Function:
    Exit Function

ErrorHandler:

    Debug.Print "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "
    strMsg = "Error #" & err.Number & " - " & err.Description & vbCrLf & "in procedure GetColumnValueFromName" & vbCrLf
    strMsg = strMsg & vbCrLf & "Control name = " & ctl.Name _
        & vbCrLf & "Passed column name = '" & ColumnName & "'" & vbCrLf

    If err.Number = 3265 Then ' Item not found in this collection.
        ' Build a list of columns in the recordset to help the developer pick the correct column name.
        strMsg = strMsg & vbCrLf & "Available Columns:" & vbCrLf
        For Each fld In ctl.Recordset.Fields
            strMsg = strMsg & fld.OrdinalPosition & " - " & fld.Name & vbCrLf
        Next
    End If

    Debug.Print strMsg
    MsgBox strMsg, vbExclamation, "GetColumnValueFromName()"

    GoTo Exit_Function
    Resume Next
    Resume
End Function

作为奖励,我有一个更简单的函数,如果您传入索引,该函数可以返回列的名称。

Public Function GetColumnNameFromIndex(ctl As Control, ColumnIndex As Long) As String
' Pass in a listbox/combobox control and a column number and return
' the field name of that column.
' Ben S. - 11/8/2019

    If ctl.Recordset Is Nothing Then
        ' Recordset is not loaded.
    ElseIf ctl.ListIndex = -1 Then
        ' No current row.
    Else
        'Debug.Print ctl.Name; Tab(20); "Column " & ctl.Recordset.Fields(ColumnIndex).Name & " (" & ColumnIndex & ") = '" & ctl.Column(ColumnIndex) & "'"

        GetColumnNameFromIndex = ctl.Recordset.Fields(ColumnIndex).Name
    End If
End Function

答案 1 :(得分:0)

虽然我听到了很多 No,not possible ,但实际上这对于行源类型 Table / Query 的列表框来说是可行的,使用ListBox.RecordSet属性。

对于组合框,这很容易,因为记录集随着所选值一起移动。对于列表框,它没有,所以你必须知道ID列的名称和位置(或者,如果ID列是绑定列,只需使用.Value属性)

示例:

Dim rs As DAO.Recordset
Set rs = Me.List1.Recordset.Clone
rs.FindFirst "ID = " & Me.List1.Value
Debug.Print rs.Fields!Field1

添加代码以检查是否选择了值,是否设置了记录集属性,以及是否在需要时找到匹配项。

答案 2 :(得分:0)

您可以遍历列名并在找到所需的列名时停止并返回位置编号。

下面的函数应该为你做。

Public Function fn_find_lb_column(lb As ListBox, strColName As String)

   'this function returns the position of a column in a list box

    Dim intColPos As Integer
    Dim intColCount As Integer

    intColCount = lb.ColumnCount

    'Debug.Print lb.RowSource

    intColPos = -1

    For i = 0 To intColCount - 1
    
       'Debug.Print lb.Column(i, 0)
        If strColName = lb.Column(i, 0) Then
            intColPos = i
            Exit For
        End If

    Next i

exit_here:

    fn_find_lb_column = intColPos

    Exit Function

err_h:

    intColPos = -1

    Resume exit_here

End Function

您可以这样称呼它。

ColumnPos = fn_find_lb_column(Me!ListBox, "ColumnName"))
ColumnVal = Me!ListBox.Column(ColumnPos)

ColumnVal = Me!ListBox.Column(fn_find_lb_column(Me!ListBox, "ColumnName"))