Voorbeeldbestand
ADODB Recordset


1. Wat is een ADODB Recordset ?

2. Waarvoor een ADODB Recordset ?

3. Achtergrond van ADODB Recordset

4. Maak een ADODB Recordset
4.1 Early binding
4.1.1 Local scope
4.1.2 Private scope
4.1.3 Public scope
4.2 Late binding
4.2.1 Local scope
4.2.2 Private scope
4.2.3 Public scope

5. ADODB Recordset struktuur
5.1 Velden definiŽren
5.2 Velden verzameling
5.3 Veldeigenschappen
5.4 Veld verwijderen
5.5 Struktuur vastleggen
5.6 Records maken
5.7 Records uit Excel Range
5.8 Records uit Listobject
5.9 Records toevoegen

6. Externe gegevens
6.1 ADTG bestand
6.2 XML bestand
6.3 Access bestand
6.4 Excel bestand
6.5 Text bestand
6.6 geopend Excel bestand

7. Aantal records
7.1 Aantal gekoppelde records

8. Record wijzigen
8.1 Gekoppeld Record wijzigen

9. Records sorteren
9.1 Op 1 veld
9.2 Op 1 veld op- /aflopend
9.3 Op meer velden
9.4 Op meer velden op- /aflopend
9.5 Sortering opheffen

10. Record zoeken
10.1 Vooruit zoeken
10.2 Achteruit zoeken
10.3 Records overslaan
10.4 Zoekcriteria
10.5 Record bestaat ?

11. Records filteren
11.1 Filter op 1 veld
11.2 Filter op 2 velden
11.3 Filter opheffen

12. Recordset opslaan
12.1 .GetString
12.2 .GetRows
12.2.0.1 Application.Transpose
12.2.0.2 ActiveX ListBox
12.2.0.3 VBA-Array
12.2.1 Recordselektie
12.2.2 Veldselektie
12.2.3 Veldvolgorde
12.3 .CopyFromRecordset
12.4 .Save
12.4.1 ADTG bestand
12.4.2 XML bestand
12.4.3 Excel naar XML

13. Record verwijderen
13.1 Niet-gekoppeld record
13.2 Diverse records
13.3 Alle records met filter
13.4 Alle records met loop
13.5 Gekoppeld record
13.5.1 Access >2003 record
13.5.2 Access <2007 record
13.5.3 XML record
13.5.4 ADTG record
13.5.5 CSV record
13.5.6 Excel record


14. Trefwoorden

1. Wat is een ADODB Recordset ?

Een ADODB Recordset in VBA is een verzamelobject: je kunt er allerlei verschillende zaken in opbergen: getallen, teksten, datums.
Een ADODB Recordset is een database die je volledig in het werkgeheugen kunt ontwerpen, vullen en bewerken.

VBA heeft verschillende andere mogelijkheden om gegevens op te slaan:
- een dictionary
- een collection
- een array variabele
- een ActiveX ComboBox
- een ActiveX ListBox
- een Userform control ComboBox
- een Userform control ListBox
- een sortedlist

De keuze voor een van deze methoden is afhankelijk van het te bereiken doel.
In deze pagina wordt geen poging gedaan al deze methoden met elkaar te vergelijken.
We beperken ons tot een bespreking van de mogelijkheden van de ADODB Recordset.

De meeste 'verzamel' methoden hebben geen sorteermethode.
De sorteermethode van de ADODB Recordset is de enige mij bekende VBA-sorteermethode waarmee op verschillende velden kan worden gesorteerd.
Deze sorteermethode is erg snel.
Bovendien is deze sorteermethode heel bijzonder.
In de wiskunde wordt het een 'stable sort' genoemd.
Dat betekent dat items met gelijke waarden de volgorde behouden waarin ze aan de verzameling zijn toegevoegd.
Ook bevat de ADODB Recordset een ingebouwde filtermethode.
Dat kunnen argumenten zijn om juist van een ADODB Recordset gebruik te maken.

Omdat de ADODB recordset een aparte VBA bibliotheek heeft kun je deze methode in alle Office applicties (Word, Access, OUtlook, Excel, Powerpoint, etc.) gebruiken.

In deze pagina ga ik niet alle aspekten van de ADODB Recordset behandelen.
Ik beperk me tot de eigenschappen en methoden die vergelijkbaar zijn met de andere 'verzamel'methoden in VBA die ik hierboven noemde.

2. Waarvoor kun je een ADODB Recordset gebruiken ?

Je kunt de ADODB Recordset gebruiken om gegevens uit allerlei bronnen bij elkaar te zetten en snel te bewerken omdat ze via de ADODB Recordset in het werkgeheugen geladen zijn en snel toegankelijk zijn.
In plaats van gegevens te bewerken in een Excel-werkblad, een Word Document, een Powerpointpresentatie, doe je dat in het werkgeheugen.
Daarvoor hoeft bijv. geen scherm ververst te worden, berekeningen uitgevoerd te worden, waardoor de ADODB Recordset snel is.

3. Waar komt de ADODB Recordset vandaan ?

De ADODB Recordset maakt geen deel uit van de standaard VBA-bibliotheek.
De ADODB Recordset is onderdeel van de bibliotheek "ADODB.Recordset".
Die vind je in de VBEditor; tabblad 'Tools', optie 'References' als Microsoft ActiveX Data Objects 2.0 Library.
Die bevindt zich in het bestand ....\Common Files\System\Ado\msado20.tlb of in een vergelijkbare directory.

Je kunt via de VBEditor een aktieve verbinding leggen naar dit bestand door Microsoft ActiveX Data Objects 2.0 Library bij de Referenties aan te vinken (Extra/referenties... of Tools/References..)
Als je een bestand waarin je gebruik maakt van een ADODB Recordset verspreidt, wordt meteen ook die verbinding naar deze bibliotheek meeverspreid.

In VBA kun je op twee verschillende manieren die referentie maken
ThisWorkbook.VBProject.References.AddFromFile "C:\Common Files\System\Ado\msado20.tlb"
of met
ThisWorkbook.VBProject.References.AddFromguid "{BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}", 2, 4
Om gebruik te kunnen maken van de ADODB Recordset hoeft er geen referentie aktief te zijn ('early binding').
Je kunt de code ook pas een verbinding laten leggen op het moment dat je de ADODB Recordset nodig hebt ('late binding').
Daarvoor gebruik je dan deze VBA code:
createobject("ADODB.Recordset")

4. Hoe maak je een ADODB Recordset ?

Er zijn verschillende methoden om een ADODB Recordset aan te maken.
Dat is afhankelijk van:
- de manier waarop je naar de bibliotheek van de ADODB Recordset wil verwijzen: 'early binding' of 'late binding'
- de 'scope' van de ADODB Recordset: wil je hem in 1 procedure of meer procedures gebruiken:'local scope','private scope','public scope'

