Wellicht weten sommige Word-gebruikers wel hoe ze een vaak te herhalen serie handelingen, tekst en manipulaties kunnen opnemen en met één toetscombinatie automatisch kunnen herhalen: een Word-macro. Maar zonder het te beseffen, gaan ze op die manier aan de slag met een bijzonder krachtige functionaliteit die achter elke module van Microsoft Office steekt: Visual Basic for Applications, kortweg VBA. Op deze manier gaat de deur open voor een wereld van zelf te ontwikkelen snufjes, trucjes en andere spitsvondigheden.

Via menu of toetsenbord

Druk in Word 2003/2007 op Alt+F11 en we komen in de VBA-editor terecht. Dit gaat ook via het Lint van Word 2007 (tabblad Ontwikkelaars / knop Visual Basic) of het menu in Word 2003 en eerder (kies Extra / Macro / Visual Basic Editor). Met diezelfde Alt+F11 schakelen we heen en weer tussen Word en de VBA-editor. Om een eerder opgenomen macro of zelf ontworpen VBA-programma uit te voeren, drukken we Alt+F8, of klikken we in Word 2007 op de knop Macro's op het tabblad Ontwikkelaars van het Lint (of in Word 2003: Extra / Macro / Macro's). Het starten van een macro-opname kan dan weer via de knop Macro opnemen (in Word 2003 en eerder: Extra / Macro / Nieuwe macro opnemen), maar gaat veel sneller als we dubbelklikken op het vensterpictogram (in Word 2003 en eerder: het OPN-vakje).

© PXimport

Een bewerking opnemen als een macro is de eenvoudigste manier om VBA-code te produceren.

Niet alleen in Word

Nagenoeg alle basisvaardigheden die in deze Expertcursus beschreven worden, gelden ook in elke andere module van Microsoft Office: probeer maar eens dingen uit in Excel, PowerPoint, Outlook, Access, Project of Visio. Sterker nog: er bestaat heel wat software van andere partijen, die er eveneens voor gekozen hebben om VBA als macrotaal aan te bieden, compleet met de VBA-editor en alle vermelde sneltoetsen, waaronder AutoCAD, iGrafx FlowCharter, CorelDRAW, WordPerfect Office, BusinessObjects, etc.

De eerste stappen

De eenvoudigste toegang tot de wereld van VBA, is het in een macro opnemen van een bewerking, die u vervolgens uitbreidt en verfijnt door er extra functionaliteit bij te coderen. Stel bijvoorbeeld dat u besluit om in een bestaand document elke zin binnen een tekstblok te laten volgen door twee spaties in plaats van één. Een eerste aanpak hiervoor is het herhaaldelijk oproepen van de zoek/vervangfunctie (zie ook de Expertcursus 'Zoek en vervang' in het vorige nummer van Computer!Totaal): zoeken naar een punt gevolgd door een spatie en vervangen door een punt met twee spaties. Dan opnieuw beginnen voor het vraagteken, het uitroepteken, etc. Dit moet sneller en ­eleganter kunnen, toch? Op naar VBA!

De VBA-editor

Laten we die eerste vervangslag opnemen in een macro waarvoor we de standaard voorgestelde benaming Macro1 aanvaarden en aangeven dat we die wensen op te slaan in het huidige Document1. Vervolgens drukken we Alt+F11, en we belanden in de VBA-editor. Vanaf hier dienen we een tweetalige wereld te aanvaarden: de gebruiksinterface blijft in het Nederlands (of in welke taal Word ook gebruikt wordt), maar de code is altijd in het Engels, zelfs al dient die om een Nederlandstalige Word te automatiseren. De voornaamste werkruimtes binnen de VBA-editor zijn het Codevenster en de Projectverkenner. Die laatste toont in een boomstructuur alle actieve documenten en sjablonen. We klappen Project (Document1) uit, en we zien drie takken: Microsoft Word -objecten, Modules en Verwijzingen, telkens met één onderliggend niveau. Onder Modules is dat NewMacros. Als we tenslotte op NewMacros dubbelklikken, dan verschijnt de code die we (onbewust) gegenereerd hebben in het codevenster

© PXimport

Met Alt+F11 komen we vanuit elke module van Microsoft Office in de VBA-editor terecht.

