8. Werken met objecten

8.1 Objectvariabelen

Microsoft Access kent objecten als tabellen, query's, formulieren en rapporten waarmee taken voor gegevensbeheer worden uitgevoerd. 

Er zijn verschillende soorten objecten

De verschillende objecten worden verzameld in collecties en worden bewaard volgens een hiërarchisch objectenmodel.

Elk object kent eigenschappen en wordt bestuurd met methodes

8.2 Microsoft Access-objecten.

De volgende tabel toont de hiërarchische structuur van de objecten:

object2.jpg (21090 bytes)

Het Application-object bevat alle Microsoft Access-objecten en -collecties
Forms is de collectie van alle geopende formulieren, terwijl Reports de collectie is van alle geopende rapporten. De elementen van een form worden bewaard in de controls-collectie.

Een object uit een collectie kan op drie manieren aangesproken worden

  1. naam van de collectie ! [naam van het object]
    voorbeeld : forms![form1]
  2. naam van de collectie ("naam van het object")
    voorbeeld : forms("form1")
    voordeel : hetgeen tussen de haakjes staat kan eventueel een variabele zijn : naam = "form1"
    de aanspreekvorm wordt dan : forms(naam)
  3. naam van de collectie (indexnummer)
    Bij het openen van bijvoorbeeld een form krijgt die een nummer (indexnummer). Is bijvoorbeeld form1 als eerste geopend dan krijgt die de index 0. De aanspreekvorm is dan : form(0).

In de programmacode kan men deze objecten toekennen aan een variabele. Na het declareren kan men een waarde toekennen, net zoals men een getal of een string toekent aan een variabele.
Een objectvariabele moet net als een gewone variabele gedeclareerd worden :

Dim f as form, c a as control

Hierbij zijn f en c de variabelen. In de naam van de variabelen zijn alle tekens toegelaten behalve leestekens. Underscore is ook toegelaten.

Om een waarde te stockeren in een objectvariabele gaat men als volgt te werk :

Set f = forms![naam van een geopend formulier]  of
Set f = forms!("naam van een geopend formulier") of
Set f = forms(0)
indien het formulier het eerst geopend werd

Een voorbeeld maakt dit duidelijk :

Bijzondere eigenschappen bij objecten en collecties zijn count en name. Bovendien is properties de collectie van alle property's of eigenschappen. Een voorbeeld

oefeningen

  1. Schrijf een functie die in het foutopspringsvenster al de namen van alle eigenschappen van het geopend formulier frmLeerlingen_o afdrukt.
  2. Zelfde vraag maar naam en waarde van de eigenschap.
  3. Schrijf een functie die in het foutopspringsvenster al de namen van de besturingselementen  van het geopend formulier frmLeerlingen_o afdrukt.
  4. Zelfde vraag maar alleen de tekstvakken.
  5. De vorige lijst uitbreiden met de inhoud van de tekstvakken.

antwoorden

8.3 DAO-objecten

De volgende tabel toont de structuur.

object3.jpg (25365 bytes)

Enkele bedenkingen

Het DBEngine-object is het object van het hoogste niveau in het DAO-objectmodel .Het bevat en bestuurt alle andere objecten.

Een workspace is een sessie voor een gebruiker. Dit is het werkgebied waar men terecht komt bij het opstarten van access. Workspaces is de collectie van alle workspace-objecten. De default workspace is workspaces(0)

Het database-object is de gepende database(MDB). Databases is de collectie van de geopende databases. De default database is databases(0)
De huidige geopende database kan men aanspreken met dbengine.workspaces(0).databases(0). Dit kan korter met currentdb

Net zoals bij de Microsoft Access-objecten kunnen de propertiescollectie en de count- en name-eigenschappen gebruikt worden.

Het volgend voorbeeld drukt de namen van de properties van de huidig geopend database.

Function databaseproperties()
Dim db As Database, x As Integer
Set db = CurrentDb
For x = 0 To db.Properties.Count - 1
Debug.Print db.Properties(x).Name
Next x
End Function

