VBA uitbreiden met de mogelijkheden van API's.
Niettegenstaande VBA over veel functies beschikt komt men in bepaalde situaties waar VBA functies niet volstaan of waar bepaalde bewerkingen
in VBA niet mogelijk zijn. Windows beschikt over uitgebreide bibliotheken van functies waarop mijn via VBA beroep kan doen.
Men spreekt van Windows API (application programming interface). Beroep doen op API in VBA is niet echt gebruiksvriendelijk, en de datatypes die er gebruikt worden verschillen van deze in VBA.
De Windows API bestaat uit verschillende DLL's (Dynamically Linked Library).Alle toepassingen onder Windows interacteren op één of andere
wij met de DLL's.
Om beter te begrijpen in de VBA editor kan men via het menu Tools, Referenties een link leggen naar vb ADO-bibliotheek, Microsoft Scripting Runtime...enz. Het gebruik maken van API's komt in feite op het zelfde neer, maar kan echter niet via het Tools menu gerealiseerd worden.
Hier moet men aanduiden welke DLL men wil gebruiken en bovendien specifiëren welke functie ervan. Dit doet men door het declaren van API's. Daartoe moet men gebruik maken van het Declare statement,in de declaratie sectie van een module indien nodig op module niveau. De syntax :
Het Declare Sleutelwoord betekent dat VBA beroep wil doen op een functie in een DLL en bepaalt tevens indien het gaat over een functie of een sub. In een Class-module moet het Declare statement steeds Private zijn.
Opgepast :
Functies en Sub's in de Windows API zijn in de taal C of C++ geschreven en aanvaarden argumenten net zoals functies en sub's in VBA.
Echter de datatype's verschillen van de vertrouwde VBA datatype's, bovendien kunnen sub-routines, opnieuw in tegenstelling met VBA, wel
waarden teruggeven.
En om het nog verwarrender te maken de verwijzingingen ByVal en ByRef worden anders geïnterpreteerd dan in VBA.Volgens
de nagelezen literatuur en artikelen zou VBA daaromtrent inconsistent zijn.
Bij VBA is het zo dat :
ByRef geeft een verwijzing (pointer) door naar de locatie in het geheugen waar de variabele opgeslagen wordt, maar die toelaat dat de waarde zelf
gewijzigd wordt.
ByVal by ByVal wordt de waarde van de variabele wordt doorgegeven en eventuele wijzigingen in de waarde lokaal blijven in de aangeroepen
routine en niet terug gegeven worden aan de aanroepende routine.
Dat is zo voor zowel string als numerieke waarden.
Het voorbeeld hierna verduidelijkt dit :
Private Sub sWijzigByRef(ByRef intEenwaarde As Integer)
intEenwaarde = 100
End Sub
Private Sub sWijzigByVal(ByVal intEenwaarde As Integer)
intEenwaarde = 1000
End Sub
Private Sub sWijzigStringByRef(ByRef strEenstring As String)
strEenstring = "Slecht bier!"
End Sub
Private Sub sWijzigStringByVal(ByVal strEenstring As String)
strEenstring = "Slechte wijn!"
End Sub
Public Sub sTestByRef_ByVal()
Dim intWaarde_1 As Integer
Dim intWaarde_2 As Integer
Dim strString_1 As String
Dim strString_2 As String
intWaarde_1 = 333
intWaarde_2 = 444
strString_1 = "Lekker biertje"
strString_2 = "Lekker wijntje"
Call sWijzigByRef(intWaarde_1)
Debug.Print "de waarde was 333 en is na ByRef " & intWaarde_1
Call sWijzigByVal(intWaarde_2)
Debug.Print "de waarde was 444 en is na ByVal " & intWaarde_2
Call sWijzigStringByRef(strString_1)
Debug.Print "Lekker biertje is na ByRef " & strString_1
Call sWijzigStringByVal(strString_2)
Debug.Print "Lekker wijntje is na ByVal " & strString_2
End Sub
Laat men bovenstaande routine lopen dan is het resultaat:
de waarde was 333 en is na ByRef 100
de waarde was 444 en is na ByVal 444
Lekker biertje is na ByRef Slecht bier!
Lekker wijntje is na ByVal Lekker wijntje
Stringwaarden in DLL's zijn in C-taal gekend als LPSTR objecten. De DLL's kunnen de grootte van een string niet wijzigen eens die
gecreëerd is, wat erop neerkomt dat de opgegeven string voldoende groot moet zijn om de door de DLL geretourneerde waarde te kunnen
bevatten en bovendien moet de string eindigen met een ANSI nulwaarde.
In VBA kan men dit via de Space en Chr functies :
strEen String = Space(255) & Chr(0) indien ook de grootte als argument moet gegeven worden :
lngGroot = 256
Het probleem met API functies is dat men hun functionaliteit moet kennen, wat voor mij althans niet altijd evident is. Als Access ontwikkelaar
heb ik hier en daar voorbeelden gevonden, en sommige heb ik in mijn eigen projecten ook toegepast.
Ik geef daar ook enkele voorbeelden van. Het is vooral handig API Functies in te kapselen in Class-modules, onder deze rubriek ook enkele voorbeelden.