Access macro's, modules, VBA programmacode en functies en subroutines

http://www.pcmenu.nl - Hans Bronkhorst

Zie ook elders op deze site:

PCMenu Access Tips en trucs Access tabellen
Access query's Access formulieren en rapporten Access voor gevorderden
Access beveiliging E-mail vanuit Access Access en Word
Programmavoorbeelden Access Access uitgeplozen Access uitgeplozen: modules
De tekst Access voor gevorderden, elders op deze site, gaat verder in op programmacode, verschillen tussen Access 97 en 2000/XP en tussen DAO en ADO, het maken of bijwerken van een tabel middels programmacode en andere onderwerpen. Als u na het lezen van deze twee teksten nog vragen over modules en programmacode hebt, stel uw vraag dan op een forum als http://office.webforums.nl.  

In deze tekst:

Begrippen
Hergebruik
Naamgeving
Helpfuncties gebruiken
Macro's
Modules
Programmacode
Functies en subroutines
Gebruik , als scheidingsteken in programmacode
Fouten voorkomen en opsporen
In programmacode foutafhandeling opnemen
Fouten met laden van DAO bestanden
Tabellen maken in VBA programmacode

Tips op andere websites

Begrippen

In deze tekst worden de volgende begrippen besproken:

*   Macro's verzorgen alle acties binnen een Accces-programma, zoals het openen van een invoerscherm na een muisklik op een knop in een menu. Macro's kunt u ordenen door enkele macro's onder één hoofd-naam op te slaan. U kunt macro's voorwaardelijk maken, de stappen van de macro worden dan pas uitgevoerd als aan de voorwaarde voldaan wordt. Wilt u een wat groter of complexer programma maken of bent u van plan om in de toekomst veel meer programma's in Access te maken, dan is het aan te raden dat u geen macro's gebruikt, maar direct met modules aan de slag gaat.

*   Modules zijn vergelijkbaar met macro's, maar zijn geheel opgebouwd uit programmeertaal-opdrachten, geschreven in de programmeertaal Visual Basic for Applications. Dezelfde programeertaal wordt ook gebruikt in o.a. Excel en Word. Met modules kunt u nog beter dan met macro's opdrachten in het Access-programma instellen en fouten in invoer of uitvoer ondervangen. U kunt modules afzonderlijk programmeren, maar ook als onderdeel van een formulier of rapport. Met de VBA programmacode kunt u ook queries maken of tabellen lezen, maken en bewerken. VBA gebruikt voor het grootste deel dezelfde code als Visual Basic, een programmeertaal waarin u complete, zelfstandig draaiende programma's kunt ontwikkelen, maar VBA kan alleen aanvullend op een Access-, Word-, Excel- of andere applicatie of document gebruikt worden. 

Voor u begint

Hergebruik

Probeer uw programma zo op te zetten dat u delen hiervan kunt hergebruiken in andere programma's. Probeer programmacode te ontwikkelen die algemeen bruikbaar is.Documenteer de modules met commentaarregels, zodat u later altijd weet waar de code voor geschreven is.
Beter goed gejat dan slecht zelf gemaakt. Bij programmeren gaat dit volledig op. U kunt vaak delen van programmacode uit andere programma's overnemen voor uw eigen programma. Het is wel netjes als u de bron van de overgenomen programmacode ergens vermeldt, in een commentaarregel in de programmacode zelf en/of in een opmerkingen-veld in uw programmainformatie.

Naamgeving

Gebruik bij voorkeur duidelijke namen en vermijd spaties, streepjes en andere leestekens in de namen van modules en variabelen. U kunt wel de _ gebruiken, in plaats van een spatie. Bij het schrijven van programmacode ondervindt u veel voordelen van deze naamgeving.
Namen van variabelen, functies en subroutines kunt u vooraf laten gaan met een prefix. Bijvoorbeeld str voor tekstvariabelen, lng voor variabelen met een numerieke waarde van het type Lange integer, sub voor een subroutine enzovoort. Dit wordt de Hongaarse notatie genoemd. Een consequente naamgeving maakt direct duidelijk wat voor een soort variabele of stukje programmacode het is. Zie http://www.sip.be/cursus/access/appena.htm voor een tabel met richtlijnen. 

Helpfuncties gebruiken

U kunt het uzelf makkelijker maken door volop gebruik te maken van de helpfuncties van Access. U kunt veel helpfuncties onder de rechtermuisknop vinden. Of u kunt een Wizard of Opbouwfunctie gebruiken. De F1-toets geeft u toegang tot de uitgebreide helpteksten van Access. In Access vindt u afzonderlijke helpteksten voor Access zelf en voor VBA / programmacode.

Onderdelen

Macro's

Macro's worden uitgebreid besproken in onder meer de on line cursus Access 97 van http://www.sip.be.
Hoewel macro's makkelijker te maken zijn dan modules, is het toch aan te raden om uw opdrachten in programmacode te schijven in de Modules. Met modules kunt u veel meer dan met macro's en de code is doorzichtiger: u kunt sneller zien wat de code doet. 
Het kan soms wel handig zijn om een macro te gebruiken, als oefenmateriaal: een door Access gemaakte macro kunt u omzetten naar VBA (open da macro in de Ontwerpweergave, klik op Bestand >> Opslaan  als >> als programmacode), waardoor u kunt zien wat de vergelijkbare programmacode is achter deze macro.

Modules

Modules en programmacode worden uitgebreid besproken in onder meer de on line cursus Access 97 van http://www.sip.be.
U kunt programmacode bij formulieren en rapporten schrijven (Gebeurtenisprocedure), maar u kunt ook programmacode afzonderlijk in een Module opnemen. Als u een stukje programmacode meerdere keren wilt gebruiken of ook in andere programma's wilt opnemen, dan is het raadzaam om de programmacode als Functie (Function) in een Module op te nemen en dus niet in het Formulier of Rapport. Vanuit het formulier of het rapport kunt u met =fncFunctienaam() de betreffende functie oproepen.

Voorbeeld voor navigatieknoppen: u maakt een nieuwe Module met de volgende code:

Function fncVolgende()
'Ga naar volgende record
On Error Resume Next
    DoCmd.GoToRecord , , acNext
End Function

 

Function fncVorige()
'Ga naar vorige record
On Error Resume Next
    DoCmd.GoToRecord , , acPrevious
End Function

Op een formulier maakt u twee knoppen met de namen Naar_volgend_record en Naar_vorig_record en zet u bij de knop Naar_volgend_record bij de Gebeurtenis Bij klikken:

= fncVolgende()

en bij de knop Naar_vorig_record bij de Gebeurtenis Bij klikken:

            = fncVorige()

U kunt deze knop nu makkelijk kopiëren naar andere formulieren, waarbij u niet meer voor elk formulier de programmacode voor deze knop hoeft te maken.

Weet u niet wat de programmacode van een bepaalde opdracht is, dan kunt u proberen om er eerst een macro van te maken. Daarna exporteert u de macro naar Programmacode (klik op de rechter muisknop) en u ziet hoe Access de macro vertaald heeft in VBA. Deze code kunt u vervolgens in uw Modules opnemen.
De programmacode voor Access 97 wijkt op enkele punten af van de programmacode die u in Access 2000 of XP kunt gebruiken. Zie de tekst Access voor gevorderden.

Gebruik , als scheidingsteken in programmacode

In alle versies van Access gebruikt u in programmacode de , om gegevens te scheiden en een . als decimaal scheidingsteken. Voorbeeld:

         txtAchternaam =  DLookup("Achternaam", "tblNaam", "ID_Naam = " & Me!ID_Naam)

        dblPi = 3.14

In de Nederlandse versie van Access gebruikt u daarentegen bij queries en bij de eigenschappen van bijvoorbeeld formulieren de ; als scheidingsteken en de , als decimaal scheidingsteken. Voorbeeld:

Formulier frmNaam, veld txtNaam, gegevensbron is:

        =  DLookup("Achternaam"; "tblNaam"; "ID_Naam = " & Me!ID_Naam)

Query qryCirkel, veld Omtrek:

        Omtrek: 3,14 * [Straal]

Functies en subroutines

Een functie gebruik u als u een bepaalde waarde aan een variabele wilt teruggeven. U kunt een of meer waarden meegeven waarop u de berekening wilt uitvoeren, waarvan de laatste waarden optioneel kunnen zijn. Voorbeeld:

Function fncMachtverheffen(dblGetal As Double, Optional dblMacht As Double) as Double

     If IsNull(dblMacht) Then
        dblMacht = 2
     End If

End Function

U roept de functie op door deze toe te wijzen aan een variabele, in dit voorbeeld dblWortel en dblKwadraat:

Dim dblWortel As Double, dblKwadraat As Double
Dim dblOorsprong As Double 

dblOorsprong = 16

dblWortel = fncMachtverheffen(dblOorsprong, 0.5)  
' macht 0,5, ofwel de wortel: resultaat is 4

dblKwadraat = fncMachtverheffen(dblOorsprong)  
'geen macht opgegeven, dus geef dan het kwadraat: resultaat is 256

Een subroutine gebruikt u om een bepaalde opdracht te doen. Een subroutine geeft geen waarde terug. Voorbeeld:

Sub subToon_boodschap()
    MsgBox "Toon deze boodschap"
End Sub

U roept de subroutine op door hem te noemen of door de opdracht Call:

subToon_boodschap

of

Call subToon_boodschap

Wilt u een parameter meegeven aan de subroutine, zet deze parameter dan:

bij de declaratie van de subroutine tussen de twee haakjes:

        Sub subToon_boodschap (strBoodschap As String)
            MsgBox  strBoodschap
        End Sub

en bij de oproep van de subroutine achter de naam van de subroutine, gescheiden met een spatie:

       subToon_boodschap "Dit is de boodschap"

Fouten voorkomen en opsporen

Het is bij een wat complexer programma niet mogelijk om direct alle fouten te voorkomen, maar u kunt het aantal fouten wel verminderen en gemaakte fouten beter opsporen met de volgende aanbevelingen:

Fouten voorkomen

Neem in elke module als tweede regel de regel Option Explicit op, u bent dan verplicht om variabelen te declareren (te benoemen met de opdracht Dim .. As ..). Hiermee krijgt u nettere programmacode en dus minder kans op ernstige en niet te achterhalen fouten:
  Option Compare Database
    Option Explicit
