8.10. Besturingselementen - Formulieren

Macro's uitvoeren kan je op diverse manieren:

In wat volgt zie je voorbeelden van de 2 laatste werkwijzen. De besproken voorbeelden staan in de werkmap Kalender.

Er wordt een aantal keer een maandkalender gemaakt. De eerste 4 bladen van de map weren Kalender01, Kalender02, Kalender03 en Kalender04 genoemd.

8.10.1. Opdrachtknoppen in een werkblad

Je wil vanaf de cel A1 op het blad Kalender01 een maandkalender in 2 kolommen maken. Na het klikken op de knop 'Kalender' wil je het nummer van de maand in een dialoogvenster invoeren. Een klik op de knop 'Wissen' maakt je werkblad opnieuw leeg.

Werkwijze:

zet de werkbalk 'Visual Basic' op je scherm en klik op . Je ziet dan de 'Werkset besturingselementen'.

klik op (Opdrachtknop) en sleep in het werkblad een rechthoek met de gewenste grootte

klik rechts op de geselecteerde knop en kies uit het snelmenu 'Eigenschappen'

noem de knop cmdKalender (Name) en typ 'Kalender' bij de eigenschap 'Caption'. Deze tekst komt op de knop zelf.

sluit het eigenschappenvenster

klik nogmaals rechts op de geselecteerde kop en kies in het snelmenu 'Programmacode weergeven'. Je komt in het codevenster van blad1. Dit is het blad waarop de knop staat. Je kan hier een procedure schrijven die zal worden uitgevoerd bij het klikken op de knop. De eerste en de laatste regel zijn reeds ingevuld:

Private cmdKalender_Click()

End Sub

vul de rest in zoals hieronder is afgebeeld.

ga naar het werkblad

zet in de werkbalk 'Visual Basic' of in de 'Werkset besturingselementen' de ontwerpmodus uit door op te klikken.

ontwerpmodus aan: als je besturingselementen wil selecteren

ontwerpmodus uit: wanneer je besturingselementen wil gebruiken.

klik op de knop 'Kalender' en je kan het nummer van de gewenste maand (1-12) invoeren.

opmerkingen:

In het venster 'Projectverkenner' zie je alle geopende projecten. Het project 'Kalender' bevat een werkmap met 4 werkbladen, een formulier, een module. Dubbelklikken op 'Blad1' brengt je bij de programmacode die bij het blad of een object eruit hoort. Dit kan bijvoorbeeld een opdrachtknop zijn..

 

Oefeningen:

Maak zelf de knop Wissen en schrijf er de code bij.

8.10.2. Parameters in macro's

Op het blad Kalender02 maak je beide hiernaast getoonde knoppen. Noem ze 'cmdHuidige' en 'cmdKeuze'. Een klik op de knop 'Huidige' genereert een kalender van de huidige maand. Klikken op de knop 'Keuze' geeft je zoals op blad Kalender01 de keuze om een maand te kiezen(1-12).

Voor beide knoppen moet in feite dezelfde macro gemaakt worden; enkel de maand waarvoor een kalender getoond zal worden verschilt. Je kan in zo'n geval volstaan met één macro waar je tweemaal naar verwijst. Bij het verwijzen naar of oproepen van de macro moet je er dan wel voor zorgen dat de macro 'weet' voor welke maand een kalender gemaakt moet worden. Het gegeven dat je moet meesturen is een parameter. Dit is dus een gegeven dat de aangeroepen macro nodig heeft om correct te kunnen functioneren.

 

Private Sub cmdHuidige_Click()
Dim intMaand As Integer
intMaand = Month(Date)
KalenderMetParameter (intMaand)
End Sub
De code voor de knop 'cmdHuidige' staat hiernaast. Het maandnummer wordt bepaald (intMaand) en dan wordt vanuit de macro een andere macro opgeroepen nl. 'KalenderMetParameter'. Tussen de haakjes staat daarbij het gegeven dat vanuit 'cmdHuidige_Click' wordt meegestuurd.
Private Sub cmdKeuze_Click()
Dim strMaand As String, dtmDatum, dtmBegin As Date
strMaand = InputBox("Maand")
KalenderMetParameter (CInt(strMaand))
End Sub
In de code voor 'cmdKeuze' wordt het maandnummer ingevoerd als string en na conversie naar integer meegestuurd naar 'KalenderMetParameter'. Het is van belang te weten van welk type de parameter is. De aangeroepen macro 'verwacht' zich in dit geval aan een integer.
Private Sub KalenderMetParameter(p_m As Integer)
dtmBegin = DateSerial(Year(Date), p_m, 1)
dtmDatum = dtmBegin
Range("a1").Activate
Do
   ActiveCell.Value = Format(dtmDatum, "dddd")
   ActiveCell.Offset(0, 1).Activate
   ActiveCell.Value = dtmDatum
   ActiveCell.Offset(1, -1).Activate
   dtmDatum = dtmDatum + 1
