Begin

ADO Recordset

Het Recordset object.

Zoals bij DAO is het object ADODB.Recordset is waarschijnlijk het meeste gebruikte object van ADO. Vooral wanneer men toegang wil hebben tot de data van een database voor bewerkingsdoeleinden, en in het bijzonder op één rij. Men kan een aantal eigenschappen instellen die de mogelijkheden van de recordset bepalen, cursor type, lock type,cursor plaats, en de recordset opties.
In ADO is de cursor het object die regelt in welke zin men doorheen een recordset kan bewegen, en indien er wijzigingen aan de data van de recordset kunnen aangebraccht worden.
Syntax:

	Dim con As New ADODB.Connection
            Set con = CurrentProject.Connection
            rst.Open Bron,Connectie,CursorType,LockType,Opties
        
  1. Bron
    • Naam van een tabel
    • Naam van een query
    • Naam van een SQL expressie
  2. Connectie
    • De actieve connectie
  3. CursorType
    • adOpenDynamic : alle wijzigingen aangebracht door andere gebruikers zijn zichtbaar, alle bewegingen doorheen de recordset zijn mogelijk, en bookmarks zijn ook toegelaten.
    • adOpenKeySet : toont veel overeenkomsten met adOpenDynamic, rijen toegevoegd door andere gebruikers zijn evenwel niet zichtbaar.
    • adOpenStatic : wijzigingen aangbebracht door andere gebruikers zijn niet zichtbaar.
    • adOPenForwardOnly : toont veel overeenkomsten met adOpenStatic, men kan evenwel enkel voorwaarts in de recordset bewegen.
  4. LockType
    • adLockReadOnly : de recordset is alleen lezen en kan niet bewerkt worden, is standaard wanneer geen LockType ingesteld is.
    • adLockPessimistic : van zodra men gegevens bewerkt kan de andere gebruiker geen wijzigingen meer aanbrengen.
    • adLockOptimistic : enkel wanneer de Update-methode toegepast wordt kunnen andere gebruikers geen wijzigingen aanbrengen.
    • adLockBatchOptimistic : voor recordsets waar de UpdateBatch methode zal toegepast worden.
  5. Opties
    • adCmdText : evalueert de bron als een SQL expressie
    • adCmdTable : geeft alle rijen van de tabel of query die in de bron opgegeven werd
    • adCmdTableDirect : practisch identiek aan adCmdTable
    • adCmdUnKnown : indien er geen optie opgegeven wordt, gaat na indien de bron een tabel of een query is.
    • adCmdFile : de bron is de naam van een persisted recordset.

Een Recordset creëren voorbeeld.

Hier een voorbeeld met een tabel als bron, kan ook met SQL-Expressie of Query

	Sub sADO_RST()
            Dim con As New ADODB.Connection
            Set con = CurrentProject.Connection
            Dim rst As ADODB.Recordset
            Set rst = New ADODB.Recordset

        'rst.Open "tblOrders", con, adOpenKeyset, adLockOptimistic
            'rst.open "qselOrders",con,adOpenKeyset, adLockOptimistic
                rst.Open "SELECT * FROM tblOrders WHERE IDOrder > " & 20000 & ";", con, adOpenKeyset, adLockOptimistic
                Debug.Print rst.RecordCount

            rst.Close
            Set rst = Nothing
            con.Close
            Set con = Nothing
        End Sub
Top

Bewegen doorheen een Recordset.

Vooraf enkele Eigenschappen: als men door een Recordset wil bewegen moet men vooral controleren indien er wel degelijk rijen (records) aanwezig zijn.

  • BOF betekent dat men op het eerste record zit (BOF = True)
  • EOF betekent dat men op het laatste record zit (EOF = True)

Beide eigenschappen laten toe om te controleren indien men geen 'lege' Recordset heeft

If Not rst.BOF And Not rst.EOF Then
            'er zijn wel degelijk rijen in de Recordset
        'End If
        
  • RecordCount is een eigenschap die het aantal rijen in een Recordset geeft, en laat ook toe te controleren indien men geen 'lege' Recordset heeft.
If rst.RecordCount > 0 Then
            'er zijn wel degelijk rijen in de Recordset
        End If
        

