Bouwen van een invoegtoepassing voor Excel
Inhoud
Inleiding
Excel is een krachtige applicatie met duizenden opties en functies om
rekenmodellen, rapporten en analyses te bouwen. Het komt toch nog regelmatig
voor dat je in je dagelijkse werk wat functionaliteit zou kunnen gebruiken
die Excel niet biedt.
Met behulp van VBA is het mogelijk om functionaliteit aan Excel toe te
voegen. In dit artikel laat ik zien hoe je een kleine invoegtoepassing maakt
in Excel VBA. Het artikel bespreekt alle benodigde stappen die ik nam om
de invoegtoepassing te bouwen. De principes die ik tijdens het bouwen heb
gebruikt helpen jou hopelijk bij het maken van je eigen tool!
Download
Ik heb een voorbeeldbestand beschikbaar
gesteld dat je kunt downloaden.
Specificatie
Een heel belangrijke stap bij het maken van software is het bepalen wat
de software moet kunnen; de specificatie. Laten we eens proberen een specificatie
op te stellen.
Doel
De primaire doelstellingen van de invoegtoepassing die ik voor ogen heb
zijn:
- Een eenvoudige methode maken zodat de gebruiker aan zijn Excel bestand
een inhoudsopgave toe kan voegen (of bijwerken);
- Een hulpmiddel op het lint om het navigeren tussen werkbladen makkelijker
te maken.
Zoals je je kunt voorstellen is meer detail nodig voordat we ons in het
programmeerwerk onder kunnen dompelen. We hebben nog meer specificaties
nodig.
Meer gedetailleerde specificatie
Werking van de inhoudsopgave
Ik preciseer hier nader wat de invoegtoepassing zal doen
- De Inhoudsopgave zal geplaatst worden op een tabblad genaamd TOC
(Table Of Content), beginnende in cel C2;
- De tabel zal worden “Opgemaakt als tabel”;
- De tabel zal in kolom C een lijst met alle werkbladnamen bevatten,
met in kolom D een directe snelkoppeling naar cel A1 van dat werkblad.
Kolom E geeft de gebruiker ruimte om naast het werkblad een opmerking
in te voegen;
- Deze opmerkingen zullen behouden blijven bij het vernieuwen van
de Inhoudsopgave, zodanig dat –op basis van de tabnaam– de opmerking
bij het juiste tabblad blijft staan;
- De inhoudsopgave krijgt deze opmaak:

Het Lint
De invoegtoepassing zal een aangepaste tab op het lint maken met daarin
één groep met daarop:
- Een vervolgkeuzelijst die alle werkbladen zal bevatten van de actieve
werkmap;
- Een knop om de inhoudsopgave te maken of te vernieuwen:

Andere functies
- Zodra de gebruiker een andere werkmap selecteert wordt de lijst
met werkbladen in de vervolgkeuzelijst automatisch bijgewerkt;
- Als een ander werkblad wordt geselecteerd wordt deze op de vervolgkeuzelijst
weergegeven.
Is dat alles?
In “echte” softwareprojecten zijn er natuurlijk nog allerlei andere vragen
die ook nog beantwoord moeten worden. In willekeurige volgorde (niet pretenderend
dat deze lijst volledig is):
- Zorg voor een sponsor, je moet tenslotte je rekeningen betalen;
- Doe marktonderzoek (als je tenminste van plan bent om die nieuwe
invoegtoepassing te verkopen. Het zou toch leuk zijn als er ook een
markt voor bestaat;)
- Google. Twitter. Vraag het aan de buurman. Zorg er in ieder geval
voor dat je niet iets gaat bouwen dat al bestaat.
De kans is aanzienlijk dat iemand jou voorging met dit idee en misschien
kan je zijn invoegtoepassing gewoon gebruiken;
- Planning: Wanneer moet het klaar zijn?
Andere dingen om aan te denken
En dan hier nog een lijstje met dingen die je nodig zou kunnen hebben
die eigenlijk weinig te maken hebben met de basisfunctionaliteit van je
invoegtoepassing:
- Ontwerpen van de gebruikersinterface;
- Internationalisatie (vertalen in andere talen)
- Bugs waar je omheen zal moeten werken;
- Installatie;
- Activatie (Mocht je van plan zijn te licenties te verkopen, hoe
zorg je er dan voor dat er ook wordt betaald);
- Demo versie;
- Hoe zorg ik ervoor dat updates bij mijn klanten komen.
Zo, dan is het nu tijd om code te gaan schrijven.
Basisfunctionaliteit
Ervaring leert, dat invoegtoepassingen voor Excel iets gemeen hebben.
De tijd die je tijdens het bouwen besteedt aan de kernfunctionaliteit is
vaak slechts een klein deel van de tijd die nodig is om het project tot
een goed einde te brengen. Dit is iets dat overigens voor heel veel softwareprojecten
geldt.
De werkmap maken
Een invoegtoepassing voor Excel is niets meer of minder dan een gewone
werkmap, die is opgeslagen als een invoegtoepassing. Je kan natuurlijk de
invoegtoepassing zelf bewerken en opslaan, zoals ieder ander Excel bestand,
maar ik persoonlijk bewerk liever een "normale" werkmap en sla die op als
invoegtoepassing als ik klaar ben.
Dus, open een nieuw, leeg Excel bestand (Ik heb hier de VBA editor naast
het venster van Excel gezet, met slechts de projectverkenner open):