Het volgend voorbeeld toont de naam van de huidig geopende database en of hij al of niet updatable is.

Function databaseproperties()
Dim db As Database, x As Integer
Set db = CurrentDb
Debug.Print db.Name
Debug.Print db.Updatable
End Function

8.4 Werken met de hiërarchie van de DAO-objecten

Als voorbeeld nemen met de collectie tabledefs. Dit is de verzameling van de gegevens van alle tabellen.

De volgende functie toont een lijst van alle tabellen uit de actieve database in het foutopsporingsvenster.

Function tabellen()
Dim db As Database, t As TableDef, aantal As Integer, x As Integer
Set db = CurrentDb
aantal = db.TableDefs.Count
For x = 0 To aantal - 1
Debug.Print db.TableDefs(x).Name
Next x
End Function

Elke tabel heeft eigenschappen. Het volgend voorbeeld toont na invoer van de tabelnaam deze eigenschappen. We maken daarbij gebruik van de propertiescollectie.

Function tabeleigenschappen()
Dim db As Database, t As TableDef, tabel As String, x As Integer
Set db = CurrentDb
tabel = InputBox("welke tabel")
Set t = db.TableDefs(tabel)
For x = 0 To t.Properties.Count - 1
Debug.Print t.Properties(x).Name
Next x
End Function

Bemerk de manier waarop de objectvariabele t zijn waarde krijgt. Hier wordt niet het indexnummer gebruikt maar een variabele, namelijk tabel.

De fieldscollectie is dan weer een subcollectie van tabledefs. Het volgend voorbeeld maakt het mogelijk na invoer van een tabel de velden af te drukken.

Function velden_in_tabel()
Dim db As Database, t As TableDef, tabel As String, x As Integer
Set db = CurrentDb
tabel = InputBox("welke tabel")
Set t = db.TableDefs(tabel)
For x = 0 To t.Fields.Count - 1
Debug.Print t.Fields(x).Name
Next x
End Function

of  gebruikmakend van een fieldobject

Function velden_in_tabel()
Dim db As Database, t As TableDef, f As Field, tabel As String, x As Integer
Set db = CurrentDb
tabel = InputBox("welke tabel")
Set t = db.TableDefs(tabel)
For x = 0 To t.Fields.Count - 1
Set f = t.Fields(x)
Debug.Print f.Name
Next x
End Function

oefeningen

1. Maak een lijst in het foutopsporingsscherm met tabelnamen en aantal records voor elke tabel.

2. Zorg dat na invoer van een veldnaam alle tabellen waarin deze veldnaam voorkomt getoond worden.

3. Schrijf een functie die na invoer van een tabelnaam en een veldnaam die in deze tabel voorkomt, de eigenschappen van dat veld afdrukt.

4. Zelfde vraag maar de waarde van het veld moet afgedrukt worden.

antwoorden

8.5 Gevorderde bewerkingen met DAO-objecten

8.5.1 QUERYDEFS

Deze collectie bevat de querydefobjecten. Dit zijn de gegevens i.v.m. query's en de bijhorende sql-commando's. Het sql-commando kan men bekomen met de speciale eigenschap sql.
Het volgende voorbeeld genereert een lijst van bestaande query's uit de actieve database en het bijhorend sql-commando.

Function querylijst()
Dim db As Database, q As QueryDef, x As Integer
Set db = CurrentDb
For x = 0 To db.QueryDefs.Count - 1
Set q = db.QueryDefs(x)
Debug.Print q.Name, q.SQL
Next x
db.close
End Function

Actionquery's kunnen met de execute-methode vanuit een functie uitgevoerd worden. Stel dat de query qryBoeken een bijwerkquery is die de eenheidsprijs van de boeken met 2% verhoogt, dan zal de volgende functie deze query uitvoeren.

Function prijsverhoging()
Dim db As Database, q As QueryDef
Set db = CurrentDb
Set q = db.QueryDefs("qryBoeken")
q.Execute
db.close
End Function

