Reference List Box Column by Field Name

。_饼干妹妹 提交于 2020-01-05 05:55:34

问题


I have an MS Access form in which selection of a list box item determines how many other aspects of the application behave.

I have a table containing an ID and description and several other fields which correspond to settings for other aspects of the application; this table is the Row Source of the list box.

The list box is configured such that the first two columns (ID & Description) are visible, with the widths of the remaining columns set to 0 - the Column Widths property of the list box is therefore something like:

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

Within my application I then reference the remaining fields using expressions such as:

MyListBox.Column(n)

However, this relies heavily on the order of the fields in the table, and if I then decide to add another field to my table, I have to:

  • Increment the list box Column Count
  • Add another zero to the semi-colon delimited Column Widths
  • Potentially change the identifiers used in the various Column(n) statements, depending on where the new field was added in the table.

My original reason for using this approach was to avoid the need to repeatedly open a RecordSet to obtain the values of the additional fields associated with the item selected from the list box.

Is there a way to reference list box fields by field name rather than by column number?

(Or is there an entirely better way to approach this task?)


回答1:


While I'm hearing a lot of No, not possible, this actually is possible for list boxes that have a row source type of Table/Query, by using the ListBox.RecordSet property.

For combo boxes, this is easy, since the recordset moves along with the selected value. For list boxes, it doesn't, so you will have to know the name and position of the ID column (or, if the ID column is the bound column, just use the .Value property)

Example:

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

Add code to check if a value is selected, if the recordset property is set, and if a match is found if needed.




回答2:


Get the value from a list box/combo box by referencing its field name

I have a listbox that contains 30+ columns but only a few are visible. When a row in the listbox is selected, I need to grab values from columns on the selected row and display them in other fields or use them to enable/disable other controls. Over the years there have been various people supporting this application and sometimes a column gets added or re-positioned in a new order. This causes havoc for references like this:

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

It's hard to debug code written like this and keep track of each column position.

I had an idea to reference each column by name instead of by its column position and I created a function to make the code more readable and writable.

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

Is there a way to reference list box fields by field name rather than by column number?

I believe this function or the method used within it addresses your question. The error handler will show you the available field names if you try to address a column name that is not present.

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

As a bonus, I have a simpler function that can return the name of a column if you pass in the index.

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


来源:https://stackoverflow.com/questions/48853790/reference-list-box-column-by-field-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!