Most Valuable Professional


View Jan Karel Pieterse's profile on LinkedIn subscribe to rss feed
Subscribe in a reader

Subscribe to our mailing list

* indicates required

Audit !!!

Probeer onze RefTreeAnalyser
de beste Excel formule auditing tool.

Cursussen

Excel VBA Masterclass (Engels)
Excel VBA voor Financials

Third party tools

Speed up your file

FastExcel
The best tool to optimise your Excel model!

Repair your file

Stellar Phoenix Excel Repair
Best tool to repair corrupt Excel sheets and objects
Home > Nederlandse site > Artikelen > Invoegtoepassing bouwen > Applicatie events
This page in English

Bouwen van een invoegtoepassing voor Excel, Applicatie events

In zijn huidige staat laadt onze invoegtoepassing netjes de lijst met tabbladnamen van de actieve werkmap. Maar dat is dan ook alles; zodra we van map wisselen of van tabblad wisselen wordt de keuzelijst niet bijgewerkt. Dat is ook logisch, want er is niets in de programmacode dat dat regelt.

De benodigde events

Wat hebben we nodig? We willen dat het lint wordt bijgewerkt zodra:

Normaalgesproken, als je VBA code in een werkmap schrijft, dan zou je event macro's toevoegen aan de ThisWorkbook module. Events als deze:

Private Sub Workbook_Activate()
End Sub

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
End Sub

Maar deze events reageren alleen op gebeurtenissen binnen die werkmap. Wat wij nodig hebben zijn events die voor iedere werkmap gelden. We noemen dat Applicatie events.

Een klasse module

Houd je vast, we gaan een klassemodule invoegen. Jazeker! We hebben een klassemodule nodig om dergelijke applicatie events te kunnen gebruiken.

Chip Pearson heeft een uitstekend artikel over Applicatie events geschreven. Ik hoef niet meer naar zijn website te gaan om dat artikel te lezen om deze stof te doorgronden, maar als dit nieuw voor je is, dan raad ik je aan het artikel te lezen.

Dus voeg een klasse module in en noem deze clsApp:

Class module

Bovenaan de module declareren we een object variabele met het speciale sleutelwoord "WithEvents":

Public WithEvents App As Application

Hiermee weet de compiler dat App een variabele is van het type Application die tevens events moet ophalen uit het applicatie object. Het lijkt of er niets bijzonders is gebeurd, maar de kleine dropdowns bovenaan het modulevenster bevatten nu links een nieuw object (App):

The top-left dropdown of the classes code window

als je die kiest kan je in de rechter dropdown alle Application Events zien staan. Het standaard event wordt tevens ingevoegd in de module:

Private Sub App_NewWorkbook(ByVal Wb As Workbook)

End Sub

Meestal is dat niet degene die ik wil hebben, maar met de dropdown kan je nu degene kiezen die je wel wilt. (de eerste halen we later wel weer weg):

The lefthand dropdown, showing the available events

Jazeker, alle applicatie events staan tot je beschikking! Kies degenen die je nodig hebt, tot je deze regels hebt:

Private Sub App_SheetActivate(ByVal Sh As Object)
    InvalidateRibbon
End Sub

Private Sub App_WorkbookActivate(ByVal Wb As Workbook)
    InvalidateRibbon
End Sub

Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
    InvalidateRibbon
End Sub

Private Sub Class_Terminate()
    Set App = Nothing
End Sub

Merk op dat ik InvalidateRibbon ertussen heb gezet, een subroutine in modRibbonX die er zo uitziet:

Sub InvalidateRibbon()
    moRibbon.Invalidate
End Sub

Alleen die simpele "Invalidate" methode is afdoende om Excel duidelijk te maken dat het onze hele lintaanpassing opnieuw moet doen. Simpeler kan niet. Tenslotte heb ik nog het terminate event van de klasse zelf toegevoegd om ervoor te zorgen dat bij beeindigen van onze code alle object variabelen netjes op "Nothing" worden gezet. Het huis altijd opgeruimd achterlaten is ook voor VBA developers belangrijk!

De klasse aan het werk krijgen

Een klasse module is niets meer dan een blauwdruk van code. Anders dan bij een normale module kane je code in een klasse module niet zomaar uitvoeren. Je moet een kopie van de klasse in het geheugen laten laden. Het is die kopie (ontwikkelaars noemen dat een "instantie") die het werk gaat doen. Ik heb dit gedaan in een normale module genaamd modInit.

Bovenaan deze module is een object variabele genaamd mcApp gedeclareerd. Deze variabele gaat een pointer bijhouden naar de geheugenlokatie waar de instantie van onze klasse wordt geladen. De module variabele is noodzakelijk omdat module variabelen hun waarde niet verliezen bij het beeindigen van een subroutine. En zolang er tenminste 1 pointer naar de klasse instantie is blijft deze in het geheugen en dus ook reageren op de events:

Option Explicit

'Variabele die instantie van klasse clsApp vasthoudt
Dim mcApp As clsApp

Public Sub Init()
    'mcApp resetten indien deze al geladen is
    Set mcApp = Nothing
    'Een nieuwe instantie van clsApp laden
    Set mcApp = New clsApp
    'Geef het Excel object door aan clsApp zodat deze weet op welke applicatie
    'deze moet reageren
    Set mcApp.App = Application
End Sub

Ik verwacht dat de commentaren in bovenstaande code duidelijk genoeg zijn. Begrijp je het nog niet helemaal, lees dan dat artikel van Chip Pearson eens door...

Tenslotte willen we dat deze sub Init gestart wordt als we het bestand openen zodat onze invoegtoepassing direct gaat reageren op de events. Dus voegen we toe aan de ThisWorkbook module:

Private Sub Workbook_Open()
    Application.OnTime Now, "'" & ThisWorkbook.FullName & "'!Init"
End Sub

Ik gebruik de OnTime methode, omdat dat een aloude truc is die ervoor zorgt dat Excel helemaal klaar is met laden voordat Init wordt gestart. Soms start Excel het workbook_open event namelijk al voordat het zelf klaar is met al zijn opstartwerk. Met deze truc geef je Excel even de ruimte om dat af te maken.

Volgende: De invoegtoepassing maken


 


Vragen, suggesties en opmerkingen

Heeft u vragen, suggesties of opmerkingen? Gebruik dan dit formulier.

Mocht uw vraag niet direct relevant zijn voor deze pagina, maar een algemene Excel vraag betreffen, dan adviseer ik om deze hier te stellen: www.eileenslounge.com.

Uw naam (verplicht veld):

Uw e-mail adres (Niet verplicht, dit adres wordt niet getoond)

Uw verzoek of commentaar:

Als u VBA code in uw commentaar plaatst, gebruik dan [VB] tags: [VB]Uw code[/VB].