Loop Until Month(dtmDatum) > Month(dtmBegin)
Range("a1").Activate
End Sub
Vanwaar de parameterwaarde komt en hoe ze bij de 'afzender' heet heeft voor de opgeroepen macro geen belang. Essentieel is het aantal, de volgorde en het type van de parameters. In ons voorbeeld is er slechts één. Deze is van het type integer.

Om de parameterwaarde(n) te kunnen 'in ontvangst nemen' moet de opgeroepen macro één/meerdere geheugenlokatie(s) voorzien. De naam en het type ervan vind je in de hoofding tussen de haakjes.

Je laat een parameternaam best met 'p_' beginnen om deze te onderscheiden van andere, 'gewone' variabelen die je in de macro gebruikt.

 

Een parametervariabele wordt NIET met de DIM-instructie aangemaakt!

De macro 'KalenderMetParameter' staat in het codevenster van het blad 'Kalender02'. Wil je een macro die vanuit andere bladen en/of formulieren bereikbaar is, dan moet je deze in een moduleblad zetten.

8.10.3. Knoppen aanmaken dmv. een macro

Bij het activeren van het blad 'Kalender03' wil je 3 knoppen met daarop de begindatum van de komende 3 maanden vanaf de huidige. Je kiest dan de maand waarvan je een kalender wil maken. Je zou de knoppen manueel kunnen maken en een macro telkens de gepaste tekst er laten op zetten. Hieronder wordt getoond dat je de knoppen zelf telkens opnieuw kan laten maken, gebruiken en bij het verlaten van het blad verwijderen.

 

Private Sub Worksheet_Activate()
Dim intTeller, intMaand As Integer
Dim intLeft, intTop, intWidth, intHeight As Integer
Dim cmdNieuw As Button
Dim dtmDatum As Date
intMaand = Month(Now())
dtmDatum = DateSerial(Year(Now()), intMaand, 1)
'Plaatsbepaling knoppen
intLeft = Range("d1").Left
intTop = 0
intWidth = Range("d1:e1").Width
intHeight = Range("d1:d2").Height
'Aanmaken knoppen, toevoegen tekst, oproepen macro
For intTeller = 1 To 3
   Set cmdNieuw = ActiveSheet.Buttons.Add(intTeller * intLeft,    intTop, intWidth, intHeight)
   cmdNieuw.Caption = Format(dtmDatum, "yy-mm-dd")
   cmdNieuw.OnAction = "Formulieren.xls!Module1.Kalender"
   intMaand = intMaand + 1
   dtmDatum = DateSerial(Year(Now()), intMaand, 1)
Next intTeller
End Sub
Bijgaande macro wordt uitgevoerd wanneer het werkblad waaraan hij gekoppeld is, geactiveerd wordt.

De instructie ActiveSheet.Buttons.Add() voegt aan de verzameling knoppen van het actieve werkblad een knop toe. Je kan de afmetingen en de plaats opgeven in pixels en/of als afmeting van een celbereik. Range("D1").Left geeft de afstand van de linkerbladrand tot de linkerrand van D1 aan. De aanduiding van de andere afmetingen is wellicht duidelijk.

Met 'cmdNieuw.Caption=' krijgt elke nieuwe knop meteen een label.

Na 'cmdNieuw.OnAction=' geef je de naam van de macro op die moet uitgevoerd worden wanneer op het object (hier een knop) geklikt wordt. Je kan hier echter géén parameter opgeven!

Private Sub Worksheet_DeActivate()
ActiveSheet.Buttons.Delete
End Sub
Bij her verlaten van het blad worden alle knoppen verwijderd.

 