Net de geur van een nieuwe auto vind je niet?
Kernfunctionaliteit
Een module invoegen
De basis van de invoegtoepassing wordt een werkblad genaamd ToC. Omdat
ik ervoor gekozen heb om een commentaar bij ieder werkblad mogelijk te maken,
moeten deze commentaren tijdens het vernieuwen van de lijst tijdelijk worden
opgeslagen en na het vernieuwen weer naast hun bijbehorende werkbladen worden
teruggeplaatst.
Laten we dus eerst een module invoegen:

En verander de naam van die module in het eigenschappen venster:

Het VBA project moet er nu zo uitzien:

Dubbel-klik op modTOC om het bijbehorende codevenster te openen.
De basiscode
Zonder verder uitgebreid uit de doeken te doen hoe de code werkt (het
commentaar geeft al een flinke zet in de goede richting); is hier de code:
'-------------------------------------------------------------------------
' Module : modMain
' Company : JKP Application Development
Services (c)
' Author : Jan Karel Pieterse
(jkp-ads.com)
' Created : 30-4-2015
' Purpose : De hoofdroutinesvan de tool
'-------------------------------------------------------------------------
Option Explicit
Public Sub UpdateTOC()
'-------------------------------------------------------------------------
' Procedure : UpdateTOC
' Company : JKP Application Development
Services (c)
' Author : Jan Karel Pieterse
(jkp-ads.com)
' Created : 30-4-2015
' Purpose : Maakt werkblad met inhoudsopgave
(of werkt deze bij)
'-------------------------------------------------------------------------
Dim oSh As
Object
Dim oToc As
Worksheet
Dim vRemarks
As Variant
Dim lCt As
Long
Dim lRow As
Long
Dim lCalc As
Long
Dim bUpdate
As Boolean
bUpdate = Application.ScreenUpdating
Application.ScreenUpdating = False
lCalc = Application.Calculation
Application.Calculation = xlCalculationManual
'Controleer of er al een werkblad ToC
is, Zo niet, voeg er een toe:
If Not
IsIn(Worksheets, "ToC") Then
With Worksheets.Add(Worksheets(1))
.Name =
"ToC"
End
With
Set oToc
= Worksheets("ToC")
ActiveWindow.DisplayGridlines =
False
ActiveWindow.DisplayHeadings =
False
Else
Set oToc
= Worksheets("ToC")
'We hebben een
bestaand ToC blad, Sla de tabel met de inhoudsopgave op
'zodat we de commentaren
na vernieuwen terug kunnen zetten
vRemarks = oToc.ListObjects(1).DataBodyRange
End If
'Controleer of er een tabel staat op het
ToC werkblad, zo niet, toevoegen
If oToc.ListObjects.Count = 0
Then
oToc.Range("C2").Value = "Werkblad"
oToc.Range("D2").Value = "Snelkoppeling"
oToc.Range("E2").Value = "Opmerkingen"
oToc.ListObjects.Add xlSrcRange,
oToc.Range("C2:E2"), , xlYes
End If
On Error
Resume Next
'Tabel leegmaken
'Fouten negeren voor het geval de tabel al leeg is
oToc.ListObjects(1).DataBodyRange.Rows.Delete
For Each
oSh In Sheets
If oSh.Visible
= xlSheetVisible Then
lRow = lRow
+ 1
oToc.Range("C2").Offset(lRow).Value
= oSh.Name
oToc.Range("C2").Offset(lRow,
1).FormulaR1C1 = _
"=HYPERLINK(""#'""&RC[-1]&""'!A1"",RC[-1])"
oToc.Range("C2").Offset(lRow,
2).Value = ""
'Bestaand
commentaar voor dit werkblad invoegen
For
lCt = LBound(vRemarks, 1) To
UBound(vRemarks, 1)
If
vRemarks(lCt, 1) = oSh.Name Then
oToc.Range("C2").Offset(lRow,
2).Value = vRemarks(lCt, 3)
Exit
For
End
If
Next
End
If
Next
oToc.ListObjects(1).Range.EntireColumn.AutoFit
Application.Calculation = lCalc
Application.ScreenUpdating = bUpdate
End Sub
Wellicht heb je al opgemerkt dat deze code een compileerfout geeft als
je ze probeert uit te voeren:

