Suggesties |
voorbeeldbestand
Controle op gebruikersinvoer in Userform
|
1 Inleiding 2.1 Userform methode I 2.2 Userform methode II 2.3 Userform methode III 2.3.1 Klassemodule 2.3.2 Code in de klassemodule 2.3.3 Code in het Userform 2.3.4 met een 'Collection' 2.3.5 met een 'Array' 3 Beperkingen 4 Toelichting voorbeeldbestand 5 Verwante onderwerpen 6 Voorbeeldbestanden |
Als je gebruikersinvoer wil begeleiden/ondersteunen/controleren kun je in een Officeprogramma gebruik maken van een Userform. Als je alle denkbare 'vergissingen' van gebruikers wil ondervangen merk je dat je snel heel veel coderegels nodig hebt. Met het gebruik van een klassemodule kun je dat flink beperken. Dat geldt ook voor VBA-controle op invoer in ActiveX-objekten in een sheet. Voor een uitleg daarvan zie deze pagina. De uitleg van de werkwijze gebeurt hier aan de hand van tekstvakken in een Userform. 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 userform met 10 tekstvakken. Deze tekstvakken hebben de naam tekst1, tekst2.. ...t/m tekst10. In het userform kun je deze code zetten om te controleren of alle 10 tekstvakken in het Userform tekst bevatten. Als dat het geval is wordt de knop 'Vervolg' zichtbaar. Private Sub Tekst1_Change() For j=1 To 10
End Sub If Trim(Me("Tekst" & j).Text)="" Then Exit For
NextMe("knop_vervolg").Visible = j >10 Private Sub Tekst2_Change() For j=1 To 10
End SubIf Trim(Me("Tekst" & j).Text)="" Then Exit For
Next Me("knop_vervolg").Visible = j >10 Private Sub Tekst3_Change() For j=1 to 10
End SubIf Trim(Me("Tekst" & j).Text)="" Then Exit For
NextMe("knop_vervolg").Visible= j >10 etc. Private Sub Tekst1_Change() vervolg
End Sub Private Sub Tekst2_Change() vervolg
End SubPrivate Sub Tekst3_Change() vervolg
End SubPrivate sub vervolg() For j=1 to 10
End SubIf Trim(Me("Tekst" & j).Text)="" Then Exit For
NextMe("knop_vervolg").Visible = j >10 - zet alle tekstvakken als objecten in een verzameling: een 'Collection' of een 'Array' - koppel de controlecode (zoals hierboven de macro 'vervolg') aan de -Change-gebeurtenis van ieder element in deze verzameling Alle koppelingen zitten dan in een verzameling. Iedere wijziging van een element aktiveert dan de koppeling in de verzameling. Een koppeling met een gebeurtenis kun je alleen maar leggen met een 'WithEvents' variable. Die kun je echter alleen in een klassemodule gebruiken. Daarom zul je voor zo'n methode gebruik moeten maken van een klassemodule. Hoe werkt zo'n klassemodule in dit geval ? Omdat ieder besturingselement in een Userform 'eigen' gebeurtenissen heeft, moet je voor ieder soort besturingselement in de klassemodule een aparte gebeurtenisvariabele definiëren Je koppelt met VBA alle tekstvakken in het userform via een verzameling aan die overeenkomstige gebeurtenisvariabele in 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 besturingselementen in een userform. 2.3.2 Wat staat er in de klassemodule ? 1. Een publieke object-variabele waaraan een bepaald userformobject (in dit geval een tekstvak) kan worden toegewezen: in het voorbeeld de variabele cl_tekstvak.Omdat het om het afvangen van gebeurtenissen (Events) gaat moeten we die variabele nader specificeren met de instruktie WithEvents. Public WithEvents cl_tekstvak As MSForms.TextBox In het voorbeeld van de bijlage staan o.a. de gebeurtenissen _Change en _DblClick: Private Sub cl_tekstvak_Change() ------- End Sub Private Sub cl_tekstvak_DblClick() ----- End Sub 2.3.3 Wat staat er in het Userform ? Omdat alle controles op wat de gebruiker in het userform doet in de klassemodule staan, is de userformmodule wel erg leeg (maar dat was ook de bedoeling).2.3.4 Gebruik een 'Collection' Declareer een 'public' variabele als een nieuwe 'collection'Public ctl_verzameling as New Collection In de gebeurtenis Userfom_Initialize: Private Sub Userform_Initialize() For Each ct in Controls
End Subctl_verzameling.Add New invoercontrole, ct.Name
NextIf TypeName(ct)="TextBox" Then Set ctl_verzameling(ct.Name).cl_tekstvak = ct Die koppeling krijgt hier de naam van het userformobject als sleutel, zodat je de naam ook kunt gebruiken om het element uit de collection op te roepen. Als je de sleutel achterwege laat kun je alleen de index gebuiken om een element te benaderen. ctl_verzameling.add New invoercontrole, ct.Name set ctl_verzameling(ct.Name).cl_tekstvak = ct Dim sr() as New invoercontrole Private sr() as New invoercontrole Private Sub Userform_Initialize() ReDim sr(Controls.Count-1)
End SubFor j = 0 to Controls.Count - 1 If TypeName(Controls(j)) = "TextBox" Then Set sr(j).cl_tekstvak = Controls(j)
NextReDim sr(Controls.Count) Elementen van een array zijn alleen met de index te benaderen. Ieder besturingselement van het userform moet in een apart element van de array terechtkomen. Daarom gebruiken we hier de For j ..Next lus. Met een For Each lus zouden we een extra teller nodig hebben. Controleer om wat voor type besturingselement het gaat (met de methode 'typename') om de koppeling met de juiste WithEvents-variabele te kunnen leggen. Wijs het tekstvak via die koppeling toe aan de 'WithEvents'-variabele ('cl_tekstvak') van de klassemodule. Set sr(j).cl_tekstvak=Controls(j) Niet alle gebeurtenisssen van besturingselementen kunnen via een WithEvents-variable worden 'afgevangen' Dat geldt voor de volgende gebeurtenissen: - Activate
- Deactivate - QueryClose - Resize - Terminate - AfterUpdate - BeforeUpdate - Enter - Exit 4 Toelichting op het voorbeeldbestand Het voorbeeld bestand bevat:- de klassemodule 'invoercontrole' - het userform 'scherm collection', dat gebruik maakt van de 'collection' methode. - het userform 'scherm array' dat gebruik maakt van de 'array' methode. Het bestand illustreert tegelijkertijd dat de code in een klassemodule voor diverse userforms tegelijkertijd dienst kan doen. De klassemodule 'invoercontrole' De klassemodule bevat WithEvents-variabelen voor: - Label
De klassemodule bevat per besturingselement alle gebeurtenissen die via een klassemodule kunnen worden afgevangen.- TextBox - ComboBox - ListBox - CheckBox - OptionButton - CommandButton - SpinButton - MultiPage - Frame - UserForm Voor ieder soort besturingelement staat een eigen code in de gebeurteniscode _Click. Aan de Textbox_change gebeurtenis is de controlemacro 'A_vervolg' gekoppeld die nagaat of alle tekstvakken zijn gevuld; als dat het geval is wordt de 'knop_vervolg' zichtbaar. Bij alle andere gebeurtenissen staat een code waarmee een MsgBox kan worden getoond bij activering; deze code is met een apostrof uitgeschakeld. Door deze aprostrof te verwijderen kan de werking van iedere afzonderlijke gebeurteniscode worden getest. Ter illustratie zijn verschillende soorten code bij de _click gebeurtenis van de labels in het userform opgenomen: - het wijzigen van de inhoud van het besturingselement zelf - het wijzigen van de vormgeving van het besturingselement zelf - het wijzigen van een ander besturingselement - het starten van een macro - het aanroepen van een funktie - het wijzigen van het werkblad Het userform 'scherm_collection' Het werkblad bevat een knop dat dit userform toont. Het userform bevat van alle besturingselementen 10 exemplaren, behalve van de ListBox, de Multipage en het Frame. Het userform 'scherm_collection' is identiek aan het userform 'scherm_array'; het verschil zit in de VBA-code: het gebruik van de 'collection' methode (zie de userform_Initialize gebeurtenis). Dit userform gedraagt het zich identiek aan het userform 'scherm_array' omdat het gebruik maakt van dezelfde klassemodule. In de code voor de afhandeling van de textbox_change gebeurtenis staat een voorbeeld hoe een in het userform public gedeclareerde collection in de klassemodule kan worden uitgelezen. Het userform 'scherm_array' Het werkblad bevat een knop dat dit userform toont. Het userform bevat van alle besturingselementen 10 exemplaren, behalve van de ListBox, de Multipage en het Frame. Het userform 'scherm_array' is identiek aan het userform 'scherm_collection'; het verschil zit in de VBA-code: het gebruik van de 'array' methode (zie de userform_Initialize gebeurtenis). Omdat dit userform gebruik maakt van dezelfde klassemodule 'invoercontrole' gedraagt het zich identiek aan het userform 'scherm_collection'. VBA controle van ActiveX-objekten in een werkblad 6 Voorbeeldbestanden voor elk type userformcontrol LabelTextbox Combobox Listbox Checkbox Optionbutton Commandbutton Spinbutton Frame Multipage ToggleButton Scrollbar |