4.1 Met referentie naar de bibliotheek: 'early binding'

4.1.1 Local scope

Als je de ADODB Recordset alleen maar nodig hebt in 1 macro of funktie kun je de definitie van de ADODB Recordset tot die procedure beperken.
zonder toewijzing aan een variabele:
With new ADODB.Recordset
.Fields.Append "aa1", 129, 120
end with
declaratie en toewijzing tegelijkertijd
dim db_00 as New ADODB.Recordset
db_00.Fields.Append "aa1", 129, 120
toewijzing en daardoor impliciete declaratie
set db_00 = New ADODB.Recordset
db_00.Fields.Append "aa1", 129, 120
gescheiden declaratie (als Object) en toewijzing
dim db_00 as Object
Set db_00 = new ADODB Recordset
db_00.Fields.Append "aa1", 129, 120
gescheiden declaratie (als ADODB Recordset) en toewijzing
dim db_00 as ADODB.Recordset
Set db_00= new ADODB Recordset
.Fields.Append "aaa", 129, 120

4.1.2 Private scope

Als je een ADODB.Recordset toegankelijk wil maken voor verschillende procedures (macro's of funkties) in 1 werkblad, werkboek, Userform, Macromodule of Classmodule maak je gebruik van Private Scope.
Dan dien je altijd met een variabele te werken.
Die variabele moet je eerst in het declaratiegebied van de codemodule declareren.

Je kunt het gegevenstype van de variabele voor een ADODB.Recordset declareren als Object, ADODB.Recordset of Variant.
Omdat de Variant het default gegevenstype is, kun je de specificatie van dit gegevenstype ook achterwege laten.

In het declaratiedeel van de codemodule zet je
Dim db_00
Private db_00
of
Dim db_00 as Variant
Private db_00 as Variant
of
Dim db_00 as Object
Private db_00 as Object
of
Dim db_00 as ADODB.Recordset
Private db_00 as ADODB.Recordset
In een procedure (macro of funktie) zet je dan
Set db_00 = New ADODB.Recordset
Het kan ook heel compact met in het declaratiegebied slechts deze code
Dim db_00 As New ADODB.Recordset
of
Private db_00 as New ADODB.Recordset
Daarna is de ADODB Recordset via de variabele db_00 in iedere procedure van de codemodule beschikbaar.

4.1.3 Public scope

Als je een ADODB Recordset toegankelijk wil maken voor alle procedures (macro's of funkties) in het werkboek, Userform, Macromodule of Classmodule maak je gebruik van Public Scope.
Dan dien je altijd met een variabele te werken.

4.1.3.1 Gelijktijdige declaratie en toewijzing

Om een variabele beschikbaar te maken in alle macro's en funkties van een codemodule moet je de variabele declareren in het declaratiegebied van de codemodule.
Vervolgens moet je aan de variabele een nieuwe instantie van de ADODB Recordset toewijzen.
Wanneer je gebruik maakt van 'early binding' kan dat heel compact in ťťn keer met deze code in het declaratiegebied.
Public db_00 As New ADODB.Recordset
Daarna is de ADODB Recordset via de variabele db_00 in iedere procedure van het VBproject (=het werkboek) beschikbaar.

4.1.3.2 Declaratie in het declaratiegebied en toewijzing in een procedure

Die variabele moet je eerst in het declaratiegebied van de codemodule van een macromodule declareren.

Je kunt het gegevenstype van de variabele voor een ADODB Recordset declareren als Object, ADODB.Recordset of Variant.
Omdat de Variant het default gegevenstype is, kun je de specificatie van dit gegevenstype ook achterwege laten.

In het declaratiegebied
Public db_00
of
Public db_00 as Variant
of
Public db_00 as Object
of
Public db_00 as ADODB.Recordset
In een procedure (macro of funktie)

Wijs een nieuwe instantie van de ADODB Recordset toe aan de gedeclareerde variabele.
Set db_00 = new ADODB.Recordset
Daarna is de ADODB Recordset via de variabele db_00 in iedere procedure van het VBproject (=het werkboek) beschikbaar.

4.2 Zonder referentie naar de bibliotheek: 'late binding'

4.2.1 Local scope

Als je de ADODB Recordset alleen maar nodig hebt in 1 macro of funktie kun je de definitie van de ADODB Recordset tot die procedure beperken.
zonder toewijzing aan een variabele:
With CreateObject("ADODB.Recordset")
db_00.Fields.Append "aa1", 129, 120
end with
met toewijzing aan een variabele:
set db_00 = CreateObject("ADODB.Recordset")
db_00.Fields.Append "aa1", 129, 120

4.2.2 Private scope

Als je een ADODB Recordset toegankelijk wil maken voor verschillende procedures (macro's of funkties) in 1 werkblad, werkboek, Userform, Macromodule of Classmodule maak je gebruik van Private Scope.
Dan dien je altijd met een variabele te werken.
Die variabele moet je eerst in het declaratiegebied van de codemodule declareren.

Je kunt het gegevenstype van de variabele voor een ADODB Recordset declareren als Object of Variant.
Omdat de Variant het default gegevenstype is, kun je de specificatie van dit gegevenstype ook achterwege laten.

Vervolgens wijs je in een procedure (macro of funktie) een nieuwe instantie van de ADODB Recordset toe aan de gedeclareerde variabele.

In het declaratiedeel van de codemodule
Dim db_00
Private db_00
of
Dim db_00 as Variant
Private db_00 as Variant
of
Dim db_00 as Object
Private db_00 as Object
In een procedure (macro of funktie)
Set db_00 = CreateObject("ADODB.Recordset")
Daarna is de ADODB Recordset via de variabele db_00 in iedere procedure van de codemodule beschikbaar.

4.2.3 Public scope

Als je een ADODB Recordset toegankelijk wil maken voor alle procedures (macro's of funkties) in het werkboek, Userform, Macromodule of Classmodule maak je gebruik van Public Scope.
Dan dien je altijd met een variabele te werken.
De declaratie van die variabele dient te staan in het declaratiegebied van een macromodule (dus niet in de codemodule van een userform, werkblad, het werkboek of een klassemodule).
In welke macromodule de declaratie staat maakt niet uit.

Het gegevenstype voor de ADODB Recordset kan zijn Variant of Object.
Omdat er nog geen verbinding is gelegd met de ADODB Recordset-bibliotheek kun je het gegevenstype 'ADODB.Recordset' niet gebruiken.

In een procedure (macro of funktie) wijs je een nieuwe instantie van de ADODB Recordset toe aan de gedeclareerde variabele.

In het declaratiedeel van de codemodule van een macromodule
Public db_00
of
Public db_00 as Variant
of
Public db_00 as Object
In een procedure (macro of funktie)
Set db_00 = CreateObject("ADODB.Recordset")
Daarna is de ADODB Recordset via de variabele db_00 in iedere procedure van het VBproject (=het werkboek) beschikbaar.

Voor het vervolg in deze pagina zal ik voor de overzichtelijkheid alleen gebruikmaken van de With ... End With methode in een 'late binding' situatie.

5. Een ADODB Recordset structureren

Een ADODB Recordset vergt een bepaalde volgorde van werken in VBA:

- Maak een nieuwe ADODB Recordset instantie
CreateObject("ADODB.Recordset")
- definieer de velden van de Recordset
.Fields.Append
- sla de gedefinieerde struktuur op
.Open
- voeg records toe
.Addnew
- vul de velden in het nieuwe record met gegevens
.fields(0)=".."
- voeg het gevulde record aan de recordset toe
.Update
De basisstruktuur van de VBA code voor een ADODB struktuur is dus:
With Createobject("ADODB.Recordset")
.Fields.Append
- - - - -
.Open
.Addnew
- - - - -
.Update
End with
Als je de instantie van de ADODB Recordset voor meer dan 1 'database' wil inzetten, moet je ook de methode .Close gebruiken.

Voordat een ADODB Recordset gevuld kan worden zullen we eerst de struktuur moeten vastleggen.
De velden bepalen de struktuur van een ADODB Recordset, net zoals in een database.
Als de velden zijn gedefinieerd kun je daarna records toevoegen en per record gegevens in de velden zetten.

5.1 Velden toevoegen en definiŽren

Er zijn veel (ca. 23) verschillende soorten velden beschikbaar.
Een belangrijk deel bestaat uit velden om compatibiliteit met oudere Access-versies te kunnen verzorgen.
Ik zal me beperken tot de meest voorkomende.

Een veld toevoegen doe je met de opdracht Fields.Append.
Voor de identificatie van het veld is het nodig dat die een unieke naam krjgt.
Bovendien moet je aangeven om wat voor soort veld het gaat.
Dat kun je doen met de 'DataTypeEnumeration', die weergegeven kan worden als naam/constante of als nummer/value.
In sommige gevallen (een tekstveld of een binaryveld) moet je de lengte van het veld aangeven.
Let erop dat je vervolgens in een veld alleen die gegevens kunt inlezen die overeenkomen met het soort veld.
Het werkt dus analoog aan het declareren van variabelen in VBA.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 120
.Fields.Append "bool_001", 11
.Fields.Append "curr_001", 6
.Fields.Append "date_001", 7
.Fields.Append "numeric_001", 131
.Fields.Append "dec_001", 14
.Fields.Append "double_001", 5
.Fields.Append "integer_001", 3
.Fields.Append "single_001", 4
.Fields.Append "binary_001", 128, 4
End With
of
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", adChar, 120
.Fields.Append "text_002", adChar, 120
.Fields.Append "bool_001", adBoolean
.Fields.Append "curr_001", adCurrency
.Fields.Append "date_001", adDate
.Fields.Append "numeric_001", adNumeric
.Fields.Append "dec_001", adDecimal
.Fields.Append "double_001", adDouble
.Fields.Append "integer_001", adInteger
.Fields.Append "single_001", adSingle
.Fields.Append "binary_001", adBinary, 4
End With

5.2 De verzameling van velden

De gedefinieerde velden vormen samen de struktuur van de ADODB Recordset (= Database).
De velden vormen de 'collection' Fields.
Het eerste veld is .Fields(0).

Zoals bij alle Collections kun je de collection 'aflopen' met:
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
for each it in .fields
msgbox it.name
next
End With
of met
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
for j = 0 to .fields.count - 1
msgbox .fields(j).name
next
End With

5.3 Veldeigenschappen

Ieder veld heeft een aantal eigenschappen die je kunt instellen of uitlezen.
Sommige eigenschappen zijn onafhankelijk van de waarden die ze uiteindeljk bevatten.
Andere eigenschappen zijn alleen maar uit te lezen als er records met waarden zijn toegevoegd.
Het is niet mogelijk via de eigenschap 'Name' de naam van het veld te wijzigen.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
msgbox .Fields(0).Name
msgbox .Fields(0).Precision
msgbox .Fields(0).Type
msgbox .Fields(0).Attributes
msgbox .Fields(0).DefinedSize
msgbox .Fields(0).NumericScale
msgbox .Fields(0).Status
End With
' "text_001"
' 0
' 200
' 0
' 120
' 0
' 0

5.4 Verwijder een veld

Voordat de veldstruktuur wordt opgeslagen met de opdracht .Open, kun je nog velden verwijderen, daarna niet meer.
Gebruik het indexnummer van het te verwijderen veld.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Fields.delete 0
End With

5.5 Bewaar de databasestruktuur: de gedefinieerde velden

De opdracht .Open slaat de databasestruktuur op.
Daarna kun je de struktuur niet meer wijzigen.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
End With

5.6 Records creŽren

De ADODB Recordset maakt een onderscheid tussen het creŽren van records en het toevoegen van gecreŽerde records aan de database.
De Methode .AddNew maakt een nieuw record, de methode 'Update' voegt gecreŽerde records toe aan de database.

Als je een record creŽert bestaat dat meteen uit een item met alle vooraf gedefinieerde velden.
De methode daarvoor is .Addnew.
Als je .Addnew sec gebruikt creŽer je een leeg nieuw record.
Daarna kun je een of meer velden vullen.
Daarvoor kun je de naam van het veld gebruiken of het indexnummer.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew
.Fields("text_001")="eerste veld"
.Fields(1)="tweede veld"
End With
Je kunt tegelijkertijd met het creŽren van een record ťťn van de velden vullen.
Gebruik dan in het eerste argument van de methode de naam of het indexnummer van het veld en in het tweede argument de waarde die je aan dat veld wil toekennen.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew "text_001","eerste veld"
.AddNew 1,"tweede veld"
End With
Je kunt ook meteen met het creŽren van een record diverse of alle velden van dat nieuwe record vullen.
Zet dan de namen of indexnummers van de te vullen velden als Array in het eerste argument van de methode .AddNew en de waarden die aan die velden moeten worden toegekend als Array in het tweede argument.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array("text_001","text_002"),Array("eerste veld","tweede veld")
.AddNew Array(0,1), Array("eerste veld","tweede veld")
End With
Welke waarden aan een veld toegekend kunnen worden is afhankelijk van de velddefinitie.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "bool_001", 11
.Open
.AddNew Array("text_001","bool_001"),Array("eerste veld",true)
.AddNew Array(0,1), Array("eerste veld",False)
End With
Het is niet nodig de velden van gemaakte records te vullen voordat ze aan de database kunnen worden toegevoegd, maar het is wel de handigste manier van werken.

5.7 Van een Excel Range records maken

Veronderstel dat in de Range "A1:E10" gegevens staan, waarbij de rijen als records worden beschouwd en de kolommen als velden.
Om de leesbewerkingen uit een werkblad tot een minimum te beperken zet je de gegevens in een array.
Dan kun je deze 10 records op de volgende manier lezen.
sn=sheets(1).Range("A1:E10")

With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Fields.Append "text_003", 129, 20
.Fields.Append "text_004", 129, 12
.Fields.Append "text_005", 129, 90
.Open
for j=1 to ubound(sn)
.AddNew Array(0,1,2,3,4),Array(sn(j,1),sn(j,2),sn(j,3),sn(j,4),sn(j,5))
next
End With

5.8 Van een Exceltabel (ListObject) records maken

Om de leesbewerkingen uit een werkblad tot een minimum te beperken komen de veldnamen en de gegevens in twee aparte arrays.
Voor de eenvoud van het voorbeeld krijgen de tekstvelden een lengte van 120 tekens.
sp = Application.Index(Sheet1.ListObjects(1).HeaderRowRange.Value, 1, 0)
sn = Sheet1.ListObjects(1).DataBodyRange.Value

With CreateObject("ADODB.recordset")
For Each it In sp
.Fields.Append it, 129, 120
Next

.Open
For j = 1 To UBound(sn)
.AddNew sp, Application.Index(sn, j)
next
End With

5.9 Records toevoegen

Een aangemaakt record voeg je aan de database toe met de opdracht .Update.
Dat kun je per record doen of als alle records zijn aangemaakt en gevuld.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "bool_001", 11
.Open
.AddNew Array(0,1), Array("eerste veld",False)
.Update
End With

6 Externe gegevens laden

Als je gegevens uit een bestand leest hoef je de struktuur van de database niet meer vast te leggen.
Ook interpreteert de driver automatisch om hoeveel velden en records het gaat.
Het bestand kan extern zijn, of het bestand waarin de macro staat.
Omdat de ADODB Recordset bibliotheek een database bibliotheek is, bevat die mogelijkheden dat verschillende gebruikers dezelfde database kunnen bewerken.
Dat wordt geregeld met een aantal eigenschappen: .CursorLocation en .LockType.
Standaard wordt een bestand als Read-only (.Locktype = adLockReadOnly 1) geopend.
Als je records wil wijzigen moet de .LockType parameter adLockPessimistic ( 2 ) of adLockOptimistic ( 3 ) zijn.
Om de gegevens te kunnen sorteren moet de eigenschap .CursorLoaction de waarde adUseClient (3) hebben.

6.1 ADTG bestand

Een ADTG bestand is een gegevensbestand dat de ADODB Recordset bibliotheek als standaard opslaat met de methode .Save.
Open een ADTG-bestand als Read-Only met de volgende code.
With CreateObject("ADODB.Recordset")
.Open "G:\OF\voorbeeld.adtg", "Provider=MSPersist", , , 256
End with
Open een ADTG-bestand waarin je wijzigingen wil aanbrengen met de volgende code.
With CreateObject("ADODB.Recordset")
.Open "G:\OF\voorbeeld.adtg", "Provider=MSPersist", , 3, 256
End with

6.2 XML bestand

De ADODB Recordset bibliotheek kan een recordset met de methode .Save opslaan als XML-bestand.
Open een XML-bestand met de volgende code.
With CreateObject("ADODB.recordset")
.Open "G:\OF\conversie.XML", "Provider=MSPersist", , , 256
End With

6.3 Access bestand

Lees alle velden van records in tabel Q_test uit Access bestand G:\OF\voorbeeld.accdb.
With CreateObject("ADODB.recordset")
.Open "SELECT * FROM Q_test", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=G:\OF\voorbeeld.accdb"
End With
Access-bestanden vůůr Office 2007
CreateObject("ADODB.Recordset")
.Open "SELECT * FROM Q_test", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=G:\OF\voorbeeld.mdb"
End With

6.4 Excel bestand

In de SQL string moet de naam staan (dus niet de Codename) van het werkblad met gegevens.
In de eerste rij van het werkblad dienen de veldnamen te staan.
De rijen in het werkblad worden als records geÔnterpreteerd.
Maak het VBA gemakkelijk en gebruik in het werkblad een tabel (VBA: Listobject).
With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM `Sheet1$`", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=G:\OF\voorbeeld.xlsb;Extended Properties=""Excel 12.0 Xml"""
End With

6.5 Tekstbestand

Een txt/csv bestand kan het best in de eerste regel de veldnamen bevatten, gescheiden door hetzelfde lijstscheidingsteken als in de regels met gegevens.
Om het bestand G:\OF\voorbeeld.txt te kunnen lezen komt de naam van het bestand in de SQL-string te staan.
Het pad naar het bestand is het tweede element van de Driverbeschrijving.
Het cursortype is adOpenStatic (3).
With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM `voorbeeld.txt`", "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=G:\OF\",3
End With

6.6 Een geopend Excelbestand

Speciale vermelding verdient de mogelijkheid de gegevens uit een geopend Excelbestand in een ADODB Recordset te lezen.
Vervolgens kan je deze gegevens met alle eigenschappen en methoden van de ADODB Recordset bewerken.
Die werken doorgaans veel sneller dan in Excel zelf.
With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM `" & thisworkbook.sheets(1).name &"$`", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & Thisworkbook.fullname & ";Extended Properties=""Excel 12.0 Xml"""
End With

7 Het aantal Records uitlezen

De eigenschap .Recordcount geeft het aantal records weer.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "tweede veld")
.AddNew Array(0,1), Array("tweede record","tweede veld")
.Update
msgbox .RecordCount
End With

7. Aantal Records in een gekoppeld bestand uitlezen

De eigenschap .Recordcount leest niet automatisch het aantal records in een gekoppeld bestand.
De eigenschap .CursorType bepaalt of de eigenschap .Recordcount het aantal records in het gekoppelde bestadn weergeeft.
Standaard gee .recordcount als resultaat -1.
Als je de eigenschap .Cursortype de waarde adOpenStatic (3) geeft, geeft .Recordcount het aantal records in het gekoppelde bestand weer.
With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM `voorbeeld.csv`", "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=G:\OF\", 3
MsgBox .RecordCount
End With

8 Een Record wijzigen

Welk record je kunt wijzigen is afhankelijk van de positie van de recordpointer.
Alleen de velden van het record waar de recordpointer staat kun je wijzigen.
De recordpointer verplaats je met
.MoveFirst: het eerste record
.MoveNext: het volgende record
.MoveLast: het laatste record
.MovePrevious: het vorige record
.Move 3: verplaats naar het 3e record na de huidige positie van de recordpointer
.Move -6 : verplaats naar het 6e record voor de huidige positie van de recordpointer
.Move 3, 1 : verplaats naar 3e record van de recordset (3e vanaf het eerste record)
.Move -7, 2: verplaats naar het op 7 na laatste record van de recordset.

Als met de methode .Find een resultaat wordt gevonden staat de recordpointer op de positie van het gezochte record
Na gebruik van de methode .Filter staat de recordpointer altijd op de positie van het eerste gefilterde record.

Voorbeeld: wijzig het tweede record
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open

.AddNew Array(0,1), Array("eerste veld", "tweede veld")
.AddNew Array(0,1), Array("tweede record","tweede veld")
.AddNew Array(0,1), Array("derde record","tweede veld")
.Update
.MoveFirst
.MoveNext
.Fields(0) = "gewijzigd"
End With

8.1 Een gekoppeld Record wijzigen

Wanneer je een koppeling legt naar een bestand, zoals in 6.1 t/m 6.6 zul je ervoor moeten zorgen dat je als gebruiker ook de bevoegdheid hebt wijzigingen in de records aan te brengen.
Standaard heb je die bevoegdheid nl. niet.
De eigenschap .CursorType regelt die bevoegdheid.
Standaard staat die eigenschap op adOpenForwardOnly (0).
Om de gebruiker Records te laten wijzigen wijzig je de eigenschap in adOpenDynamic (2).
Dat kun je doen in het tweede argument van de methode .Open.
Nadat je een veld in een aktief record hebt gewijzigd zet je die definitief in de database met de opdracht .Update.
With CreateObject("ADODB.Recordset")

.Fields(0)="nieuwe waarde"
.Update
End With

9 Records sorteren

De sorteeropties van de ADODB.Recordset maken deze bibliotheek uniek:
- je kunt op meer dan 1 veld sorteren
- je kunt per veld oplopend of aflopend sorteren
- de recordstruktuur blijft intact
- er is sprake van 'stable sorting': bij 'ties' wordt de volgorde waarin items aan de Recordset zijn toegevoegd gehandhaafd.
- het type veld (tekst of getallen/datums) bepaalt de sorteermethode (alphanumeriek of numeriek).
- de oorspronkelijke volgorde van de Database blijft intact.
- het is in VBA de eenvoudigste sorteermethode van een 2-dimensionele array op diverse velden.
- de sorteermethode is razendsnel.

NB. De sorteermethode werkt niet als er een koppeling is gelegd naar een bestand.

De sorteermethode is de eigenschap .Sort
De naam van het sorteerveld is de waarde die aan de eigenschap .Sort wordt toegekend.
De standaard (default) sorteermethode is oplopend (ascending).

9.1 Op 1 veld sorteren

Sorteren is een eigenschap van de ADODB Recordset.
Aan de sorteereigenschap wijs je de naam toe van het veld waarop gesorteerd moet worden.
Je kunt daarvoor vaste tekst ('hard coded') gebruiken of de eigenschap .Name van het betrokken veld.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "tweede veld")
.AddNew Array(0,1), Array("tweede record","tweede veld")
.Update
.Sort = "text_002"
.Sort = .Fields(1).Name
End With

9.2 Op 1 veld oplopend/aflopend sorteren

De standaard (default) sorteermethode is oplopend.
Zonder nadere specifikatie achter de veldnaam wordt op dat veld oplopend gesorteerd.
Oplopend sorteren kun je ook expliciet aangeven met ASC achter de veldnaam.
Aflopend sorteren geef je aan met DESC achter de veldnaam.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "tweede veld")
.AddNew Array(0,1), Array("tweede record","tweede veld")
.Update
.Sort = "text_002"
.Sort = "text_002 ASC"
.Sort = "text_002 DESC"
.Sort = .Fields(1).Name
.Sort = .Fields(1).Name & " ASC"
.Sort = .Fields(1).Name & " DESC"
End With

9.3 Op verschillende velden sorteren

Als je op verschillende velden wil sorteren zet je de veldnamen achter elkaar, gescheiden door een komma.
De volgorde van de sortering is gelijk aan de volgorde van de veldnamen in de eigenschap .Sort.
Records met gelijke waarden in een sorteerveld behouden de volgorde waarin ze aan de Recordset zijn toegevoegd: 'stable sort'.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "tweede veld")
.AddNew Array(0,1), Array("tweede record","tweede veld")
.Update
.Sort = "text_002,text_001"
.Sort = .fields(1).name & "," & .fields(0).name
End With

9.4 Op verschillende velden oplopend/aflopend sorteren

Per veld kun je (bij oplopend sorteren) of moet je (bij aflopend sorteren) de sorteervolgorde aangeven.
Achter iedere veldnaam zet je ASC of DESC.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "tweede veld")
.AddNew Array(0,1), Array("tweede record","tweede veld")
.Update
.Sort = "text_002,text_001"
.Sort = "text_002 ASC,text_001 ASC"
.Sort = .fields(1).name & " ASC," & .fields(0).name & " ASC"
.Sort = "text_002 DESC,text_001 DESC"
.Sort = "text_002 DESC,text_001"
.Sort = .fields(1).name & " DESC," & .fields(0).name & " DESC"
.Sort = .fields(1).name & " DESC," & .fields(0).name"
End With

9.5 Sortering opheffen

De sortering van de ADODB Recordset kun je opheffen door aan de eigenschap .Sort een lege tekstreeks toe te kennen.
De oorspronkelijke volgorde waarin de records aan de ADODB Recordset zijn toegevoegd is daarvan het resultaat.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "tweede veld")
.AddNew Array(0,1), Array("tweede record","tweede veld")
.Update
.Sort = "text_002,text_001"
.Sort = ""
End With

10 Een Record zoeken

De ADODB.Recordset kent geen object 'record'.
Het is dus niet mogelijk een record direkt 'uit te lezen' met code zoals bijv.
x0 = .records(4).fields(1)

De ADODB.Recordset werkt met een recordpointer.
De recordpointer bepaalt welk record het 'aktieve' record is.

De ADODB.recordset kent een zoekmethode: .Find
Deze methode kan slechts binnen de waarden van 1 veld zoeken.
Het eerste argument van de methode .Find moet de naam van het zoekveld bevatten en de zoekwaarde van dat veld.
Zet de zoekwaarde tussen enkelvoudige aanhalingstekens 'waarde'.

De methode .Find kan vooruit zoeken: vanaf de huidige cursorpositie tot het laatste ingevoerde record.
De methode .Find kan teruguit zoeken: vanaf de huidige cursorpositie tot het eerste ingevoerde record.
Het derde argument van de methode .Find bevat de parameter of vooruit gezocht moet worden (1) of teruguit (-1).

Bij vooruitzoeken eindigt de cursor zonder zoekresultaat op de positie .EOF (End of File)
Bij achteruitzoeken eindigt de cursor zonder zoekresultaat op de positie .BOF (Begin of File)
Als de zoekaktie succesvol is, is de recordpointer gelijk aan het gevonden record.

Bij vooruitzoeken is het handig de recordpointer naar het eerste record te verplaatsen: .MoveFirst. Bij achteruitzoeken is het analoog handig de recordpointer naar het laatste record te verplaatsen: .MoveLast.

10.1 Vooruit zoeken

Om consistente resultaten van de zoekaktie te krijgen is het bij vooruitzoeken handig de recordpointer eerst naar het eerste record te verplaatsen: .MoveFirst
Het derde argument van de .Find methode is de 'richting' parameter.
De parameter om vooruit te zoeken is de constante adSearchForward of de waarde 1.
Om te illustreren dat de recordpointerr 'op/in' het gevonden record staat een msgbox.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "tweede veld")
.AddNew Array(0,1), Array("tweede record","tweede veld")
.Update
.MoveFirst

.Find "text_001='tweede record'",,1

If Not .EOF then MsgBox Join(Array(.Fields(0),.Fields(1)),vbTab)
End With

10.2 achteruit zoeken

Om consistente resultaten van de zoekaktie te krijgen is het bij achteruitzoeken handig de recordpointer eerst naar het laatste record te verplaatsen: .MoveLast
Het derde argument van de .Find methode is de 'richting' parameter.
De parameter om achteruit te zoeken is de constante adSearchBackward of de waarde -1.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "tweede veld")
.AddNew Array(0,1), Array("tweede record","tweede veld")
.Update
.MoveLast

.Find "text_001='tweede record'",,-1

If Not .BOF Then MsgBox Join(Array(.Fields(0),.Fields(1)),vbTab)
End With

10.3 records overslaan

In het tweede argument van de methode .Find kun je aangeven hoeveel records vanaf de positie van de recordpointer gerekend in de zoekaktie moeten worden overgeslagen.
In het voorbeeld is het 4e record het eerste gevonden record.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "eerste record")
.AddNew Array(0,1), Array("eerste veld", "tweede record")
.AddNew Array(0,1), Array("eerste veld", "derde record")
.AddNew Array(0,1), Array("eerste veld", "vierde record")
.Update
.MoveFirst

.Find "text_001='tweede record'",3,1

If Not .BOF Then MsgBox Join(Array(.Fields(0),.Fields(1)),vbTab)
End With

10.4 Zoekcriteria

Een zoekcriterium in de method .Find kan allerlei vormen aannemen.
.Find "text_001='Norway'" .Find "text_001<>'Norway'"
.Find "text_002 LIKE N*"
.Find "text_002 LIKE *n"
.Find "date_001>#7/22/2018#"

10.5 Bestaat het record in de recordset

De ADODB Recordset heeft geen methode om de aanwezigheid van een record vast te stellen.
Daardoor kunnen records ten onrechte dubbel worden ingevoerd.
Met de methode .Find kun je controleren of een record een bepaalde waarde bevat.
Als het resultaat van de zoekaktie .EOF is, bestaat het record niet.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "eerste record")
.AddNew Array(0,1), Array("eerste veld", "tweede record")
.Update
.MoveFirst

.Find "text_001='tweede record'",,1

MsgBox "record bestaat " & iif(.EOF, "niet","al")

11 Records filteren

De ADODB Recordset bevat een ingebouwd filter: .Filter.
Dit filter kan zoeken op 1 of meer velden tegelijkertijd.
Daarvoor gebruik je de operatoren OR of AND.

Filtercriteria kunnen de volgende operatoren bevatten:
- gelijk aan =
- niet gelijk aan <>
- groter dan >
- kleiner dan <
- bevat aan het begin Like x*
- bevat aan het eind Like *x
- bevat like *x*

Na filtering is de eigenschap .RecordCount aangepast: die geeft het aantal gefilteerde records weer.
Pas nadat de filtering is opgeheven geeft .Recordcount weer het totale aantal records in de ADODB Recordset weer.

De filtercriteria worden geformuleerd in een tekenreeks.
Voor de duidelijkheid kun je een veldnaam tussen rechte haken zetten: [text_001]
Als een tekstreeks een filtercriterium is moet je het tussen enkelvoudige aanhalingstekens zetten: ='crterium'
Een datum als filtercriterium vraagt omkadering door hekjes: =#12/13/2018#

11.1 Filter op 1 veld

In de ADODB.Recordset is .filter een eigenschap.
Zet de filtercriteria als tekenreeks in de eigenschap .Filter.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "eerste record")
.AddNew Array(0,1), Array("eerste veld", "tweede record")
.Update

.Filter= "text_001='eerste veld'"

MsgBox .recordcount
.Filter = "text_0011 LIKE '* veld'"
.Filter = "[text_002]<>'eerste veld'"
End With

11.2 Filter op 2 velden

In de ADODB.Recordset is .filter een eigenschap.
Zet de filtercriteria als tekenreeks in de eigenschap .Filter.
In de tekenreeks kun je met AND of OR criteria voor verschillende velden koppelen.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "eerste record")
.AddNew Array(0,1), Array("eerste veld", "tweede record")
.Update

.Filter= "text_001='eerste veld' AND text_002<>'tweede record'"

MsgBox .recordcount
End With

11.3 Filter opheffen

Het huidige filter hef je op met de waarde 0 voor de eigenschap .Filter.
De eigenschap .RecordCount geeft dan alle records in de ADODB Recordset weer.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("eerste veld", "eerste record")
.AddNew Array(0,1), Array("eerste veld", "tweede record")
.Update

.Filter= "text_001='eerste veld' AND text_002<>'tweede record'"

MsgBox .RecordCount

.Filter = 0

MsgBox .RecordCount
End With

12 Recordset opslaan

Er zijn 4 methoden om de ADODB RecordSet op te slaan

in VBA kun je alle gegevens opslaan als tekstreeks
- c00 = .GetString

Opslaan als Array
- sn = .GetRows

In Excel opslaan in een werkblad
- Range.CopyFromRecordset

Opslaan als XML-bestand of als ADTG-bestand
- .Save

12.1 .GetString

De totale recordset kun je als een tekstreeks opslaan.
Die tekstreeks kun je in een variabele zetten.
De records worden gescheiden door vbCrLf: Chr(13) & Chr(10).
De velden worden gescheiden door een TAB: vbTab: Chr(9).
In het derde argument kun je het veldscheidingsteken wijzigen.
In het vierde argument kun je het recordscheidingsteken wijzigen
With CreateObject("ADODB.Recordset")
c00 =.GetString
End With
Als je de gegevens in het klembord wil zetten om elders te kunnen gebruiken
With CreateObject("ADODB.Recordset")
c00 =.String
End With

With GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}") ' klembord
.SetText c00
.PutInClipboard
End With
Als je de gegevens in een CSV of TXT bestand wil opslaan
With CreateObject("ADODB.Recordset")
Open "G:\OF\voorbeeld.csv" For Output As #1
Print .GetString, #1
Close
End With
Je kunt het veldscheidingsteken aanpassen aan de internationale Windows-instellingen.
In het derde argument kun je een tekenreeks als veldscheidingsteken(s) aangeven.
Dat geldt ook voor het recordscheidingsteken in het vierde argument.
With CreateObject("ADODB.Recordset")
Open "G:\OF\voorbeeld.csv" For Output As #1
Print .GetString(,,";",vbCrLf), #1
Close
End With

12.2 .GetRows

De methode .GetRows zet de Recordset in een 2-dimensionele Array.
With CreateObject("ADODB.Recordset")
sn = .GetRows
End With
In tegenstelling tot wat de naam van de methode suggereert komt ieder record in een kolom terecht.
In de rijen van de Array staan de velden per record.
Om zo'n Array wat gebruiksvriendelijker te maken moeten we hem transponeren.

12.2.0 .GetRows transponeren

12.2.0.1 Application.Transpose

Als de Excel VBA library geladen is kunnen we daarvoor de Excelfunktie Transpose gebruiken.
With CreateObject("ADODB.Recordset")
sn = Application.Transpose(.GetRows)
End With

12.2.0.2 ActiveX Listbox

De Excelfunktie Transpose is beperkt tot ca. 7000 records.
De ActiveX Listbox heeft die beperking niet.
Een Listbox met gegevens kan via de eigenschap .List of .Column gevuld en uitgelezen worden.
De .List eigenschap produceert een Array die de getransponeerde Array is die de eigenschap .Column produceert en vice versa.
Wil je een Array transponeren dan wijs je de Array toe aan de ene eigenschap en lees je hem uit met de andere eigenschap.
With CreateObject("ADODB.Recordset")
sn = .GetRows
End With

With CreateObject("New:{8BD21D20-EC42-11CE-9E0D-00AA006002F3}") ' - Microsoft Forms 2.0 ListBox
.Column = sn
sn = .List
End With

12.2.0.3 VBA-Array

Aan de hand van de Array die het resultaat is van .GetRows kunnen we een nieuwe Array maken als rotatie van .GetRows en daarin alle waarden op de juiste plaats zetten.
With CreateObject("ADODB.Recordset")
sn = .GetRows
ReDim sq(UBound(sn, 2), UBound(sn))

For j = 0 To UBound(sn, 2)
For jj = 0 To UBound(sn)
sq(j, jj) = sn(jj, j)
Next
Next
End With

12.2.1 Recordselektie

De methode .Getrows kent als eerste argument het aantal op te halen records.
Als je dit argument leeg laat worden standaard alle records gelezen.
Als je hier een aantal invult dien je ook aan te geven vanaf welk record dat aantal gelezen moet worden.
Dat doe je in het tweede argument.
Als een x aantal records gelezen moet worden vanaf de huidige cursorpositie: 0
Als een x aantal records gelezen moet worden vanaf het eerste record: 1
Als een x aantal records gelezen moet worden vanaf het laatste record: 2

Lees 3 records uit de recordset vanaf het eerste record
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("veld 1.1", "eerste record")
.AddNew Array(0,1), Array("veld 2.1", "tweede record")
.AddNew Array(0,1), Array("veld 3.1", "derde record")
.AddNew Array(0,1), Array("veld 4.1", "vierde record")
.AddNew Array(0,1), Array("veld 5.1", "vijfde record")
.Update

sn = .GetRows(3,1)
End With

12.2.2 veldselektie

De methode .Getrows leest standaard alle velden per record.
Je kunt in het derde argument van .GetRows aangeven welk veld je wil uitlezen door de veldnaam in te voeren.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("veld 1.1", "eerste record")
.AddNew Array(0,1), Array("veld 2.1", "tweede record")
.Update

sn = .GetRows(,,.Fields(0).Name)
End With
Wanneer je verschillende velden wil lezen gebruik je daarvoor een Array met de veldnamen.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("veld 1.1", "eerste record")
.AddNew Array(0,1), Array("veld 2.1", "tweede record")
.Update

sn = .GetRows(,,Array(.Fields(0).Name,.Fields(1).Name))
End With

12.2.3 veldvolgorde

Wanneer je verschillende velden wil lezen gebruik je daarvoor een Array met de veldnamen.
In die Array kun je ook aangeven in welke volgorde de velden moeten worden gelezen.
Je kunt zo volledig bepalen hoe de veldstruktuur van de resulterende Array eruit moet komen te zien.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Fields.Append "text_003", 129, 90
.Open

.AddNew Array(0,1,2), Array("veld 1.1", "eerste record","oud")
.AddNew Array(0,1,2), Array("veld 2.1", "tweede record","nieuw")
.Update

sn = .GetRows(,,Array(.Fields(2).Name,.Fields(0).Name))
End With

12.3 Excelmethode .CopyFromRecordset

Excel heeft een eigen methode om gegevens uit een recordset in een werkblad te zetten.
Deze methode is gebonden aan de linkerbovenhoek van een gebied (Range) in een werkblad.
Alle records vanaf het 'actuele' record ( = recordselector) worden gekopieerd.
Als je de gegevens van alle records wil, zul je eerst de recordselector naar het begin van de recordset moeten verplaatsen.
Je verwijst naar de gegevens van de recordset met de eigenschap .DataSource.
In het tweede argument van de methode .CopyFromRecordset kun je het maximaal aantal records aangeven.
In het derde argument kun je het maximale aantal velden specificeren.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open

.AddNew Array(0,1), Array("veld 1.1", "eerste record")
.AddNew Array(0,1), Array("veld 2.1", "tweede record")
.Update

.Movefirst

Sheet1.Cells(20,1).CopyFromRecordset .DataSource
End with

12.4 .Save

De methode .Save van de ADODB Recordset slaat de recordset als bestand op.
In het eerste argument van de methode zet je het pad en de bestandsnaam.
In het tweede argument kun je specificeren welk soort bestand je wil opslaan.
Standaard slaat de methode het bestand op als .adtg (Advanced Data TableGram) bestand.
Zo'n bestand kan later eenvoudig met de ADODB.recordset blibiotheek geopend worden.
De methode .Save kan geen bestand overschrijven of vervangen.
Als een bestand al bestaat genereert .Save een foutmelding.
Controle of een bestand al bestaat voorkomt dit.

12.4.1 Opslaan als .adtg bestand

With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open
.AddNew Array(0,1), Array("veld 1.1", "eerste record")
.AddNew Array(0,1), Array("veld 2.1", "tweede record")
.Update

If Dir("G:\OF\voorbeeld.adtg")="" Then .save "G:\OF\voorbeeld.adtg"
End with
Open een .adtg bestand:
With CreateObject("ADODB.Recordset")
.Open "G:\OF\voorbeeld.adtg", "Provider=MSPersist", , , 256
End with

12.4.2 Opslaan als XML bestand

Met de constante 'adPersistXML' of de waarde 1 in het 2e argument van de methode .Save sla je het bestand op als XML bestand.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open

.AddNew Array(0,1), Array("veld 1.1", "eerste record")
.AddNew Array(0,1), Array("veld 2.1", "tweede record")
.Update

If Dir("G:\OF\voorbeeld.XML")="" Then .save "G:\OF\voorbeeld.XML",1
End with

12.4.3 Converteer Excelbestand in XML bestand

De inhoud van een Excel werkblad kun je inlezen in een ADODB recordset.
De methode .Save kan de recordset als XML opslaan.
Zo converteer je een Excel werkblad in 2 regels naar een XML bestand.
With CreateObject("ADODB.recordset")
.Open "SELECT * FROM `" & ThisWorkbook.Sheets(1).Name & "$`", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0 Xml"""

.Save "G:\OF\conversie.xml", 1
End With

13 Verwijder record

13.1 Verwijder niet-gekoppeld record

De methode .delete verwijdert records.
Zonder een argument verwijdert deze methode het 'aktieve' record.
Dat is ook het geval als je het argument van de methode de waarde 1 geeft.
De methode verwijdert aangemaakte records voordat ze aan de database zijn toegevoegd of nadat ze aan de database zijn toegevoegd.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open

.AddNew Array(0,1), Array("veld 1.1", "eerste record")
.AddNew Array(0,1), Array("veld 2.1", "tweede record")

.Delete     ' verwijdert het tweede record
.Update

.Delete 1    ' verwijdert het eerste record
End with

13.2 Diverse records

Je kunt diverse records tegelijk verwijderen met de waarde 2 van het argument van de methode .delete.
Dat kan alleen in combinatie met de filtermethode.
De aangemaakte, nog niet aan de database toegevoegde records verwijderen.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open

.AddNew Array(0,1), Array("veld 1.1", "eerste record")
.AddNew Array(0,1), Array("veld 2.1", "tweede record")

.Filter = 1
.Delete 2      ' verwijdert alle records
.Filter=0

msgbox .recordcount
End with

13.3 Alle records in de database verwijderen met filter

Alle records in de database verwijderen met filter.
With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open

.AddNew Array(0,1), Array("veld 1.1", "eerste record")
.AddNew Array(0,1), Array("veld 2.1", "tweede record")
.Update

.Filter = 1
.Delete 2      ' verwijdert alle records
.Filter=0

msgbox .recordcount
End with

13.4 Alle records in de database verwijderen met loop

With CreateObject("ADODB.Recordset")
.Fields.Append "text_001", 129, 120
.Fields.Append "text_002", 129, 80
.Open

.AddNew Array(0,1), Array("veld 1.1", "eerste record")
.AddNew Array(0,1), Array("veld 2.1", "tweede record")
.Update

Do until .EOF
.Delete
.Movefirst
Loop

msgbox .recordcount
End with

13.5 Gekoppeld record verwijderen

Om een record in een gekoppeld bestand te kunnen wijzigen/verwijderen moet je daarvoor rechten hebben.
Die regel je met de eigenschap .LockType.
Dat is ook het 4e argument van de methode .Open.
Geef de eigenschap .Locktype de waarde 2 om gekoppelde records te kunnen verwijderen.

13.5.1 Gekoppeld Access-record verwijderen < 2007

With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM Q_test", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=G:\OF\voorbeeld.mdb", , 2
.Delete 1
End With

13.5.2 Gekoppeld Access-record verwijderen > 2003

With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM Q_test", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=G:\OF\voorbeeld.accdb", , 2
.Delete 1
End With

13.5.3 Gekoppeld XML-record verwijderen

Bij een gekoppeld Accessbestand worden de records meteen uit het bestand verwijderd.
Bij een XML bestand moet je eerst het bestand opslaan met .Save.
With CreateObject("ADODB.Recordset")
.Open "G:\OF\voorbeeld.XML", "Provider=MSPersist", , 2, 256
.Delete
.Save
End With

13.5.4 Gekoppeld ADTG-record verwijderen

Bij een gekoppeld Accessbestand worden de records meteen uit het bestand verwijderd.
Bij een ADTG bestand moet je eerst het bestand opslaan met .Save.
With CreateObject("ADODB.Recordset")
.Open "G:\OF\voorbeeld.adtg", "Provider=MSPersist", , , 256
.Delete
.Save
End With

13.5.5 Gekoppeld CSV-record verwijderen

Voor zover ik heb kunnen nagaan is er geen methode om een record uit een gekoppeld CSV-bestand te verwijderen.
De volgende code geeft eeen foutmelding op de regel met .Delete.
With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM `voorbeeld.csv`","Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=G:\OF\",,2
.Delete
.Save
End With
Natuurlijk is het mogelijk om records uit een CSV-bestand te verwijderen.
Daarvoor gebruik je de filtermethode in de SQL-string of de .Filter eigenschap van de ADODB.Recordset.
Omdat naar het gekoppelde CSV-bestand niet weggeschreven kan worden moet je de recordset eerst sluiten of de gefilterde gegevens naar een nieuw bestand schrijven.

In de SQL-opdracht
With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM `voorbeeld.csv` Where [veld1]='Haaglanden'", "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=G:\OF\"
CreateObject("scripting.filesystemobject").createtextfile("G:\OF\voorbeeld_001.csv").write .GetString(, , ";", vbCrLf)
End With
Met de eigenschap .Filter
With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM `voorbeeld.csv`", "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=G:\OF\" .filter= "[veld1]='Haaglanden'"
c00=.GetString(, , ";", vbCrLf)
.close
CreateObject("scripting.filesystemobject").createtextfile("G:\OF\voorbeeld_001.csv").write c00
End With

13.5.6 Gekoppeld Excel-record verwijderen

Voor zover ik heb kunnen nagaan is er geen methode om een record uit een gekoppeld Excel-bestand te verwijderen.
De volgende code geeft eeen foutmelding op de regel met .Delete.
With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM `Sheet1$`", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=G:\OF\Voorbeeld.xlsb;Extended Properties=""Excel 12.0 Xml""",,2
.Delete
End With
Vergelijkbaar met een CSV bestand kun je met de SQL-string of de eigenschap .Filter gefilterde (=niet-verwijderde) records in een nieuw bestand zetten.
Maar dit is essentieel anders dan met een gekoppeld Access-bestand.

In de SQL-opdracht
With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM `Sheet1$` Where [veld1]='Haaglanden'", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=G:\OF\Voorbeeld.xlsb;Extended Properties=""Excel 12.0 Xml"""
WorkBooks.Add.Sheets(1).Cells(1).CopyFromRecordset .DataSource
End With
Met de eigenschap .Filter
With CreateObject("ADODB.Recordset")
.Open "SELECT * FROM `Sheet1$`", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=G:\OF\Voorbeeld.xlsb;Extended Properties=""Excel 12.0 Xml"""
.Filter="[veld1]='Haaglanden'"
WorkBooks.Add.Sheets(1).Cells(1).CopyFromRecordset .DataSource
End With