voorbeeldbestand
ActiveX-controls in een werkblad:
controle op gebruikersinvoer

1 Inleiding

2.1 Methode I
2.2 Methode II
2.3 Methode III
2.3.1 Klassemodule
2.3.2 Code in de klassemodule
2.3.3 Code in het werkblad

3 Technische opmerkingen

4 Voorbeeldbestanden

5 Verwante onderwerpen

1 Inleiding

Als je gebruikersinvoer wil begeleiden/ondersteunen/controleren kun je in een Excel werkblad gebruik maken van ActiveX controls (werkset besturingselementen).
Als je alle denkbare 'vergissingen' van gebruikers wil ondervangen merk je dat je snel veel coderegels nodig hebt.
Met een klassemodule kun je dat flink beperken.
Dat geldt ook voor VBA-controle op invoer in Userforms.
Voor een uitleg daarvan zie deze pagina.

De uitleg van de werkwijze gebeurt hier aan de hand van tekstvakken in een werkblad.
Gebruikersinvoer leidt bijvoorbeeld tot wijziging van de inhoud van een tekstvak (TextBox).
Om de invoer te controleren kun je gebruik maken van de gebeurtenis 'Change' van een tekstvak.
Iedere wijziging in het tekstvak door de gebruiker aktiveert deze controle.
We gaan hier uit, zoals in het voorbeeldbestand, van een werkblad met 10 tekstvakken.
Deze tekstvakken hebben de naam tekst1, tekst2.. ...t/m tekst10

2.1 Methode I

In de VBA-module van het werkblad kun je deze code zetten om te controleren of alle 10 tekstvakken in het werkblad tekst bevatten.
Als dat het geval is wordt de knop 'Vervolg' zichtbaar.
Private Sub tekst1_Change()
For j=1 to 10
If Trim(OLEObjects.("Tekst" & j).Object.Text)="" Then Exit For
Next
OLEObjects("knop_vervolg").Object.Visible=j=11
End Sub

Private Sub tekst2_Change()
For j=1 to 10
If Trim(OLEObjects("Tekst" & j).Object.Text)="" Then Exit For
Next
OLEObjects("knop_vervolg").Object.Visible=j=11
End Sub

Private Sub tekst3_Change()
For j=1 to 10
If Trim(OLEObjects("Tekst" & j).Object.Text)="" Then Exit For
Next
OLEObjects("knop_vervolg").Object.visible=j=11
End Sub

etc.

2.2 Methode II

Het wordt al een beetje efficiënter met:
Private Sub tekst1_Change()
vervolg
End Sub

Private Sub tekst2_Change()
vervolg
End Sub

Private Sub tekst3_Change()
vervolg
End Sub

Private sub vervolg()
For j=1 to 10
If Trim(OLEObjects("Tekst" & j).Object.Text)="" then Exit For
Next
OLEObjects("knop_vervolg").Object.Visible=j=11
End Sub
Maar nog steeds moet je bij ieder tekstvak in de gebeurtenis _Change aangeven wat er moet gebeuren.

2.3 Methode III

Dan zou je nog het volgende kunnen bedenken:
- zet alle tekstvakken in een 'Collection'
- koppel de controlecode (zoals hierboven de macro 'vervolg') aan de -Change-gebeurtenis van deze 'collection'

Zo'n koppeling met een gebeurtenis kun je alleen maar leggen met een 'WithEvents' instruktie voor een variable.
Die kun je alleen gebruiken in een klassemodule.
Daarom zul je voor zo'n methode gebruik moeten maken van een klassemodule.

2.3.1 Klassemodule

Hoe werkt zo'n klassemodule in dit geval ?
Je koppelt met VBA alle tekstvakken in het werkblad via een 'Collection' aan de gebeurtenisvariabele van de klassemodule.
In de klassemodule zet je dan de (gebeurtenis)code die van toepassing is op de gebeurtenisvariabele van de klassemodule.

NB. een klassemodule kan voor nog veel meer zaken gebruikt worden, maar hier beperken we ons tot het 'afvangen' van gebeurtenissen van tekstvakken in een werkblad.

2.3.2 Wat staat er in de klassemodule ?

1. Een publieke object-variabele waarin de eigenschappen van een bepaald ActiveXobject (in dit geval een tekstvak) worden opgeslagen.

Omdat het om het afvangen van gebeurtenissen gaat moeten we die variabele aanduiden met de instruktie WithEvents.
Public WithEvents cl_tekstvak As MSForms.TextBox
2. Eén procedure per 'gebeurtenis' van de objectvariable cl_tekstvak.

Dat kunnen natuurlijk alleen de gebeurtenissen zijn die bij TextBox horen.
In het voorbeeld van de bijlage staan de gebeurtenissen _Change en _DblClick:
Private Sub cl_tekstvak_Change()
-------
End Sub

Private Sub cl_tekstvak_DblClick()
-----
End Sub
NB. Deze enkele _Change procedure in de klassemodule vervangt zo alle _change procedures die we eerst in de codemodule van het werkblad hadden staan.

2.3.3 Wat staat er in de codemodule van het werkblad ?

Omdat alle controles van wat de gebruiker in de ActiveX-controls doet in de klassemodule staan, is de werkbladmodule wel erg leeg (maar dat was ook de bedoeling).

Declareer eerst een nieuwe 'collection'
Public verzameling as New Collection
Zet in de gebeurtenis Workbook_Open:
Private Sub Workbook_Open()
For Each ctl in OLEObjects
If TypeName(ctl.Object)="TextBox" then
verzameling.Add New invoercontrole
set verzameling(verzameling.Count).cl_tekstvak=ctl.Object
End If
Next
End Sub
Voor iedere te controleren ActiveX-control voeg je een koppeling met de klassemodule (technisch: een instantie van de klassemodule) toe aan de collection 'verzameling'.
verzameling.add New invoercontrole
Via die koppeling in de collection (het laatste element van de verzameling) wijs je een tekstvak toe aan de 'WithEvents'-variabele ('cl_tekstvak') van de klassemodule.
De instructie 'Set' is nodig omdat het om een object gaat.
set verzameling(verzameling.Count).cl_tekstvak=OLEObject("tekst1")
Zo zorg je ervoor dat als de gebruiker een element van die verzameling wijzigt de code van de klassemodule wordt 'afgevuurd' via die koppeling.

3 Technische opmerkingen

- Omdat de variabele 'verzameling' Public is kun je deze verzameling ook uitlezen in de klassemodule.
- Omdat de variabele cl_tekstvak in de klassemodule Public is, kun je alle tekstvakken vanuit het werkboek direkt toewijzen aan deze variabele.
- Alle voorbeeldbestanden zijn gemaakt met Excel 2000.

4 Voorbeeldbestanden

Het voorbeeldbestand met de hier besproken code

voorbeeldbestand

Per ActiveX-control een apart voorbeeldbestand:

TextBox
ComboBox
CheckBox
OptionButton
ToggleButton
SpinButton
ScrollBar

5 Verwante onderwerpen

VBA controle van besturingselementen in een userform