Er zijn 5 methoden waarmee men door een Recordset kan bewegen:

  1. MoveFirst -> ga naar de eerste rij
  2. MoveLast -> ga naar de laatste rij
  3. MovePrevious -> ga naar de voorgaande rij
  4. MoveNext -> ga naar de volgende rij
  5. Move -> doorloopt opgegeven rijen, zowel voorwaarts (positief) als achterwaarts (negatief), en dit vanaf de huidige rij of vanaf een bewaarde Bookmark.
    rst.Move aantalrijen, Bookmark(optioneel)
Sub sADO_RST()
            Dim con As New ADODB.Connection
            Set con = CurrentProject.Connection
            Dim rst As ADODB.Recordset
            Set rst = New ADODB.Recordset
            Dim lngTel As Long


                rst.Open "SELECT * FROM tblOrders WHERE IDOrder > " & 20000 & ";", con, adOpenKeyset, adLockOptimistic
                Debug.Print "Het aantal rijen :" & rst.RecordCount
            rst.MoveFirst
        'met MoveNext methode door Recordset bewegen tot einde
                Do Until rst.EOF
                    lngTel = lngTel + 1
                    rst.MoveNext
                Loop
                Debug.Print "Het aantal rijen geteld bij het bewegen van eerste naar laatste rij: " & lngTel
            rst.MovePrevious
                Debug.Print "Het IDOrder van de laatste rij: " & rst("IDOrder")
        'met Move methode 100 rijen terug gaan
            rst.Move -100
            Debug.Print "IDOrder 100 rijen terug " & rst("IDOrder")
            rst.Close
            Set rst = Nothing
            con.Close
            Set con = Nothing
        End Sub
        
Top

Zoeken met de Seek methode.

Als bij DAO is Seek de snelste methode, daar men op indexen zoekt. Het is evenwel noodzakelijk dat de recordset geopend werd met de adCmdTableDirect optie. Zoniet zal de Seek-methode een foutbericht genereren. Hier geen operatoren als bij DAO maar wel Seek opties:

  • adSeekAfterEq : zoek naar de index die gelijk is aan de opgegeven waarde.Indien geen match de volgende index.
  • adSeekAfter : zoek naar de index volgend op deze waar de match gevonden werd.
  • adSeekBeforeEQ : zoek naar de index die gelijk is aan de opgegeven waarde. Indien geen match de vorige index
  • adSeekBefore : zoek naar de index juist voor deze waar de match gevonden werd.
  • adSeekFirstEq : de eerste sleutel die gelijk is aan de opgegeven waarde.
  • adSeekLastEq : de laatste sleutel die gelijk is aan de opgegeven waarde.

Men dient eerst de recordset Index eigenschap instellen, gewoonlijk is dit de primaire sleutel 'PrimaryKey';

Sub sADO_Seek_RST()
        Dim con As New ADODB.Connection
            Set con = CurrentProject.Connection
            Dim rst As ADODB.Recordset
            Set rst = New ADODB.Recordset

            rst.Open "tblOrders", con, adOpenKeyset, adLockOptimistic, adCmdTableDirect

            rst.Index = "PrimaryKey"
            rst.Seek 15183, adSeekAfterEQ
                Debug.Print "adSeekAfterEQ: " & rst("IDOrder")
        '15163 is de eerste sleutelwaarde
            rst.Seek 15162, adSeekAfterEQ
                Debug.Print "adSeekAfterEQ 15162: " & rst("IDOrder")
            rst.Seek 15183, adSeekAfter
                Debug.Print "adSeekAfter: " & rst("IDOrder")
            rst.Seek 15183, adSeekBeforeEQ
                Debug.Print "adSeekBeforeEQ: " & rst("IDOrder")
        '30419 is de laatste sleutelwaarde
            rst.Seek 30420, adSeekBeforeEQ
                Debug.Print "adSeekBeforeEQ 30420: " & rst("IDOrder")
            rst.Seek 15183, adSeekBefore
                Debug.Print "adSeekBefore: " & rst("IDOrder")
        'zal tweemaal dezelfde waarde opleveren daar in dit voorbeeld de indexen uniek zijn
            rst.Seek 15183, adSeekFirstEQ
                Debug.Print "adSeekFirstEQ: " & rst("IDOrder")
            rst.Seek 15183, adSeekLastEQ
                Debug.Print "adSeekLastEQ: " & rst("IDOrder")
        rst.Close
            Set rst = Nothing
            con.Close
            Set con = Nothing
        End Sub
        