Dit komt omdat er een functieaanroep in staat naar de functie "IsIn"
die nog moet worden ingevoerd. IsIn is een functie die ik ooit van mijn
collega Excel MVP Bill
Manville heb gekregen.
Functies module
Omdat we misschien nog meer algemene functies nodig hebben, voeg ik een
module toe die ik modFunctions noem. Daarin staat nu slechts deze functie:
Option Explicit
Function IsIn(vCollection
As Variant,
ByVal sName As
String) As
Boolean
'-------------------------------------------------------------------------
' Procedure : IsIn Created by Jan Karel Pieterse
' Company : JKP Application Development
Services (c) 2005
' Author : Jan Karel Pieterse
' Created : 28-12-2005
' Purpose : Bepaalt of een object deel
uitmaakt van een collectie
'-------------------------------------------------------------------------
Dim oObj As
Object
On Error
Resume Next
Set oObj = vCollection(sName)
If oObj Is
Nothing Then
IsIn = False
Else
IsIn = True
End If
If IsIn = False
Then
sName = Application.Substitute(sName,
"'", "")
Set oObj
= vCollection(sName)
If oObj
Is Nothing
Then
IsIn =
False
Else
IsIn =
True
End
If
End If
End Function
Nu zou de routine UpdateTOC moeten werken!
De gebruikersinterface
Invoegtoepassingen zijn verborgen bestanden en hebben dus geen werkbladen
waar je bijvoorbeeld knoppen op kunt zetten. Er is dus iets nodig zodat
de gebruiker ermee kan werken zoals misschien invoerschermen. Of ze moeten
werkbladen toevoegen waar de gebruiker data in in kan voeren. Deze invoegtoepassing
gebruikt enkele elementen op het lint.
Lint aanpassingen
Onze invoegtoepassing heeft dus slechts een beperkte gebruikersinterface,
alles wat er nodig is zal op het lint komen te staan. Lintaanpassingen doen
is geen eenvoudige klus. Gelukkig zijn er enkele zeer goede bronnen met
informatie te vonden:
Met hulp van de
Custom UI Editor, open ik het bestand waarin we aan het werk zijn (Ik
heb dit bestand daarvoor opgeslagen en Excel gesloten om conflicten te voorkomen.
Na openen in de editor voeg ik een "Office 2007 CustomUI part" toe aan
het bestand:

Door deze variant te nemen zorgen ik ervoor dat de lintaanpassingen in
alle Excel versies werken. Vervolgens heb ik onderstaande XML code ingevoegd:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui"
onLoad="rxJKPSheetToolscustomUI_onLoad">
<ribbon>
<tabs>
<tab id="rxJKPSheetTools"
label="SheetTools">
<group
id="rxJKPSheetToolsGeneral" label="Sheet Tools">
<dropDown
id="rxJKPSheetToolsbtnSheets"
getItemCount="rxJKPSheetToolsbtnSheets_Count"
getItemLabel="rxJKPSheetToolsbtnSheets_getItemLabel"
onAction="rxJKPSheetToolsbtnSheets_Click"
sizeString="MMMMMMMMMMMMMMMMMMMMMMMM"
label="Sheets"
getSelectedItemIndex="rxJKPSheetToolsbtnSheets_getSelectedItemIndex"
/>
<button
id="rxJKPSheetToolsbtnInsertToc"
label="Table Of Contents"
size="large"
onAction="rxJKPSheetToolsbtnInsertToc"
imageMso="CustomTableOfContentsGallery" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Na invoegen van die code ziet de Custom UI Editor er zo uit:

Van groot belang zijn de zogeheten callbacks die in de xml staan. Die
geven aan dat er voor die acties VBA code in de werkmap in kwestie moeten
staan. Door op de meest rechtse knop op de toolbar te klikken laat je de
Custom UI editor de lege Sub ... End Sub kapstokken voor je genereren.
De xml bevat deze callbacks:
- onLoad (Aangeroepen wanneer het bestand wordt geopend)
- getItemCount (geeft het aantal elementen in een dropdown)
- getItemLabel (Haalt het n-de element van een dropdown op)
- onAction (Aangeroepen bij het klikken op een knop of het kiezen
van een element uit een dropdown)
- getSelectedItemIndex (geeft door welk element in de dropdown moet
worden geselecteerd)
Misschien is het je opgevallen wat voor complexe
routinenamen ik heb gemaakt (zoals "rxJKPSheetToolsbtnSheets_Click"). Vooral
het "rxJKPSheetTools" deel. Callback namen moeten namelijk strikt
uniek zijn binnen de contaxt van een lopende instantie van Excel. En dan
bedoel ik ook echt uniek. Geen enkel ander openstaand Excel bestand kan
een callback hebben met een routinenaam die samenvalt met een andere. Is
dat wel het geval, dan loop je de kans dat de routine in de andere werkmap
wordt aangeroepen en kunnen dus zeer onverwachte dingen gebeuren. Daarom
zet ik altijd een stukje tekst voor iedere routinenaam waardoor ik er zeker
van kan zijn dat deze uniek zijn.
Na kopieren van de kapstokjes uit de Custom UI editor sla ik de werkmap
op en open deze in Excel. Vervolgens plak ik ze in een module in het VBA
project:
Option Explicit
Sub rxJKPSheetToolscustomUI_onLoad(ribbon
As IRibbonUI)
End Sub
Sub rxJKPSheetToolsbtnInsertTOC(control
As IRibbonControl)
End Sub
'Callback for rxJKPSheetToolsbtnSheets getItemCount
Sub rxJKPSheetToolsbtnSheets_Count(control
As IRibbonControl, ByRef
returnedVal)
End Sub
Public Sub rxJKPSheetToolsbtnSheets_getItemLabel(control
As IRibbonControl, Index
As Integer,
ByRef returnedVal)
End Sub
'Callback for rxJKPSheetToolsbtnSheets getSelectedItemIndex
Sub rxJKPSheetToolsbtnSheets_getSelectedItemIndex(control
As IRibbonControl, ByRef
returnedVal)
End Sub
Sub rxJKPSheetToolsbtnSheets_Click(control
As IRibbonControl, id As
String, Index As
Integer)
End Sub
Ribbon callbacks
Ribbon load
Zodra het lint wordt vernieuwd wordt als eerste de callback aangeroepen
die een verwijzing geeft naar het lint object. We gebruiken een object variabele
op module niveau en wijzen het Ribbon object eraan toe:
Option Explicit
Dim moRibbon As
IRibbonUI
Sub rxJKPSheetToolscustomUI_onLoad(ribbon
As IRibbonUI)
Set moRibbon = ribbon
End Sub
Zo. VBA onthoudt nu het ribbon object zodat we het lint vanuit onze code
kunnen laten vernieuwen. Zodra het Excel bestand wordt geopened, wordt onLoad
aangeroepen.
De dropdown voorzien van de tabnamen
Als het lint moet worden vernieuwd wordt als eerste de routine “rxJKPSheetToolsbtnSheets
getItemCount” aangeroepen. In die routine moet worden doorgegeven aan het
lint hoeveel werkbladen er in de lijst moeten worden geladen:
'Callback for rxJKPSheetToolsbtnSheets getItemCount
Sub rxJKPSheetToolsbtnSheets_Count(control
As IRibbonControl, ByRef
returnedVal)
Dim lCt As
Long
Dim oSh As
Object
For Each
oSh In Sheets
If oSh.Visible
= xlSheetVisible Then lCt = lCt + 1
Next
returnedVal = lCt
End Sub
De getoonde routine telt simpelweg het aantal zichtbare werkbladen in
het huidige Excel bestand en geeft dat getal door aan de variabele returnedVal.
Vervolgens zal de routine “rxJKPSheetToolsbtnSheets getItemLabel” vanzelf
dat aantal keer worden aangeroepen om de naam van ieder werkblad op te vragen,
dus als er drie werkbladen zijn, wordt die routine drie keer aangeroepen
om de naam van dat werkblad op te vragen:
Public Sub rxJKPSheetToolsbtnSheets_getItemLabel(control
As IRibbonControl, Index
As Integer,
ByRef returnedVal)
Dim lCt As
Long
Dim oSh As
Object
For Each
oSh In Sheets
If oSh.Visible
= xlSheetVisible Then lCt = lCt + 1
If lCt
= Index + 1 Then
returnedVal
= oSh.Name
Exit
For
End
If
Next
End Sub
Dus iedere keer dat deze routine wordt aangeroepen moet deze één tabnaam
teruggeven.
Ik zou het zeer op prijs hebben gesteld als de makers
van Excel slim genoeg waren geweest om vooraf te bedenken of tellers van
lijstjes (collections) met het getal 0 of het getal 1 moeten beginnen. Maar
dat hebben ze helaas niet gedaan, met als gevolg dat tellers dan weer bij
0, dan weer bij 1 beginnen in VBA.
Nadat de dropdown de tabnamen heeft opgehaald willen we de naam van het
huidige tabblad tonen in die dropdown. Dat wordt gedaan door onderstaande
callback:
'Callback for rxJKPSheetToolsbtnSheets getSelectedItemIndex
Sub rxJKPSheetToolsbtnSheets_getSelectedItemIndex(control
As IRibbonControl, ByRef
returnedVal)
Dim lCt As
Long
Dim oSh As
Object
For Each oSh
In Sheets
If oSh.Visible
= xlSheetVisible Then lCt = lCt + 1
If oSh.Name
= ActiveSheet.Name Then
returnedVal
= lCt - 1
Exit
Sub
End If
Next
End Sub
En dan willen we natuurlijk ook nog naar eeh tab gaan als die uit de
keuzelijst wordt gekozen:
Sub rxJKPSheetToolsbtnSheets_Click(control
As IRibbonControl, id As
String, Index As
Integer)
Dim lCt As
Long
Dim oSh As
Object
For Each
oSh In Sheets
If oSh.Visible
= xlSheetVisible Then lCt = lCt + 1
If lCt
= Index + 1 Then
oSh.Activate
Exit
Sub
End
If
Next
End Sub
Weet je nog dat ik zei dat de index van de dropdown bij 0 begint? Nou,
de index van Excel's tabbladen begint bij 1.
De knop de inhoudsopgave laten vernieuwen
O wacht, wezijn er nog niet; de knop om de inhoudsopgave te vernieuwen
doet het nog niet. We hadden er al een lege Sub ... End Sub voor, dus laten
we die gebruiken::
Sub rxJKPSheetToolsbtnInsertTOC(control
As IRibbonControl)
UpdateTOC
End Sub
Zo, dat was niet zo moelijk, wel?
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:
- We een ander tabblad selecteren;
- We een tabblad verbergen of zichtbaar maken;
- We een andere werkmap selecteren.
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:

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):

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):

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.
De invoegtoepassing maken
Zo, het lastige deel zit erop, het programmeerwerk is af. Het enige dat
ons nog te doen staat is het maken van de invoegtoepassing zelf. En natuurlijk
testen!
Een invoegtoepassing maken
Het maken van een invoegtoepassing is simpel, gewoon op bestand, Opslaan
Als klikken:

In dat Opslaan Als venster, klikken we op het "Opslaan Als" dropdowntje
en selecteren we" Excel Invoegtoepassing (*.xlam)":

Zodra je voor "Excel Invoegtoepassing kiest, is Excel vriendelijk
genoeg om zelf de standaard map voor invoegtoepassingen voor je te activeren.
Maar omdat dat eigenlijk nooit de plaats is waar ik mijn invoegtoepassingen
bewaar, ergerde ik mij enorm hieraan. Totdat iemand mij erop wees, dat je
de "Terug" knop op dat opslaan als venster kunt gebruiken om terug te gaan
naar de oorspronkelijke lokatie:

Zo, dat is alles, klik op Opslaan en je invoegtoepassing is klaar voor
gebruik!
Gerelateerde artikelen
Hieronder een aantal artikelen die met invoegtoepassingen te maken hebben: