VBA kent - zoals elke programmeertaal - een groot aantal standaard-
of bibliotheekfuncties.
We illustreren er enkele van in het venster
"Foutopsporing".
Een functie is een stukje programma dat een waarde
oplevert.
Meestal zal je één of méérdere parameters moeten
meegeven bij het aanroepen van een functie. Zo hebben de functies
Ucase, Fix en Year één parameter terwijl de functie Mid$ er
drie heeft. De parameter(s) is/zijn als het ware de
grondstof(fen) waarmee het afgewerkt product moet gemaakt worden.
Naast het aantal is ook het type der parameters van belang. Zo
heeft de functie Ucase een parameter van het type string, terwijl
de functie Fix er een heeft van het type Numeriek.
Nu kan je naast standaardfuncties ook je eigen functies gebruiken. Je moet ze dan wel eerst maken...
Voorbeeld 1: de functie EersteLetterHoofdletter
Je wil van een woord steeds de eerste letter als hoofdletter en de rest als kleine letter(s) afdrukken.
Je kiest in het Module-ontwerpscherm voor Invoegen,Procedure
of drukt de knop
en je komt in het volgend dialoogvenster terecht:
Je geeft de functie een naam, klikt het keuzerondje 'Functie' aan en kiest 'OK'. De eerste en laatste regel van de functie verschijnen dan spontaan op het scherm:
Public Function EersteLetterHoofdletter()
End Function
Aan jou om de rest in te vullen:
Tussen de haakjes achter de functienaam declareer je zoveel
variabelen als er parameters zijn. (Straks letten we ook
op het type.) Bij het oproepen van een functie of een
subprocedure wordt/worden (meestal) namelijk één of meerdere
waarden (parameters, benoemde argumenten) meegegeven. De in de
functie geschreven bewerkingen zullen op of met deze gegevens
uitgevoerd worden. Dit veronderstelt echter dat binnen de
'werkruimte' van de functie de doorgegeven waarden kunnen
onthouden worden. Dit is de rol van de variabelen tussen de
haakjes in de hoofding van de functie. De waarden, meegegeven met
de functie-oproep, worden in deze 'parametervariabelen'
gecopieerd. (Dit kan op 2 manieren: parameterbinding 'by
reference' en 'by value':cfr subprocedures.)
In de laatste regel wordt aan de functie een waarde toegewezen.
Deze begint steeds met de naam van de functie gevolgd door het
toewijzingsteken (=).
Je kan de functie nu uitvoeren of oproepen als betrof het een
standaardfunctie. We doen dit even in het venster
'Foutopsporing':
Bij het declareren van parametervariabelen en/of geheugenvariabelen kan je het TYPE ervan aangeven. Doe je dit niet dan neemt ACCESS het type VARIANT. Variabelen van dit type zijn automatisch converteerbaar naar de meeste andere types , doch nemen meer plaats in het geheugen en worden trager verwerkt.
Wij nemen als richtlijn het type van een geheugenvariabele of een parametervariabele zelf te bepalen!
Je kan ook het type van het resultaat van de functie expliciet opgeven. Je doet dit achter de haakjes in de functiehoofding na het woordje 'As'. Vul je niets in, dan is het type 'Variant'.
Volgende hoofdingen zijn alle correct voor onze functie doch zijn niet identiek:
Public Function EeersteLetterHoofdletter(x)
Public Function EeersteLetterHoofdletter(x As String)
Public Function EeersteLetterHoofdletter(x As String) As String
In de volgende tabel zijn enkel de elementen van de syntax opgenomen die in de voorbeelden aan bod kwamen. Dit zijn de meest voorkomende en daarom de belangrijkste. De volledige syntax van de instructie FUNCTION vind je natuurlijk in de helpschermen.
| instructie FUNCTION: Declareert de naam, argumenten
en programmacode Syntaxis : [Public] Function naam [(argumenten)] [As type] |
Er zijn dus 2 verschilpunten met de syntax van een SUB:
opmerking: in het venster
'Foutopsporing'kan je variabelen onmiddelllijk initialiseren
zonder een expliciete declaratie. Het type is steeds Variant.
Is het type van een/de parameter(s) in een functiehoofding
bepaald, dan moeten de doorgegeven waarden van exact hetzelfde
type zijn behalve als bedoeld type 'Variant' is. Veranderen we
bijvoorbeeld de hoofding van onze functie als volgt:
EersteLetterHoofdletter(x As String) dan is het niet meer
mogelijk de functie te testen met de waarde uit de variabele
'varWoord' daar deze van het type Variant is en de functie een
waarde van het type string verwacht!
Het type van een variabele kun je opvragen met de functie Vartype.
Voor strings is dit de waarde 8. Doe je dit nu met onze variabele
'varWoord', dan krijg je 8 ook al is 'varWoord' van het type
Variant! Dit komt omdat ACCESS een intern type toewijst
aan variabelen van het type Variant en dit op grond van de
actuele inhoud. Het is deze waarde die weergegeven wordt met de
functie Vartype. Deze verandert dus zodra 'varWoord' een inhoud
van een ander type krijgt. Bij het doorgeven van de waarde van
'varWoord' geldt echter steeds het type Variant. Zowaar een
addertje onder het gras!
Voorbeeld 2 : de functie 'Beoordeling'
Bij het resultaat van een leerling moet een beoordeling afgedrukt worden gaande van 'grootste onderscheiding' tot 'onvoldoende'. De punten en het maximum worden aan de functie doorgegeven.
| Public Function Beoordeling(sngPtn,
sngMax As Single) As String Dim sngPercent As Single sngPercent = Format(ptn / max * 100, "#.00") Select Case sngPercent Case Is >= 90 Beoordeling = "Grootste onderscheiding" Case Is >= 80 Beoordeling = "Grote onderscheiding" Case Is >= 70 Beoordeling = "Onderscheiding" Case Is >= 60 Beoordeling = "Eervolle vermelding" Case Is >= 50 Beoordeling = "Voldoening" Case Else Beoordeling = "Onvoldoende" End Select End Function |
In de hoofding van de functie staat dat 2 waarden van het type 'Single' zullen worden aangeboden wanneer de functie wordt opgeroepen. Uiteraard is de volgorde belangrijk. De functie levert een resultaat op van het type 'string'.
opmerking:
Bij het opgeven van de parameters kunnen de aanduidingen 'Optional', 'ByVal', ByRef' gebruikt worden. Dit is ook het geval bij subprocedures.
Functies kan je gebruiken overal waar je een expressie gebruikt. Dit is o.a.
Natuurlijk kan je functies ook gebruiken in het venster 'Foutopsporing', doch dit is enkel voor testdoeleinden en werd reeds geïllustreerd in de voorbeelden.
Stel dat we in onze database 'Boeken.mdb' een tabel met o.a. de namen en geboortedata van leerlingen bijhouden. We willen een lijst met de naam, de geboortedatum en de leeftijd van alle leerlingen. We maakten vroeger reeds de functie 'Leeftijd'. Deze staat in de algemene module 'basEigenFuncties'. Dit brengt mee dat deze functie in alle query's, formulieren en rapporten van de database kan gebruikt worden. Je maakt de query 'qryLeeftijd':

Een berekend veld geef je best een naam, anders wordt de naam 'Exprnnn' toegekend. Hier werd 'lt' (afkorting van leeftijd) gebruikt.
We willen een lijst van de leerlingen uit punt 7.4.4.1 die vandaag jarig zijn. We maakten vroeger de functie 'MaandDag'. Deze levert ons de maand en de dag van een datum. Indien dit voor de geboortedatum én voor vandaag dezelfde waarde oplevert is de betrokken leerling jarig. Je maakt de query 'qryVerjaardag':

De gegevens in een formulier hoeven niet per se uit een tabel of query te komen. Ze heten dan 'niet-afhankelijk'. Onderstaand voorbeeld toont hoe we de gemiddelde snelheid berekenen wanneer afgelegde afstand en benodigde tijd worden ingevoerd.
Het tekstvak 'Gemiddelde snelheid in km/u' heeft als
besturingselementbron de zelfgedefinieerde functie
GemiddeldeSnelheid(). Deze heeft 4 parameters: afstand, uren,
minuten en seconden.
De functie ziet er zo uit:
| Public Function
GemiddeldeSnelheid(strA, strU, strM, strS As String) As
Single Dim dblSeconden As Double dblSeconden = CDbl(strU) * 3600 + CDbl(strM) * 60 + CDbl(strS) If dblSeconden > 0 Then 'deling door nul kan niet GemiddeldeSnelheid = CDbl(strA) * CDbl(3600) / dblSeconden Else GemiddeldeSnelheid = 0 End If End Function |
In ons voorbeeld komen de parameterwaarden uit 4 tekstvakken van een formulier en zijn dus van het type 'string'. Ook al gebeuren een aantal typeconversies in ACCESS automatisch, toch wordt de conversie van 'string' naar getal IN de functie expliciet aangegeven (CDbl). Zo hebben we een duidelijker beeld van de gegeventypes waarmee we werken.
We voegen een paar elementen aan ons voorbeeld toe:
Hiervoor gebruiken we 2 nieuwe functies:MijnTijd
(de functie 'Tijd' bestaat reeds in ACCESS; deze naam mag daarom
niet gekozen worden) en TussenGrenzen. De eerste functie vormt
met de uren, minuten en seconden één waarde van het type 'Date'
terwijl de tweede nagaat of een getal tussen 2 opgegeven grenzen
ligt.
| Public Function
MijnTijd(strU, strMin, strSec As String) As Date MijnTijd = CDate(strU + ":" + strMin + ":" + strSec) MijnTijd = Format(MijnTijd, "hh:mm:ss") End Function |
De functie bepaalt de waarde van het tekstvak txtTijd. Bij de
eigenschap 'Besturingselementbron' is dus ingevuld:
=MijnTijd([txtUren];[txtMinuten];[txtSeconden])
De functie 'TussenGrenzen' wordt gebruikt om na te gaan of de ingevoerde waarde bij de tekstvakken txtAfstand, txtUren, txtMinuten en txtSeconden tussen bepaalde grenzen ligt. De ingevoerde waarde en de 2 grenswaarden worden als parameterwaarden doorgegeven.
Select Case sngWaarde Case Is Case Is > sngMax TussenGrenzen = 2 ' getal is te groot Case Else TussenGrenzen = 0 ' getal ligt tussen de grenzen End Select End Function |
De functie TussenGrenzen heeft 3 mogelijke teruggavewaarden.
De invoercontrole wordt uitgevoerd vòòrdat de waarde van het
ingevulde tekstvak wordt bijgewerkt. We wijzen daarom een sub toe
aan de eigenschap 'Voor Bijwerken' van de 4 tekstvakken waarin
een waarde moet ingevuld worden. De 4 subs zijn analoog. Je vindt
er hier één:
| Private Sub
txtMinuten_BeforeUpdate(Cancel As Integer) Dim intOK As Integer intOK = TussenGrenzen(CSng(txtMinuten), 0, 59) Select Case intOK Case 0 'Getal is OK. Case 1 MsgBox ("Het getal is te klein!") Cancel = True Case 2 MsgBox ("Het getal is te groot!") Cancel = True End Select End Sub |
Bespreking:
Private Sub txtMinuten_BeforeUpdate(Cancel As Integer)
De sub heeft een parameter 'Cancel'. Hiermee kan je de gebeurtenis die aanleiding geeft tot het uitvoeren van de sub annuleren. Dit doe je wanneer een foutieve waarde werd ingevuld. Deze moet m.a.w. verbeterd worden. De parameter Cancel krijgt de waarde 'True' om de betrokken gebeurtenis te annuleren.
intOK = TussenGrenzen(CSng(txtMinuten), 0, 59)
Je roept de functie 'Tussengrenzen' op met de inhoud van het
actieve tekstvak. Omdat de door te geven waarde numeriek moet
zijn wordt deze eerst geconverteerd (CSng).De 2 andere parameters
zijn de onder- en de bovengrens.
Je kan de grenzen toch opgeven bij 'Validatieregel'? Ja, maar er zijn gevallen waar dit ontoereikend is zoals:
In zo'n gevallen brengt een sub bij de gebeurteniseigenschap 'Vòòr Bijwerken' de oplossing.
Er zijn nog meer cobtroles mogelijk bij de in te vullen tekstvakken: is er iets ingevuld?, is de invoer numeriek?,...). Dit kan gecontroleerd worden via 'Validatieregel', een sub bij 'Vòòr bijwerken' of een combinatie van de 2. Dit brengt ons bij het volgende punt.
Dit zijn de eigenschappen 'Invoermasker', 'Standaardwaarde' en
'Validatieregel'. In het ontwerpscherm van een tabel of formulier
tref je bij de eigenschappen van een veld of een
besturingselement de opbouwknop
aan. Klik je hier dan kan je een
expressie en dus ook een functie invullen.
Stel dat je in het formulier 'frmGemiddeldesnelheid(2)' een verband wil instellen tussen de afstand en de uren. Je kan dan een functie schrijven om bij het invoeren van de uren rekening te houden met de reeds ingevulde afstand. In ons voorbeeld is op deze wijze een minimumsnelheid ingesteld bij de eigenschap 'Validatieregel'. De ingevulde grenzen voor de uren zijn nul en het resultaat van de functie 'ControleUren'. Deze heeft als parameter de ingevoerde afstand en als resultaat het maximum aantal uren dat voor deze afstand wordt toegestaan.
| Public
Function ControleUren(strX As String) As Integer Select Case CDbl(strX) Case Is ControleUren = 1 Case Is ControleUren = 2 Case Is >= 30 ControleUren = 4 Case Else ControleUren = 99 End Select End Function |
|
7.4.6.1 Gebeurteniseigenschappen
Gebeurtenissen worden door 'ACCESS' gekoppeld aan gebeurteniseigenschappen. Bij het zich voordoen van een gebeurtenis kunnen we
Je ziet hieronder mogelijkheid 2 en 3.
Voorbeeld:
Je maakt of gebruikt een formulier op basis van
de tabel tblLeerlingen. Zet er de naam en de onderwijsvorm in.
De naam van een leerling uit het TSO moet cursief en niet vet,
deze van een BSO-leerling rechtop en vet worden getoond.
De gebeurtenis waarop moet gereageerd worden heet 'Current' of 'Aanwijzen'. Deze doet zich voor iedere keer dat er van record gewisseld wordt.
| Je kan de
gebeurtenisprocedure 'Bij aanwijzen' laten uitvoeren.
|
Private
Sub Form_Current() txtNaam.SetFocus txtNaam.SelStart = Len(txtNaam) Select Case [txtOnderwijsvorm].Value Case "TSO" txtNaam.FontItalic = True txtNaam.FontBold = False Case "BSO" txtNaam.FontItalic = False txtNaam.FontBold = True End Select End Sub |
Je kan eveneens de functie
NaamOpmaak laten uitvoeren. NaamOpmaak is een zelfgekozen
naam terwijl de naam 'Form_Current' automatisch wordt
aangemaakt. ![]() Let op het verschil in syntax op het eigenschappenblad! |
Private
Function NaamOpmaak() txtNaam.SetFocus txtNaam.SelStart = Len(txtNaam) Select Case [txtOnderwijsvorm].Value Case "TSO" txtNaam.FontItalic = True txtNaam.FontBold = False Case "BSO" txtNaam.FontItalic = False txtNaam.FontBold = True End Select End Function |
opmerkingen:
Het effect van beide werkwijzen is identiek. Het gebruik van een functie doet een beetje raar aan omdat er geen teruggavewaarde is op de klassieke manier. Velen geven daarom de voorkeur aan het gebruik van een gebeurtenisprocedure in dit verband. Je vindt de volledige lijst der mogelijke gebeurtenissen en der gekoppelde eigenschappen in het helpscherm 'Gebeurtenissen en gebeurteniseigenschappen, naslag'.
In een macro kan je VBA-code laten uitvoeren via de opdracht 'ProcedureUitvoeren'. Bij deze actie wordt je naar de functie gevraagd met de uit te voeren code. Het is niet mogelijk de naam van een 'SubProcedure' op te geven, enkel een 'Functieprocedure' wordt aanvaard.
De opdracht 'ProcedureUitvoeren' kan o.a. worden gebruikt bij het maken van een eigen menubalk. Dit valt evenwel niet binnen het bestek van dit hoofdstuk.