Geeft volgende uitslag in de immidiate window :
adSeekAfterEQ: 15183
adSeekAfterEQ 15162: 15163
adSeekAfter: 15184
adSeekBeforeEQ: 15183
adSeekBeforeEQ 30420: 30419
adSeekBefore: 15182
adSeekFirstEQ: 15183
adSeekLastEQ: 15183

Top

Zoeken met de Find methode.

Find is heel wat flexibeler als de Seek methode.Het kan tevens aangewend worden in 'Loops', gezien men niet hoeft te starten van het begin van de recordset.
Syntax:

	Recordset.find Criteria, SkipRows,SearchDirection,Start
                
  • Criteria, is wat volgt op WHERE van een SQL-expressie, zonder WHERE evenwel en met slechts één veldnaam.
    1. strings moeten omgeven worden door '
    2. datum moet omgeven worden #
    3. er kan gebruik gemaakt worden van de Like operator met de * wildcard
  • SkipRows bepaalt het aantal rijen, te beginnen vanaf de actieve rij, waarna het zoeken moet starten.
  • SearchDirection
    1. adSearchForward
    2. adSearchBackward
  • is een optionele bookmark vanaf dewelke het zoeken begint
Sub sADO_Find_RST()
                Dim con As New ADODB.Connection
                    Set con = CurrentProject.Connection
                    Dim rst As ADODB.Recordset
                    Set rst = New ADODB.Recordset
                    Dim intTel As Integer
                    Dim strZoek As String

                    strZoek = "KlantVoornaam = 'Anja'"
                    rst.Open "SELECT * FROM tblKlant ;", con, adOpenDynamic, adLockOptimistic

                    rst.Find strZoek
                        Do While Not rst.EOF
                            Debug.Print rst("KlantNaam") & " " & rst("KlantVoornaam")
                            intTel = intTel + 1
                            rst.Find strZoek, 1
                        Loop
                            Debug.Print intTel & " gevonden!"
                rst.Close
                Set rst = Nothing
                con.Close
                Set con = Nothing
                End Sub
                
Top

Data bewerken in een ADO recordset.

Een eerste vereiste is dat de recordset bewerken toelaat. Zie 'cursortype' en 'locktype' hierboven. Wanneer bewerken niet toegestaan is krijgt men foutmelding, die natuurlijk met een goede foutbehandeling te onderscheppen is.
Eeen essentieel verschil met DAO bestaat er in dat bij ADO het recorset-object geen Edit-methode kent. De Utdate-methode bestaat wel, maar is in principe niet vereist. Persoonlijk gebruik ik de Update-methode wel, al was het maar omwille van de leesbaarheid van de code.

  • Data wijzigen :
    1. Ga naar de gewenste rij
    2. Breng de wijzigingen aan
    3. Gebruik de Update methode van de recordset.
  • Een nieuwe rij toevoegen :
    1. Gebruik de AddNew methode van de recordset
    2. Voeg de data toe
    3. Gebruik de Update methode van de recordset
  • Een rij verwijderen
    1. Ga naar de gewenste rij
    2. Gebruik de Delete methode van de recordset