Maak een consequent gebruik van witregels en inspringingen. Laat bijvoorbeeld de regels binnen een If .. Then (..) End If constructie en binnen loops als Do While (..) Loop een tabstop inspringen. Uw programmacode wordt hierdoor veel overzichtelijker.
Maak voldoende gebruik van commentaarregels (regels voorafgegaan met een ' teken), gebruik consequente naamgeving met voorvoegsels (zie het kopje Naamgeving, eerder in deze tekst) en vermijd alle leestekens (behalve _) in de namen van variabelen. Op deze wijze houdt u de programmacode leesbaar voor uzelf en voor anderen en kunt u veel sneller uw programma aanpassen en onderhouden, ook na enkele maanden, als u niet meer zo goed weet hoe u het programma hebt opgezet.
U kunt een tabel voor foutcodes in Access downloaden bij www.sforsoftware.nl/downloadsaccess.htm.

Fouten opsporen

Compileer uw programma regelmatig, Access geeft dan de syntaxfouten weer. Syntaxfouten zijn fouten in het gebruik van de code, bijvoorbeeld een functie waarbij een verplichte parameter ontbreekt, een ; in plaats van een , of een variabele die niet gedeclareerd is. In Access 2000 compileert u uw programma in de VBA-editor (het venster waarin u uw programmacode wijzigt) Bij Foutopsporing  >> <programmanaam> compileren. In Access 97 opent u een module en klikt u op Extra >> Foutopsporing >> Alles compileren en opslaan. Zie ook de tekst Access voor gevorderden >> Verwijzingen.
Als uw programma telkens op één bepaalde plek vastloopt of een ander resultaat geeft dan wat u verwacht, dan kunt u de programmacode op deze plek of op een eerdere plek laten stoppen zodat u bij elke programmaregel kunt nagaan welke waarden de variabelen op dat moment hebben. Klik met de muis in de linkermarge  van de betreffende programmaregel of druk op de F9-toets om een stop-teken te plaatsen (u kunt geen stoptekens bij lege regels, commentaarregels of labels plaatsen). Laat de programmacode opnieuw doorlopen en controleer de variabelen in het venster Lokale variabelen. Met de F8-toets gaat u stap voor stap naar de volgende regel.
U kunt ook meerdere Debug.Print <variabelenaam> regels opnemen in uw programmacode. In het direct-venster (typ Ctrl+G) kunt u dan de waarde van de variabelen bekijken.

In programmacode foutafhandeling opnemen

Het is voor gebruikers storend als zij foutmeldingen zien tijdens het gebruik van het programma. U kunt in alle programmacode een foutafhandeling opnemen, waarbij u bij fouten òf geen melding laat zien, òf een voor de gebruiker begrijpelijke melding laat zien. Access maakt standaard een foutafhandeling aan als u programmacode met een Wizard maakt. Als u zelf modules schrijft, dan kunt u deze foutafhandeling zelf in de code opnemen. Zie de handleiding van Access voor de toegestane code (Resume <labelnaam>, Resume Next, Resume 0, Err of Err.Number, Error$ of Err.Description enz.). Een voorbeeld voor een foutafhandeling:

Function  fXyz()  
On Error GoTo Err_fXyz

(...)

Exit_fXyx:  'het label waar de functie verlaten wordt
  Exit Function

Err_fXyz:   'het label waar de foutafhandeling begint
   Select Case Err.Number
     Case 123  'als fout 123 is opgetreden, dan ...
       MsgBox "Dit is foutmelding 123: " & Error$
       Resume Next
     Case 456  'als fout 456  is opgetreden, dan ...
       'Toon niets
       Resume Exit_fXyz
   Case Else 'bij een andere fout, dan...
       MsgBox Error$
       Resume Exit_fXyz
   End Select

End Function

Exit_fXyz en Err_fXyz zijn labels in de programmacode waarnaar u met Resume <labelnaam> kunt springen.U moet bij een fout altijd een Resume-opdracht geven, anders geeft Access een foutmelding en stopt Access met het doorlopen van de code. 

De programmacode mag alleen naar een Err_-label springen, wanneer er een fout optreedt. U moet daarom altijd een opdracht als Exit Function of Exit Sub plaatsen vóór het Err-label, zodat de programmacode de functie of subroutine verlaat voordat de foutafhandeling bereikt wordt.

Fouten met laden van DAO bestanden

In Access 2000 en XP wordt standaard geen verwijzing naar DAO bibliotheek aangezet. U kunt dan foutmeldingen krijgen over ontbrekende verwijzingen. Zie voor meer uitleg hierover de tekst Verwijzingen in Access voor gevorderden.

Tabellen maken in VBA programmacode

Dit onderdeel beschrijft ook enkele verschillen tussen DAO (Access 97) versus ADO (Access 2000 en XP) programmacode.

U kunt met queries records in tabellen selecteren, bewerken enzovoort.

U kunt ook programmacode schrijven om tabellen te raadplegen, te bewerken of aan te maken. U maakt dan gebruik van opdrachten uit de DAO of ADO bibliotheek van Access. Access 97 kent alleen de Data Access Objects (DAO) bibliotheek, Access 2000 en XP gebruiken standaard de ActiveX Data Objects (ADO) bibliotheek. In de Help van de VBA en in boeken over programmeren in VBA kunt u meer lezen over de verschillen hiertussen.

Wanneer u een programma uitsluitend in Access 2000 of XP gebruikt, dan is het aan te raden om uw programmacode in ADO te schrijven. Hoewel Access 2000 en XP wel DAO-programmacode kunnen verwerken, kan de performance van uw programma met ADO-code aanzienlijk verbeterd worden. Wilt u het programma terug converteren naar Access 97 dan moet u de betreffende programmacode in Access 97 herschrijven naar DAO.

Enkele voorbeelden van programmacode in DAO en ADO:

Lees veld Veld uit het huidige record van de tabel tblBron:

In DAO / Access 97:

Dim dbs As Database

Dim rst As Recordset

Dim strSQL As String

Dim strVeld As String

Set dbs = CurrentDb()

strSQL = "Select * From tblBron"

 

Set rst = dbs.OpenRecordset(strSQL)

strVeld =  rst!Veld

rst.Close

 

dbs.Close

In ADO / Access 2000/XP enz.:

(In de VBA-editor moet bij Extra >> Verwijzingen de Microsoft ActiveX Data Objects library aan staan)

Dim rst As New ADODB.Recordset

Dim strSQL As String

Dim strVeld As String

strSQL = "Select * From tblBron"

 

rst.Open strSQL, CurrentProject.Connection, adOpenKeyset, adLockOptimistic

strVeld = rst!Veld

rst.Close

Maak in de tabel tblBron een nieuw record met de velden Veld1 en Veld2 uit de waarden txtVeld1 en txtVeld2 van het huidige formulier:
(de code Me verwijst altijd naar het huidige formulier)

In DAO / Access 97:

Dim dbs As Database

Dim rst As Recordset

Dim strSQL As String

Set dbs = CurrentDb()

strSQL = "Select * From tblBron"

 

Set rst = dbs.OpenRecordset(strSQL)

With rst

    .AddNew

    !Veld1 = Me!txtVeld1

    !Veld2 = Me!txtVeld2

    .Update

    .Close

End With

dbs.Close

In ADO / Access 2000/XP enz.: (in de VBA-editor moet bij Extra >> Verwijzingen de Microsoft ActiveX Data Objects library aangevinkt zijn)

 

Dim rst As New ADODB.Recordset

Dim strSQL As String

strSQL = "Select * From tblBron"

 

rst.Open strSQL, CurrentProject.Connection, adOpenKeyset, adLockOptimistic

With rst

    .AddNew

    !Veld1 = Me!txtVeld1

    !Veld2 = Me!txtVeld2

   .Update

    .Close

End With

Maak een nieuwe tabel tblNieuw met de velden Tekstveld1, Tekstveld2, Memo1 en Datum1:

In DAO / Access 97:

Dim dbs As Database

Dim tbl As TableDef

 

Set dbs = CurrentDb()

Set tbl = dbs.CreateTableDef("tblNieuw")

 

With tbl

    .Fields.Append .CreateField("Tekstveld1", dbText, 30)

    .Fields.Append .CreateField("Tekstveld2", dbText, 6)

    .Fields.Append .CreateField("Memo1", dbMemo)

    .Fields.Append .CreateField("Tekstveld1", dbDate)

End With

 

dbs.TableDefs.Append tbl

dbs.Close

In ADO / Access 20000/XP en verder:
Wanneer u een tabel in ADO wilt aanmaken dan moet u ook in de VBA-editor bij Extra >> Verwijzingen de Microsoft ADO Ext. voor DLL and security aanzetten.
ADO kent geen memo-veld, gebruik in plaats hiervan een tekstveld met onbeperkte lengte.

Dim cat As New ADOX.Catalog
Dim tbl As New Table

Set cat.ActiveConnection = CurrentProject.Connection
tbl.Name = "tblNieuw"

tbl.Columns.Append "Tekstveld1", adVarWChar, 30
tbl.Columns.Append "Tekstveld2", adVarWChar, 6

tbl.Columns.Append "Memo1", adVarWChar
tbl.Columns.Append "Datum1", adDate


cat.Tables.Append tbl

Tips op andere websites

Een goede uitleg van de, in de helpteksten van Access slecht gedocumenteerde RunCommand items vindt u op: http://home.clara.net/tkwickenden/ (met dank aan Jaap en Harry). 

Deze pagina is voor het laatst bijgewerkt op 21-01-06.

Terug naar homepage