Public Sub Kalender()
Dim strKnoptekst As String
Dim dtmStart As Date
Dim intTeller, intMaand As Integer
strKnoptekst = (ActiveSheet.Buttons(Application.Caller).Caption)
dtmStart = CDate(ActiveSheet.Buttons(Application.Caller).Caption)
KalenderMetParameter2 (dtmStart) 'kalender voor gekozen maand
End Sub
Bij het aanmaken van de 3 knoppen wordt telkens de macro 'Kalender' aangeroepen. Hoe kan dan uitgemaakt worden voor welke maand een kalender moet gemaakt worden? De eigenschap 'Application.Caller' laat je toe de aangeklikte knop te identificeren. Het label ervan wordt hier gebruikt als parameter van de macro 'KalenderMetParameter2'.

 

Sub KalenderMetParameter2(dtmStart As Date)
'Eenvoudige kalender in twee kolommen
Dim dtmTel As Date
dtmTel = dtmStart
'Vorige kalender wissen
Range("a1:b31").Clear
Range("a1").Activate
Do
   ActiveCell.Value = Format(dtmTel, "yyyy-mm-dd")
   ActiveCell.Offset(0, 1).Value = Format(dtmTel,    "dddd")
   ActiveCell.Offset(1, 0).Activate
   dtmTel = dtmTel + 1
Loop While Month(dtmTel) = Month(dtmStart)
Range("a1").Activate
End Sub
De macro KalenderMetParameter2 is niet dezelfde als KalenderMetParameter die hiervoor gebruikt werd. Er zijn 2 verschillen:
  1. het type van de parameter
  2. de plaats: 'KalenderMetParameter2' staat niet in het codevenster van een werkblad doch in een moduleblad. Dit maakt dat de macro bereikbaar is vanuit elke andere lokatie van het project! Een macro in een codescherm van een werkblad daarentegen is enkel daarbinnen te gebruiken. Omdat de macro 'KalenderMetParameter2' straks nogmaals kan gebruikt worden vanaf het blad 'Kalender04' werd hij in een moduleblad opgenomen.

8.10.4. Een formulier maken

We maken nog éénmaal een maandkalender.

In een werkblad kan je een formulier plaatsen. De 3 maanden vanaf de huidige moeten in een groepsvak met keuzerondjes getoond worden.De opdrachtknop 'Lijst maanden' biedt de mogelijkheid elke maand van het jaar te selecteren. Er wordt namelijk bij het klikken een keuzelijst met invoervak getoond met de namen van de 12 maanden. Zodra een geldige keuze is gemaakt kan de kalender afgedrukt worden dmv. de opdrachtknop 'Druk'.

Werkwijze:

  1. Je maakt het formulier en plaatst er de besturingselementen in.
  2. Je schrijft de nodige code bij de besturingselementen.
  3. Je implementeert het formulier in het project.

a. Formulier aanmaken

Je vindt in de 'Visual-Basic'-omgeving de knop 'UserForm' zoals hiernaast afgebeeld. Bij Invoegen staat het vervolgmenu van hiernaast. Je krijgt na het klikken het lege formulier en het eigenschappenvenster te zien.

Belangrijke handelingen:

objecten selecteren klik (Projectverkenner). Klik rechts en kies uit het snelmenu 'Object weergeven'.
code bij een object klik rechts op het geselecteerde object en kies in snelmenu 'Programmacode tonen' of druk F7 of dubbelklik op het geselecteerde object.
eigenschappenvenster klikken na selectie object

Sleep uit de 'Werkset Bsturingselementen' een groepsvak, 3 keuzerondjes IN het groepsvak, twee opdrachtknoppen en een keuzelijst met invoervak zoals in het voorbeeld. Nu moeten een aantal eigenschappen worden ingesteld.

Eigenschappen per object

Object Eigenschap Waarde
UserForm Name frmKalender
  Caption Kalender
Groepsvak Name grpKalender
  Caption Kalender
Keuzerondjes Name opt1, opt2,opt3
  Caption  
Opdrachtknop 'Lijst maanden' Name cmdKeuze
  Caption Lijst maanden
Opdrachtknop 'Druk' Name cmdDruk
  Caption Druk
Keuzelijst Name cboKeuze
  RowSource G1:G12