Een rij bewerken
                Public Sub sADO_Wijzig_RST()
                Dim con As New ADODB.Connection
                Dim rst As New ADODB.Recordset
                Dim lngIDKlant As Long
                lngIDKlant = 3411
                Set con = CurrentProject.Connection
                rst.Open "SELECT * FROM tblKlant WHERE IDKlant = " & lngIDKlant, con, adOpenKeyset, adLockOptimistic
                If Not rst.BOF And Not rst.EOF Then
                    rst("KlantNaam") = "Verstraeten"
                    rst.Update
                End If
                rst.Close
                Set rst = Nothing
                con.Close
                Set con = Nothing
                End Sub
                Een rij toevoegen
                Public Sub sADO_ToevoegenRij_RST()
                Dim con As New ADODB.Connection
                Dim rst As New ADODB.Recordset
                
                Set con = CurrentProject.Connection
                rst.Open "tblKlant", con, adOpenDynamic, adLockOptimistic
                
                    rst.AddNew
                    rst("IDTypeKlant") = 7
                    rst("KlantNaam") = "Debrabandere"
                    rst("KlantVoornaam") = "Jerom"
                    rst("KLantGes") = "M"
                    rst("KlantGemeente") = "Brugge"
                    rst("KlantPCode") = 8000
                    rst("KlantGebDat") = #6/21/1965#
                    rst.Update
                
                rst.Close
                Set rst = Nothing
                con.Close
                Set con = Nothing
                End Sub
                Een rij verwijderen.
                Public Sub sADO_VerwijderenRij_RST()
                Dim con As New ADODB.Connection
                Dim rst As New ADODB.Recordset
                Dim lngIDKlant As Long
                lngIDKlant = 4410
                
                Set con = CurrentProject.Connection
                
                rst.Open "SELECT * FROM tblKlant WHERE IDKlant = " & lngIDKlant, con, adOpenKeyset, adLockOptimistic
                'Opgepast men krijgt geen verwitting dat men een record zal verwijderen.
                    If Not rst.BOF And Not rst.EOF Then
                        rst.Delete
                        rst.Update
                    End If
                
                rst.Close
                Set rst = Nothing
                con.Close
                Set con = Nothing
                End Sub
            
Top

Recordset bewaren (Persisting recordsets)

Met ADO kan men een recordset als een bestand lokaal op de harde schijf bewaren. Het is mogelijk om later de recordset opnieuw te openen, te wijzigen om deze te bewaren in de oorspronkelijke databron.

Ooit ontwierp ik met collega Paul van 'The Mokker Technologies' een equete-toepassing die bestond uit :

  1. Een Access-toepassing (klein in omvang) voor het afnemen van de enquete die bestond uit 36 vragen met bijhorende mogelijkheid tot het geven van commentaar. Deze werd via email naar +- 2500 gebruikers gestuurd. Eens ingevuld werd een recordset in een bestand bewaard, die automatisch in bijlage van een email-bericht verstuurd werd naar de verantwoordelijke die instond voor de verwerking. Die beschikte over :
  2. Een centrale Access-toepassing waar in één beweging alle recordset bestanden ingeladen werden om toegevoegd te worden in één tabel. En waar de gegevens automatisch verwerkt werden.

Een vijftal jaren werd deze applicatie met succes toegepast.
Syntax.

	rst.save  bestandnaam, format
                Voorbeeld :
                Public Sub sADO_Bewaar_RST()
                Dim con As New ADODB.Connection
                Dim rst As New ADODB.Recordset
                Dim strBestand As String

                Set con = CurrentProject.Connection
                rst.Open "tblKlant", con, adOpenDynamic, adLockOptimistic

                strBestand = CurrentProject.Path & "\klanten.adtg"

                    rst.Save strBestand, adPersistADTG

                rst.Close
                Set rst = Nothing
                con.Close
                Set con = Nothing
                End Sub
                

Tenslotte hieronder de code om alle recordset-bestanden in de centrale MS Access- toepassing in te laden.