Structuur

Een op zichzelf staand stuk programmatuur wordt in VBA een subroutine genoemd. Vandaar dat alle code die het bevat tussen de instructies Sub en End Sub staat. De beginnende Sub wordt gevolgd door een zelf te kiezen naam voor de routine. Gaat het om een opgenomen macro, dan is dit de naam die men in de dialoog van Word gekozen heeft vóór de opname begon. Maar dit kan in de editor nog gewijzigd worden. De naam die u gebruikt, wordt getoond in de lijst van beschikbare macro's die u opent met Alt+F8.

Tussen deze twee regels kunnen instructies en declaraties komen, in principe één per regel, tenzij ze gescheiden worden door dubbele punten. Een regel die begint met een apostrof (') duidt een commentaarregel aan. Dergelijke stukken tekst hebben geen invloed op het verloop van het programma: ze worden overgeslagen en dienen dus alleen als documentatie. Automatisch worden ze in het groen gezet door de VBA-editor. Gereserveerde sleutelwoorden komen in het blauw, de overige tekst in het zwart, regels met fouten in het rood. Een regel broncode wordt afgesloten door op Enter te drukken: gebruik geen punten of andere leestekens, tenzij de code (om redenen van leesbaarheid, bijvoorbeeld) op de volgende regel verder gaat: dan beëindigen we de regel met een spatie en een 'underscore' (het platliggende streepje: _).

Declaraties zijn voorafgaande aankondigingen van variabelen die we van plan zijn te gebruiken, met hun type. Dergelijke meldingen beginnen met het sleutelwoord Dim, gevolgd door een zelf te kiezen naam voor de variabele, dan As en het type (zie kader). Ze zijn facultatief, tenzij Variabelen declareren vereist aangekruist staat in het tabblad Editor onder Extra / Opties, of als we in het begin van de code (dus nog vóór de eerste Sub-regel) de instructie Option Explicit plaatsen.

© PXimport

In de opties van de VBA-editor duiden we aan of we variabelen expliciet gedeclareerd willen hebben.

© PXimport

Objecten en eigenschappen

VBA is een objectgeoriënteerde programmeertaal. Dit komt neer op het bestempelen van alle onderdelen van Word als zogenoemde objecten: zo wordt indien dat het geval is de geselecteerde tekst of zo niet de plaats waar de cursor zich bevindt, het Selection-object. Een object kan andere, onderliggende objecten bevatten, heeft eigenschappen en voert methoden uit. Stel dat we een zoek/vervangbewerking willen starten vanaf de plaats van de cursor. Dan dienen we eerst een Find-object te definiëren, dat onderliggend is aan die Selection. We duiden dit aan door Selection te laten volgen door een punt, en de naam van het afhankelijke object Find. Wellicht merkt u daarbij de uiterst behulpzame rol van IntelliSense: bij het intikken van het punt komt spontaan een lijst te voorschijn met de toegelaten woorden vervolgcode. De eigenschappen van het Find-object hebben te maken met de zoekdefinitie, en komen overeen met alle parameters die we in het overeenstemmende dialoogvenster van Word aantreffen: zo kent het bijvoorbeeld de eigenschappen Text en Replacement, die respectievelijk de waarde van de te zoeken tekst en de eventuele vervangtekst dienen te krijgen. Een andere eigenschap is Forward, waarmee we aangeven of de vervangoperatie verder naar het einde van het document toe dient te gebeuren, of in de andere richting. Een Waar- of NietWaar-situatie dus. Daarom krijgt deze eigenschap geen tekst, maar een logische waarde (True of False).

© PXimport

Het intikken van een punt na een objectnaam volstaat vaak om keurig geholpen te worden door IntelliSense, zoals hier na Selection.

© PXimport

Tikken we vervolgens de eerste letter in van wat we denken te zoeken, dan positioneert IntelliSense de lijst netjes in de buurt van het gezochte.

© PXimport

Na de keuze van het Find-object komen we op een vergelijkbare manier aan de Execute-methode.

© PXimport

Het intikken van de spatie na Execute levert een handige en leesbare tooltip op met de bruikbare argumenten.

Standaardwaarden

Soms zijn de standaardwaarden van eigenschappen ook de gewenste. In zo'n gevallen dient de eigenschap niet expliciet vermeld te worden. Deze standaardwaarden kunnen we te weten komen via de helpfunctie, maar code is duidelijker, ondubbelzinniger en leesbaarder als we elke relevante eigenschap tonen: iets meer tik- en selectiewerk, maar minder twijfel!

De eigenlijke zoek- en/of vervangactie starten we tenslotte door de methode Execute op het object los te laten. Een methode kan argumenten of parameters hebben. In dit geval is er het Replace-argument, dat maar een beperkt aantal mogelijkheden biedt. Deze worden intern voorgesteld door getallen, maar ze hebben ook een meer leesbare VBA omschrijving mee gekregen, zogenaamde WdReplace-constanten: de waarde wdReplaceAll meegeven met Replace komt neer op een keuze voor de knop Alles vervangen in het dialoogvenster. Niet verwonderlijk dus dat de andere mogelijkheden hier wdReplaceNone en wdReplaceOne zijn. Denk bij twijfel niet alleen aan de F1-knop, maar ook aan de F2-knop: hiermee komen we in het Objectenoverzicht terecht, waarin we een alfabetische lijst van alle mogelijke objecten terugvinden. Een klik op WdReplace levert dan rechts een opsomming van alle toegelaten waarden op.

© PXimport

De F2-knop brengt ons in het Objectenoverzicht van alle toegelaten objecten, eigenschappen, methoden, constanten, etc.

© PXimport

© PXimport

Lussen

Door lussen in te bouwen, kunnen we zich herhalende handelingen automatiseren. Er zijn lussen van het type Do...Loop, While...Wend en For...Next (zie de twee kaders hieronder).

© PXimport

© PXimport

Het eerste type is het soepelste en krachtigste: met While of Until kunnen we een conditie toevoegen, die beslist over het al of niet herhalen van alle instructies binnen de lus. En er kan altijd onverhoeds uitgestapt worden met een Exit Do-instructie, bijvoorbeeld als ergens binnen de lus aan een bepaalde conditie voldaan is. Willen we controle houden over het aantal keer dat een lus doorlopen wordt, dan gebruiken we beter de For...Next, die bovendien bij elke herhaling een tellervariabele op- of aftelt. In een dergelijke lus kunnen we indien nodig gebruik maken van de tussenwaarde van die teller. Het is zelfs mogelijk om zijn waarde aan te passen vanuit de eigen code, maar dit is dan wel om problemen vragen.

Stel dat we in een lus alle mogelijke manieren vinden waarop een zin beëindigd kan worden. We zouden dan de enige spatie die daarop volgt willen vervangen door twee spaties. Een mogelijke aanpak hier is eerst alle mogelijke eindetekens in een tekststring te stoppen en die vervolgens teken per teken te doorlopen, om er telkens een zoek/vervangbewerking mee te voeden. Voor de eerste stap declareren we een tekstvariabele en geven die een betekenisvolle naam, bijvoorbeeld:

[code]Dim AlleEindeTekens As String[/code]

Namen van variabelen dienen aan elkaar te worden geschreven. Soms worden underscores gebruikt om naamgedeelten van elkaar te scheiden, bijvoorbeeld Alle_Einde_Tekens. Hoofd- of kleine letters spelen geen rol. Het eerste karakter dient altijd een letter te zijn: 1Var mag dus niet, Var1 wel. Vervolgens geven we die de gepaste waarde. De inhoud van een tekstvariabele wordt tussen aanhalingstekens meegegeven.

© PXimport

Klik hier om de code te downloaden

 

Tenslotte komt de lus aan bod. Hierbij dienen we de drie karakters uit AlleEindeTekens te halen en aan een zoek/vervangbewerking mee te geven. Bovendien willen we de code herbruikbaar houden, mochten we ooit nog andere tekens willen toevoegen aan de operatie. Twee functies komen ons daarbij van pas: Mid laat toe om een aantal karakters uit een tekststring te halen en Len berekent de lengte van een tekst (zie kader De belangrijkste tekstfuncties hieronder).

© PXimport

Twijfel over de juiste syntax? Plaats de cursor ergens in Mid en druk op F1.

© PXimport

Een en ander leidt ons tot het volgende stukje aangepaste code. We vertrekken daarbij van wat we eerder opgenomen hadden (het vervangen van een punt gevolgd door één spatie door een punt met daarna twee spaties), en spreiden er een For...Next-lus overheen. Onze inbreng beperkt zich dus tot de blauwe coderegels.

© PXimport

Klik hier om de code te downloaden

 

Zie de alternatieve, kortere manier om te verwijzen naar eigenschappen en methoden van een object met behulp van With...End. Dit vermijdt dat de objectnaam Selection.Find nog negenmaal herhaald zou moeten worden. Het verhoogt bovendien de leesbaarheid en voert sneller uit.

Op zoek naar de kortste routine

Opgenomen code bevat doorgaans heel wat overbodige instellingen, die we mogen schrappen als we er zeker van zijn dat de instellingen van (bijvoorbeeld) de zoek/vervangdialoog nog steeds de standaardwaarden vertonen. Laten we de Option Explicit achterwege (een gevaarlijke, maar vaak toegepaste slordigheid in VBA en verwante talen), dan kunnen we eveneens de declaraties overboord gooien. Dit levert de volgende minimalistische subroutine op, die precies hetzelfde effect heeft:

© PXimport

Klik hier om de code te downloaden

Maar besparen op tikwerk is niet altijd een goede zaak. In dit voorbeeld hebben we de Len-functie en (zelfs tot tweemaal toe) de Mid-functie in de lus ondergebracht. Dit betekent dat de berekening van hun resultaat bij elke herhaling opnieuw uitgevoerd gaat worden. Niet dat we de extra rekenkracht die dit vergt, echt gaan voelen op een doorsnee hedendaagse pc, maar in complexe programma's, waarin misschien nog veel andere dingen dienen te gebeuren in zo'n lus, is dit wel een aandachtspunt.

Matrices

Om knip- en plakwerk via allerlei tekstfuncties te vermijden, vormen matrices ('arrays' in het Engels) een interessant alternatief. We stoppen eerst onze eindetekens als losse karakters in een matrix door middel van de Array-functie, en doorlopen die vervolgens in een lus. Geen functies meer nodig, geen onnodig rekenen. Opgelet: het eerste element van een matrix krijgt altijd de index 0, tenzij we dit expliciet anders zouden willen. Dit laatste is instelbaar met de instructie Option Base.

© PXimport

Klik hier om de code te downloaden

Willen we vermijden om de bovenlimiet van de matrix hard gecodeerd in de subroutine te hebben, dan kunnen we ook de functie UBound (als in 'Upper Bound' of bovengrens) gebruiken.

[code]For k = 0 To UBound(AlleEindeTekens)[/code]

Als de matrix AlleEindeTekens drie elementen bevat, dan zal dat standaard op de plaatsen met index 0, 1 en 2 zijn, en dan is UBound(AlleEindeTekens) gelijk aan de hoogste van die indices, dus 2.

© PXimport

Drie subroutines, driemaal hetzelfde ­effect, maar het blijft zoeken naar het beste compromis tussen hoeveelheid tikwerk en leesbaarheid.

Tot slot

Laat u niet afschrikken door de ogenschijnlijke complexiteit van de macrotaal van Word. Eenvoudig is anders, maar met een beetje experimenteren is er heel veel mogelijk. Via deze link vindt u meer informatie en enkele uitgebreide voorbeelden, zodat u binnen een oogwenk uw eigen macro in elkaar sleutelt! Succes!

En de toekomst?

Microsoft kwam voor het eerst op de proppen met VBA in 1993. We hebben dus te maken met een heus oudje in de informatica­wereld. Sinds 2007 wordt het ook niet langer ter beschikking gesteld aan derden. Maar gezien het nog steeds achter de meest recente versie 2007 en de toekomstige 2010 release van Microsoft Office te vinden is en zal zijn, en Microsoft er garant voor staat dat alle VBA-ontwikkelingen nog perfect gaan werken onder Vista, Windows 7 en Server 2008, zijn we zeker nog enkele jaren zoet met deze programmeertaal.

Deel dit artikel
Voeg toe aan favorieten