oefeningen

1. Indien een tabelnaam gewijzigd wordt, moeten alle query's gebaseerd op deze tabel, gewijzigd worden. Schrijf een functie die na invoer van een tabelnaam de namen van alle query's waarin deze tabel voorkomt in het foutopsporingsvenster afdrukt. Maak daarbij gebruik van de InStr-instructie.

2. Schrijf een functie die alle query's wist met de deleteobjectmethode..

antwoorden

8.5.2 RECORDSETS

8.5.2.1 Het recordset-object

Het recordsetobject bevat de records van een tabel of het resultaat van een query. De recordsets-collectie bevat alle geopende recordsetobjecten.
Er zijn 4 soorten recordsetobjecten

table Bevat de gegevens van een tabel of een gekoppeld bestand
dynaset De resultaatgegevens van een query. De gegevens kunnen gewijzigd worden.
snapshot De resultaatgegevens van een query , maar niet updatable.
forwardOnly Hetzelfde als snapshot, maar de gegevens kunnen slechts in één richting (voorwaarts)doorlopen worden. Dit zorgt voor een betere prestatie wanneer u slechts één keer door een set resultaten hoeft te lopen.

Een recordset kan men openen met volgende methode

Set recordset = object.OpenRecordset (type, opties, bewerkingenvergrendelen)

waarbij

recordset: de naam van het recordsetobjectvariabel

object: het databaseobject waarin de recordset geopend wordt

type: één van de volgende mogelijkheden dbOpenTable,dbOpenDynaset, dbOpenSnapshot of dbOpenForwardOnly  afhankelijk van wat de bron is van de recordset( tabel of query) of wat je er wil meedoen (dynaset of snapshot)             

opties: afhankelijk van de uit te voeren actie en/of beveiliging kan men kiezen uit één van de volgende mogelijkheden: dbAppendOnly ,dbDenyWrite,dbDenyRead,dbReadOnly         

bewerkingenvergrendelen: kan je gebruiken om te bepalen hoe de recordset moet vergrendeld worden bij gebruik door verschillende users. We onderscheiden o.a.  dbPessimistic en  dbPessimistic. Zoek het verschil via de help.       

Vergeet nooit op het einde van een functie de geopende recordset te sluiten met de close-methode

Het volgend voorbeeld opent en sluit de tabel tblBoeken in een recordset van het type table.

Function open_en_sluiten()
Dim db As Database, r As Recordset
Set db = CurrentDb
Set r = db.OpenRecordset("tblBoeken", dbOpenTable)
r.Close
db.close
End Function

8.5.2.2 Methoden en eigenschappen van het recordsetobject

Een object wordt bestuurd door methoden met als vorm object.methode(argumenten) of object.methode indien geen argumenten.
Bovendien heeft een object ook eigenschappen die een bepaalde waarde bevatten met als schriijfwijze: methode.eigenschap
Wat volgt is een overzicht van de voornaamste eigenschappen en methoden.

de recordcount-eigenschap

Deze eigenschap toont het aantal records van de recordset. Het volgend voorbeeld toont het aantal records van de tabel tblBoeken in het foutopsporingsscherm.

Function aantal_records()
Dim db As Database, r As Recordset
Set db = CurrentDb
Set r = db.OpenRecordset("tblBoeken", dbOpenTable)
debug.print r.Recordcount
r.Close
db.close
End Function

Methoden om een recordset te doorlopen:

De methoden movenext,movefirst,movelast en moveprevious maken het mogelijk de records uit een recordset te doorlopen

De eigenschappen eof (end of file) en bof (begin of file) zijn nodig om te testen op de eerste en laatste record van een recordset.

Wanneer u een Recordset opent, is de eerste record de huidige record en heeft de eigenschap BOF
de instelling False. Als de Recordset geen records bevat, heeft de eigenschap BOF de instelling True en is er geen huidige record.

Het volgend voorbeeld drukt de titels van de tabel tblBoeken in het foutopsporingsvenster

Function doorloop_tabel()
Dim db As Database, r As Recordset
Set db = CurrentDb
Set r = db.OpenRecordset("tblBoeken", dbOpenTable)
Do Until r.EOF
Debug.Print r![titel]
r.MoveNext
Loop
r.close
db.close
End Function

Bemerk de manier waaop een veld uit een recordset wordt aangeduid: object![veldnaam]

Kiezen we voor een dynaset, dan bestaat de mogelijkheid de naam van een bestaande query of zelfs een sqlcommande als recordsetbron te gebruiken. het volgende voorbeeld drukt de gesorteerde titels van de tabel tblBoeken in het foutopsporingsvenster.

Function doorloop_tabel()
Dim db As Database, r As Recordset
Set db = CurrentDb
Set r = db.OpenRecordset("select titel from tblBoeken order by titel", dbOpenDynaset)
Do Until r.EOF
Debug.Print r![titel]
r.MoveNext
Loop
r.close
db.close
End Function

Opgelet: bij het gebruik van de eigenschap recordcount in een dynaset moet men eerst de methode movelast uitvoeren. Het volgende voorbeeld overloopt de tabel boeken met een for-next-instructie van achter naar voor.

Function doorloop_tabel()
Dim db As Database, r As Recordset, x As Integer
Set db = CurrentDb
Set r = db.OpenRecordset("select titel from tblBoeken order by titel", dbOpenDynaset)
r.MoveLast
For x = 1 To r.RecordCount
Debug.Print r![titel]
r.MovePrevious
Next x
r.close
db.close
End Function

Sorteren van een recordset

Er zijn 3 manieren om een recordset gesorteerd te gebuiken.

Zoeken in een recordset

De manier van zoeken is afhankelijk van het type recordset, vandaar

Toevoegen in een recordset

De methoden ADDNEW en UPDATE maken het mogelijk records toe te voegen met een functie. Het volgende voorbeeld voegt in de tabel vakken een ingevoerde vakcode en omschrijving toe.

Function toevoegen_in_tabel()
Dim db As Database, r As Recordset, code As String, omschrijving As String
code = InputBox("welke vakcode")
omschrijving = InputBox("welke omschrijving")
Set db = CurrentDb
Set r = db.OpenRecordset("tblVakken", dbOpenTable)
r.AddNew
r![vakcode] = code
r![vak_omschrijving] = omschrijving
r.Update
r.Close
db.Close
End Function

Wat gebeurt er indien één van de invoervelden leeg is? Hoe los je dit op?

Function toevoegen_in_tabel()
Dim db As Database, r As Recordset, code As String, omschrijving As String
code = InputBox("welke vakcode")
omschrijving = InputBox("welke omschrijving")
If code <> Null And omschrijving <> Null Then
     Set db = CurrentDb
     Set r = db.OpenRecordset("tblVakken", dbOpenTable)
     r.AddNew
    r![vakcode] = code
    r![vak_omschrijving] = omschrijving
    r.Update
    r.Close
   db.Close
Else
   Debug.Print "één van de invoervelden was leeg"
End If
End Function

Wijzigen in een recordset

De methoden EDIT en UPDATE maken het mogelijk velden in een record te wijzigen met een functie. Het volgende voorbeeld plaatst alle vak_omschrijvingen in hoofdletters.

Function wijzigen_in_tabel()
Dim db As Database, r As Recordset
Set db = CurrentDb
Set r = db.OpenRecordset("tblVakken", dbOpenTable)
Do Until r.EOF
r.Edit
r![vak_omschrijving] = UCase(r![vak_omschrijving])
r.Update
r.MoveNext
Loop
r.Close
db.Close
End Function

Wissen in een recordset

De methode DELETE volstaat om records in een tabel te wissen. Het volgend voorbeeld wist uit de tabel boeken alle records waar uit_assortiment gelijk is aan ja. Na de delete-actie wordt het aantal gewiste records getoond.

Function wissen_in_tabel()
Dim db As Database, r As Recordset, teller As Integer
Set db = CurrentDb
Set r = db.OpenRecordset("tblBoeken", dbOpenTable)
teller = 0
Do Until r.EOF
If r![uit_assortiment] Then
r.Delete
teller = teller + 1
End If
r.MoveNext
Loop
r.Close
db.Close
MsgBox "er werden " & teller & " records gewist"
End Function

8.5.2.3 Oefeningen met recordsets

  1. Voeg in de tabel tblLeerlingen het veld klasnummer (integer ) toe. Schrijf een functie die de leerlingen per klas alfabetisch rangschikt en een klasnummer toekent.
  2. Maak een  tabel tblAfwezigheden met als velden naam en datum. Maak een formulier gebaseerd op leerlingen met per formulier de leerlinggegevens en een opdrachtenknop AFWEZIG. Bij het klikken op deze laatste wordt de naam en de systeemdatum in de tabel tblAfwezigheden weggeschreven.
  3. In een schoenwinkel moet men een aantal gelijkaardige etiketten kunnen afdrukken. De gegevens op het etiket bestaan maximum uit 3 regels bijvoorbeeld
                         Leder ZWART
                         maat 42
                         type AL56
    Maak een formulier waarin men de gegevens en het aantal exemplaren kan invoeren.
    Daarna worden de etiketten door middel van een rapport in 2 kolommen afgedrukt. Maak daarbij gebruik van een tabel tblEtiket waarin de nodige records worden aangemaakt of gewist.
  4. Maak een nieuwe tabel tblRekeningen met als velden naam, kostenomschrijving, bedrag en datum.
    Met een formulier bestaande uit 3 invoervakken: klas, kostenomschrijving en bedrag kan men in groep verrekeningen naar leerlingen aanmaken in de tblRekeningentabel.

Antwoorden

8.5.3 FORMS en ONDERLIGGENDE TABELLEN

Verwijst de recordbroneigenschap van een formulier naar een tabel dan kan deze onderliggende tabel aangesproken worden met de recordsetclone-property. Deze is steeds van het type DYNASET.
De bookmarkproperty maakt synchronisatie tussen formulier en onderliggende dynaset mogelijk.

In formulier frmVakken met vakcode, vak_omschrijving en een opdrachtenknop die verwijst naar de volgende functie toont het probleem van gegevens van het formulier en onderliggende tabel aan.

Function gegevens()
Dim r As Recordset
Set r = Forms![frmVakken].RecordsetClone
MsgBox r![Vakcode]
r.Close
End Function

Als men via de navigatieknoppen een volgende record oproept blijft de functie de eerste record tonen.
Dit kan men oplossen door beiden, formulier en recordsetclone te synchroniseren.

Function gegevens()
Dim r As Recordset
Set r = Forms![frmVakken].RecordsetClone
r.Bookmark = Forms![frmVakken].Bookmark
MsgBox r![Vakcode]
r.Close
End Function

Hierbij fungeert de bookmarkproperty als een recordnummer.

De recordsetcloneproperty bestaat alleen bij formulieren en niet bij rapporten!!!

 

8.5.4 ERROR TRAPPING ROUTINES

In sommige gevallen is een fout tijdens de uitvoering van een functie (RUNTIME fout) onvermijdelijk. Met de instructie ON ERROR kan men er voor zorgen  dat de functie op een passende  wijze reageert.
We onderscheiden volgende mogelijkheden:

8.5.4.1 Een paar voorbeelden

8.5.4.2 Oefeningen

  1. Maak een formulier gebaseerd op de tabel tblKlassen. Voorzie 2 toetsen voor vorige en volgende record, gebruik hierbij de macroactie GOTORECORD. Zorg dat er geen foutmeldingen verschijnen bij  de laatste en eerste record.
    Als uitbreiding zorg je dat volgende record op de laatste, resulteert in de eerste record en vorige record op de eerste de laatste record toont.
  2. Schrijf een functie dat na invoer van maand en jaar het aantal dagen van deze maand toont.

Antwoorden