我有一个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以获取与从列表框中选择的项目相关联的附加字段的值。
有没有办法按字段名称而不是按列号引用列表框字段?
(或者有更好的方法来完成这项任务吗?)
答案 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"))