De waarde van eigenschap 'Rowsource' bepaalt waar je de gegevens vandaan haalt die in de keuzelijst getoond worden. In het voorbeeld werd in de cellen G1:G12 de namen van de maanden gezet. Je kan dan de in houd van deze cellen verbergen dmv. de celeigenschappen.

b. Code bij de besturingselementen

Nadat de objecten aangemaakt zijn schrijf je de code die moet uitgevoerd worden bij de diverse gebeurtenissen die zich in of met het formulier kunnen voordoen.

Private Sub UserForm_Activate()
Opt1.Caption = Format(DateSerial(Year(Now()), Month(Now), 1), "mmmm yyyy")
Opt2.Caption = Format(DateSerial(Year(Now()), Month(Now) + 1, 1), "mmmm yyyy")
Opt3.Caption = Format(DateSerial(Year(Now), Month(Now) + 2, 1), "mmmm yyyy")
cmdDruk.Enabled = False
cboKeuze.Visible = False
End Sub
Bij het activeren van het formulier wordt de tekst bepaald die bij de 3 keuzerondjes geschreven wordt.

De knop 'Druk' mag enkel gebruikt kunnen worden nadat een keuze is gemaakt.

De keuzelijst met de 12 maanden mag enkel getoond worden wanneer je op de knop 'Lijst maanden' hebt gedrukt.

Private Sub grpKeuze_Enter()
cboKeuze.Visible = False
cboKeuze.ListIndex = -1
End Sub
Je gebruikt of het groepsvak of de keuzelijst. Wanneer dus het groepsvak gebruikt wordt, moet de keuzelijst verborgen en de daar (eventueel) gemaakte keuze geannuleerd worden.
Private Sub Opt1_Click()
cmdDruk.Enabled = True
End Sub
Private Sub Opt2_Click()
cmdDruk.Enabled = True
End Sub
Private Sub Opt3_Click()
cmdDruk.Enabled = True
End Sub
Klikken op een keuzerondje in het groepsvak moet meteen de knop 'Druk' bruikbaar maken.
Private Sub cmdKeuze_Click()
Opt1.Value = False
Opt2.Value = False
Opt3.Value = False
cboKeuze.Visible = True
cboKeuze.ListIndex = -1
cmdDruk.Enabled = False
End Sub
Klikken op de knop cmdKeuze ('Lijst maanden') moet de (eventueel) gemaakte keuze in het groepsvak annuleren en de keuzelijst tonen.

De keuzelijst cboKeuze wordt geopend zonder dat een selectie ingesteld wordt (ListIndex=-1).

De knop cmdDruk ('Druk') moet uitgeschakeld worden tot wanneer een keuze gemaakt werd?

Private Sub cboKeuze_Change()
If cboKeuze.ListIndex <> -1 Then
cmdDruk.Enabled = True
Else
cmdDruk.Enabled = False
End If
End Sub
Is er een geldige keuze gemaakt in de keuzelijst dan mag de knop cmdDruk ('Druk') geactiveerd worden.
Private Sub cmdDruk_Click()
Dim optX As Control
For Each optX In grpKeuze.Controls
   If optX = True Then KalenderMetParameter2    (optX.Caption)
Next optX
If cboKeuze.BoundValue <> "" Then KalenderMetParameter2 (CDate(cboKeuze.BoundValue + "-" + CStr(Year(Date))))
End Sub
Bij het klikken op de knop cmdDruk ('Druk') wordt onderzocht vanwaar de drukopdracht komt: ofwel vanuit het groepsvak ofwel vanuit de keuzelijst.

De waarde van de eigenschap 'BoundValue' van de keuzelijst levert de naam van de geselecteerde maand op.

c. Implementatie van het formulier

Het formulier moet geactiveerd worden wanneer het werkblad 'Kalender04' geactiveerd wordt.

Private Sub Worksheet_Activate()
frmKalender.Show
End Sub
'Activate' is de gebeurtenis die zich voordoet wanneer je op de tab van het betreffende blad klikt. 'Show' is een methode van en object van het type 'userform'

Oefeningen:

Zoek voor elke gebeurtenis van elk object uit het formulier 'Kalender' het helpscherm.

Maak een formulier met een keuzelijst voor het jaar en een voor de maanden. Voorzie een knop om een maandkalender af te drukken nadat een geldige keuze is gemaakt.