Private Sub cmdImporteer_Click()
                Dim con As ADODB.Connection
                Dim rstCont As ADODB.Recordset
                Dim rstScore As ADODB.Recordset
                Dim rstCom As ADODB.Recordset
                Dim rstBest As ADODB.Recordset 'de *.dat files inde IN Map
                Dim rstExtern As ADODB.Recordset ' openen recordset van de *.dat files
                Dim fso As FileSystemObject
                Dim strMapDB As String ' Map van de database
                Dim strEval As String
                Dim intI As Integer
                Dim intDum As Integer
                On Error GoTo FoutBehandeling

                Set con = CurrentProject.Connection
                strMapDB = GetDirectory
                Set rstBest = New ADODB.Recordset
                rstBest.Open "tblBestand", con, adOpenKeyset, adLockOptimistic
                rstBest.MoveFirst
                Do Until rstBest.EOF
                    'over welke evaluator gaat het
                    strEval = Left$(rstBest![BestNaam], Len(rstBest![BestNaam]) - 4)
                    'zo reeds aanwezig de gegevens van deze evaluator verwijderen
                    DoCmd.SetWarnings False
                    DoCmd.RunSQL "DELETE * From tblMedewCom WHERE IDEval = """ & strEval & """"
                    DoCmd.RunSQL "DELETE * From tblMedewScore WHERE IDEval = """ & strEval & """"
                    DoCmd.RunSQL "DELETE * FROM tblMedewCont WHERE IDEval = """ & strEval & """"
                    DoCmd.SetWarnings True
                rstBest.MoveNext
                Loop
                rstBest.Close
                Set rstBest = Nothing
                Set fso = New FileSystemObject
                'bestandsnamen inlezen
                Set rstBest = New ADODB.Recordset
                rstBest.Open "tblBestand", con, adOpenKeyset, adLockOptimistic

                DoCmd.Hourglass True
                rstBest.MoveFirst

                Do Until rstBest.EOF
                intDum = intDum + 1  ' om te tellen hoeveel bestanden er ingelezen worden

                Set rstExtern = New ADODB.Recordset
                rstExtern.Open strMapDB & "IN/" & rstBest![BestNaam], Options:=adCmdFile
                    rstExtern.MoveFirst

                    Set rstCont = New ADODB.Recordset
                    rstCont.Open "tblMedewCont", con, adOpenKeyset, adLockOptimistic
                    Set rstScore = New ADODB.Recordset
                    rstScore.Open "tblMedewScore", con, adOpenKeyset, adLockOptimistic
                    Set rstCom = New ADODB.Recordset
                    rstCom.Open "tblMedewCom", con, adOpenKeyset, adLockOptimistic

                    For intI = 1 To 18
                        rstScore.AddNew
                        rstScore![IDMedew] = rstExtern![IDMedew]
                        rstScore![IDGedragsInd] = rstExtern![IDGedragsInd]
                        rstScore![IDEval] = rstExtern![IDEval]
                        rstScore![IDFunctCrit] = rstExtern![IDFunctCrit]
                        rstScore![Score] = rstExtern![Score]
                        rstScore.Update
                        'rstScore.Save


                        rstCom.AddNew
                        rstCom![IDMedew] = rstExtern![IDMedew]
                        rstCom![IDEval] = rstExtern![IDEval]
                        rstCom![IDGedragsInd] = rstExtern![IDGedragsInd]
                        rstCom![IDFunctCrit] = rstExtern![IDFunctCrit]
                        rstCom![Com] = rstExtern![Com]
                        rstCom![ComNr] = rstExtern![ComNr]
                        rstCom.Update

                        On Error Resume Next ' om geen foutbericht dubbel primary kring te krijgen
                        rstCont.AddNew
                        rstCont![IDMedew] = rstExtern![IDMedew]
                        rstCont![IDEval] = rstExtern![IDEval]
                        rstCont![IDFreqContact] = rstExtern![IDFreqContact]
                        rstCont.Save
                        On Error GoTo FoutBehandeling
                    rstExtern.MoveNext
                    Next intI

                'na import bestand verplaatsen naar VERW Map
                    fso.MoveFile strMapDB & "IN/" & rstBest![BestNaam], strMapDB & "VERW/" & rstBest![BestNaam]

                    rstBest.MoveNext
                    Loop
                MsgBox "Resultaten van " & intDum & " Evaluator(en) ingeladen.", vbOKOnly + vbInformation, cstrToep
                Me.subBestand.Visible = False
                Verlaten:
                On Error Resume Next
                DoCmd.SetWarnings True
                DoCmd.Hourglass False
                rstCont.Close
                Set rstCont = Nothing
                rstScore.Close
                Set rstScore = Nothing
                rstCom.Close
                Set rstCom = Nothing
                rstBest.Close
                Set rstBest = Nothing
                rstExtern.Close
                Set rstExtern = Nothing
                Set fso = Nothing
                con.Close
                Set con = Nothing
                    Exit Sub
                FoutBehandeling:
                    If Not dhError("cmdImporteer_Click") Then
                            Stop
                    End If
                Resume Verlaten
                End Sub
                
Top
Begin