Returning the index of a field in a recordset

不羁的心 提交于 2019-12-24 06:22:10

问题


I have a recordset object generated by the following code.

Private Sub GetID_Click()

'first find max id on sheet; used for if no ID is found on sheet
Dim myRange As Range
Dim maxIdOnSheet As Long
Dim clientSheet As Worksheet

Set clientSheet = Sheets("Client Codes")
Set myRange = clientSheet.Range("A1:A1048576")
maxIdOnSheet = WorksheetFunction.max(myRange) + 1

'set up connections with Nina's housing database
Dim cmd As New ADODB.Command
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strConn As String
Dim strSQL As String
Dim IDdb As Long
Dim IDwb As Long

'connection string
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\db\path\here\db.accdb; Persist Security Info=False"

'open connection database
conn.Open strConn

'sql statement
strSQL = "SELECT * FROM Clients WHERE (((Clients.FirstName)='" & FirstName.Value & "') AND ((Clients.LastName)='" & LastName.Value & "'));"

'open connection with the recordset
rs.Open strSQL, conn, adOpenDynamic, adLockOptimistic

'use the late-bound application match method to find out where the firstname and lastname values are in the worksheet, if found
Dim first As Long
Dim last As Long
Dim foundWB As Boolean
Dim foundDB As Boolean

foundWB = False
foundDB = False

Dim base As Long
Dim curRow As Long

base = 1

'First check to make sure if both values are in the worksheet
If Not IsError(Application.Match(FirstName.Value, Range("c" & base & ":c1048576"), False)) And Not IsError((Application.Match(LastName.Value, Range("b" & base & ":b1048576"), False))) Then
    'if it is in the worksheet, find where it is
    While found = False
        first = Application.Match(FirstName.Value, Range("c" & base & ":c1048576"), False)
        last = Application.Match(LastName.Value, Range("b" & base & ":b1048576"), False)
        If first = last Then
            foundWS = True
            curRow = curRow + first
            IDwb = Cells(curRow, 1)
        Else
            If first < last Then
                base = first + 1
                curRow = curRow + first
            ElseIf last < first Then
                base = last + 1
                curRow = curRow + last
            End If
        End If
    Wend
Else
    'if its not in the WS, it is now the highest +1
    IDwb = WorksheetFunction.max(Range("a1:a1048576")) + 1
End If

'find if its in the database
If rs.EOF Then
    'if its not in the database, find the highest number and add 1
    rs.Close
    strSQL = "SELECT MAX(Clients.[Client ID]) FROM Clients;"
    rs.Open strSQL, conn, adOpenDynamic, adLockOptimistic
    IDdb = rs.Fields(0) + 1
    MsgBox (rs.Properties.Item("Address"))
Else
    'if it is, find the first column
    IDdb = rs.Fields(0)
    foundDB = True
    MsgBox (rs.Properties.Item("Address"))
End If

If foundWB = True Then
    ClientID.Value = IDwb
ElseIf foundDB = True Then
    ClientID.Value = IDdb
Else
    If IDdb > IDwb Then
        ClientID.Value = IDdb
    ElseIf IDwb > IDdb Then
        ClientID.Value = IDwb
    Else
        ClientID.Value = IDwb
    End If
End If

End Sub

I have two data sources - the worksheet this macro is located in Excel, and an Access database. I enter client data, and assign it a specific code. The code does that successfully.

I also want to fill out a userform based on that code which is received. The code above successfully queries the database and can get the client ID. I also want things like address, city, state, zip, household income, that is stored in the DB, from the query.

If I was doing this in strictly Excel, I would use a match statement, and if strictly through Access, a SQL query. I'm trying to run this query on both an Excel worksheet and an Access database at the same time, or in the same code. This requires setting up a recordset object: documentation is found here http://www.w3schools.com/asp/ado_ref_recordset.asp and here https://msdn.microsoft.com/en-us/library/ms675841(v=vs.85).aspx.

I know that I can get the information with something like

name = rs.fields(1)
address = rs.fields(4)
city = rs.fields(5)
'...

I'd rather get the index dynamically. If people change the database around I'd like for the formula to be stable.

Lets say if the field "Address" could be index 4, 5, 6, 7, until whenever.

How do I dynamically find the index of a specific field in a recordset object?


回答1:


So, how do I dynamically find the index of a specific field in a recordset object? Lets say if the field "Address" could be index 4,5,6,7, until whenever.

There isn't a direct property in an ADO recordset to get this, but you can find it by looping through the fields and keeping a tally like I do in this function:

Public Function GetRecordsetFieldIndexFromName(rs As adodb.Recordset, ColumnName As String) As Variant
' Pass in an ADODB recordset and a column name and return the column index.
' Returns index in base 0.
' Ben S. - 11/8/2019

    On Error GoTo ErrorHandler

    Dim i As Long

    If rs Is Nothing Then
        ' Recordset is not loaded
    Else
        For i = 0 To rs.Fields.count - 1
            'Debug.Print i, rs.Fields(i).Name
            If rs.Fields(i).Name = ColumnName Then
                GetRecordsetFieldIndexFromName = i
                Exit For
            End If
        Next
    End If

Exit_Function:
    Exit Function

ErrorHandler:
    MsgBox "Error #" & err.Number & " - " & err.Description & vbCrLf & "in procedure GetRecordsetFieldIndexFromName"
    GoTo Exit_Function
    Resume Next
    Resume
End Function

Here is a simple test that you can try in Access.

Public Sub TestADOrs()
' BS 11/8/2019 - Test for GetRecordsetFieldIndexFromName

    Dim i           As Long
    Dim strSQL      As String
    Dim conn        As New adodb.Connection
    Dim rs          As New adodb.Recordset

    ' Set an object pointing to the current database connection
    Set conn = CurrentProject.Connection
    strSQL = "Select Top 1 * From MSysObjects"
    rs.Open strSQL, conn, adOpenStatic, adLockOptimistic

    Debug.Print GetRecordsetFieldIndexFromName(rs, "Flags") ' This should return 4

    Set rs = Nothing
    Set conn = Nothing

End Sub

I made similar functions to this that work with List Box and Combo Box controls. They will let you return the index or the value from the control by passing the control and the column/field name.
https://stackoverflow.com/a/58773219/1898524 - Reference List Box Column by Field Name



来源:https://stackoverflow.com/questions/41839902/returning-the-index-of-a-field-in-a-recordset

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