Brug af dialogbokse og formularer

Excels indbyggede dialogbokse
Gem valg i variabel
Egne formularer

 

Når man programmerer i VBA vil man ofte gerne kunne kommunikere mere med brugeren end bare det, som meddelelses- og inputbokse giver mulighed for. Excel har et stort antal dialogbokse, som man kan anvende og man kan også lave sine egne dialogbokse i form af brugerdefinerede formularer. I denne artikel vi jeg se nærmere på begge muligheder på introduktionsplan.

 

Her ses et eksempel på én af Excels indbyggede dialogbokse:

 

 

og her en "hjemmelavet":

 

 

Excels indbyggede dialogbokse

Lad mig starte med de indbyggede dialogbokse. Dem har Excel som nævnt en hel del af, og de fleste af dem kan man uden problemer bruge i sin kode. De, der har prøvet at indspille makroer vil vide, at man ikke kan indspille sig til visning af en dialogboks. Det er nemlig ikke muligt at stoppe indspilningen af makroen før dialogboksen er lukket, og så er det, som bliver registreret i koden, den handling, man udførte i dialogboksen. Det vil sige, at når man afspiller makroen vil den gøre det, den blev bedt om, men den viser ikke dialogboksen undervejs.

 

Skal man fx indspille en makro, hvor man åbner en anden fil, kan man indspille sig frem til denne kode:

 

Sub Makro1()

'

' Makro1 Makro

' Makro indspillet 26-02-2010 af Jan Kronsell

'

 

'

    Workbooks.Open Filename:= _

        "C:\Documents and Settings\Administrator\Dokumenter\Deadline.xls"

End Sub

 

og når man afspiller den, åbner det specificerede dokument. Desværre får jeg ikke lejlighed til at vælge et andet dokument undervejs.

 

For at kunne vise en dialogboks, skal man bruge det objekt, som ejer dialogboksen. Det vil i Excel være Application-objektet. Desuden skal man kende navnet på dialogboksen. Og så skal man kende den metode, der viser denne.

 

Sub Makro1()

    Application.Dialogs(xlDialogOpen).Show

End Sub

 

Denne makro udfører jobbet. Application er altså det overordnede objekt. Det indeholder/ejer objektet Dialogs. I parentesen specificeres navnet på den dialogboks, det drejer sig om, og der afsluttes med at angive, at der til objektet skal anvendes metoden Show, som viser dialogboksen.  Denne syntaks er identisk for alle de dialogbokse, man kan få vist via sin kode. Når man begynder at skrive sin kode og kommer til start-parentsen, vises en liste med de tilgængelige dialogbokse. Disse begynder alle sammen med xlDialog og så navnet på dialogboksen. Dette er typisk det engelske navn på den funktion som dialogboksen repræsenterer, men der er ikke altid helt tilfældet. Søger man i hjælpen til VBA efter "Built-in Dialog Box Argument List finder man det pågældende punkt, og klikker man så på det, vises en oversigt over alle dialogboksenes navne med oplysning om, hvilke argumenter, de pågældende bokse kan kaldes med. Se illustrationen på næste side.

 

Argumenter er informationer, som automatisk overføres til dialogboksen, når denne kaldes.

 

Sub Makro1()

    Application.Dialogs(xlDialogOpen).Show "filnavn.txt"

End Sub

 

Koden her, viser som tidligere Åben-dialogboksen, men denne gang har den et argument med. Dette argument (det første i en række) fortæller, hvilket filnavn, man gerne vil have foreslået i dialogboksen, når den er åbnet. Læg mærke til at selv om argumenterne hører til dialogboksen, skal de først skrives efter metoden. Skal man bruge et argument, som ikke er det første, kan man sætte kommaer for udeladte argumenter fx

 

Sub Makro1()

    Application.Dialogs(xlDialogActiveCellFont).Show , , 16

End Sub

 

Koden her viser en dialogboks, hvor der kan vælges skrifttype, størrelse mm for den aktive celle. De første to argumenter er skrifttypens navn og om den skal være fed, kursiv osv.  Det tredje er størrelsen og her vil vi gerne foreslå 16 punkt.

 

Koden her forslår skrifttypen Times New Roman i størrelse 16

 

Sub Makro1()

    Application.Dialogs(xlDialogActiveCellFont).Show "Times New Roman", , 16

End Sub

 

 

Læg mærke til, at selv om man normal programmerer på engelsk, hvor Fed hedder Bold og Kursiv hedder Italic, skal man her skrive begge dele på dansk, fordi det er de danske betegnelser, der bruges i dialogboksen.

 

Desværre er argumenterne meget dårligt dokumenteret i hjælpen til Excel, og man kan ikke altid gætte sig til, hvad der skal stå i et givent argument. I så fald er der nok ikke andet at gøre, end at prøve sig frem. De fleste argumenter skal dog have en talmæssig værdi eller en logisk værdi (TRUE/FALSE). Ved at eksperimentere, kan man fx nå frem til at denne kode

 

Sub Makro1()

    Application.Dialogs(xlDialogPrint).Show 2, 1, 2, 3, , , , , , , , 1, , , True

End Sub

 

vil vise print-dialogboksen med disse indstillinger:

 

 

Det første 2-tal fortæller, at vi vil printe sider. Et 1-tal i det første argument ville have foreslået Alt. De to næste argumenter er Fra_side og Til_side. Her skal man være opmærksom på, at koden ikke "brokker sig", hvis man fx beder dem om at printe fra side 14 til side 3. 3-tallet i fjerde argument fortæller, at vi gerne vil udskrive 3 kopier.  1-tallet i argument 12 fortæller, at vi gerne vil udskrive Markeringen og True i argument 15 fortæller at jeg gerne vil udskrive Sætvis. På den måde er det bare at gå gang fra en ende af – med de dialogbokse, man skal bruge, og så se hvad de forskellige argumenter, får dialogboksen "til at gøre".

 

NB! Når man skal anvende argumenterne, kan man anvende deres position i argumentrækkefølgen og altså angive udeladte argumenter med kommaer. Man kan imidlertid også bruge navngivne argumenter på samme måde som i Input- og meddelelsesbokse, se Kommunikation med makroer. Imidlertid er argumentnavne ikke særligt sigende, da de bare hedder Arg1, Arg2 osv. Man skal altså stadig vide, hvad de enkelte argumenter skal indeholde, men det kan da godt være nemmere at skrive

 

Sub Makro1()

    Application.Dialogs(xlDialogPrint).Show Arg15:=True

End Sub

 

fremfor 

 

Sub Makro1()

    Application.Dialogs(xlDialogPrint).Show , , , , , , , , , , , , , , True

End Sub

 

Nogle elementer i en dialogboks, fx stien i en gem_som-dialog  eller en åbn-dialog er ikke et argument ved selve dialogboksen. For eksempel vil

 

Sub Makro1()

    Application.Dialogs(xlDialogSaveAs).Show Arg1:="Mitegetnavn.xls"

End Sub

 

vise Gem som dialogboksen med Mitegetnavn.xls som forslag til filnavn, men den vil foreslå det gemt i Standard-mappen, fx Dokumenter. Vil man foreslå det gemt et andet sted, må man selv ændre stien i koden:

 

Sub Makro1()

    ChDir "c:\xx"

    Application.Dialogs(xlDialogSaveAs).Show Arg1:="Mitegetnavn.xls"

End Sub

 

vil vise

 

 

Idet ChDir kommandoen skifter til den mappe, der specificeres.

 

 - Til top -

Gem valg i variabel

Af og til vil man gerne gemme brugerens valg i en variabel, for at kunne anvende dette et andet sted i koden. Det er desværre bare ikke muligt. Ønsker man fx at gemme det filnavn, som en bruger klikker på i Åbn-dialogen, så man selv kan bruge det videre i sin kode i stedet for bare at åbne filen, kommer man ikke ret langt, ved hjælp af de indbyggede dialogbokse. Her er man derfor nødt til at gå en anden vej og anvende en af to metoder, der adresserer styresystemet direkte, nemlig GetSaveAsFilename metoden og GetOpenFilename metoden.

 

De to metoder bruges på fuldstændigt samme måde:

 

Sub HentHilNavn()

    GemFilNavn = Application.GetSaveAsFilename()

    MsgBox "Du gemte som " & filesavename

End Sub

 

vil vise dialogboksen ovenfor og derefter en meddelelsesboks. Læg mærke til, at hele stien hentes med GetSaveFilename. Navnet gemmes i variablen, her GemFilNavn, men der sker ingen reel gemning. Bruges i stedet GetOpenFilename metoden, vises Åbn-dialogen, men ellers fungerer denne på helt samme måde. Der åbnes altså heller ikke nogen fil, når der klikkes OK.

 

Når filnavnet på denne måde er "fanget", kan man bruge det til, hvad man nu har brug for i sin kode. Denne kode skriver filnavnet uden sti i en meddelelsesboks:

 

 

Sub HentFilNavn()

    GemFilNavn = Application.GetSaveAsFilename()

    MsgBox "Filnavn: " & Mid(GemFilNavn, InStrRev(GemFilNavn, "\") + 1, Len(GemFilNavn))

End Sub

 

InStrRev(GemFilNavn, "\") + 1 finder placeringen af den sidste "\" + et tegn, altså det første bogstav efter den sidste backslash.

Mid(GemFilNavn, InStrRev(GemFilNavn, "\") + 1) finder en delstreng af en streng.  Først angives navnet på strengen. Så det sted, hvor delstrengen skal begynde, i dette tilfælde et tegn efter den sidste skråstreg. Mid kan have en længde angivelse til sidst, men anføres den ikke tages til slutningen af strengen, der undersøges.

 

 - Til top -

Egne formularer (dialogbokse)

Excels indbyggede dialogbokse er rigtigt gode til det, de nu er gode til. Det er imidlertid ikke altid, at man kan nøjes med dem. Inputboks og Meddelelsesboks kan bringe én langt, men heller ikke disse er specielt effektive i alle sammenhænge. Forestil dig, at du skal bruge 3 forskellige informationer fra Excel, som alle skal gemmes i forskellige variabler. Det kunne gøres på denne måde:

 

Sub HenteMangeData()

    Dim varA As Integer, varB As Integer, varC As Single

    varA = InputBox("Indtast antal")

    varB = InputBox("Indtast antal, der skal lægges til")

    varC = InputBox("Indtast antal, der skal divideres med")

    MsgBox "Svaret er " & (varA + varB) / varC

End Sub

 

Det vil vise tre forskellige inputbokse og til sidst en meddelelsesboks, og det er både besværligt at skrive og ikke mindst besværligt at bruge. Og forestil dig så, at der var 20 forskellige variabler, der alle skulle indtastes. Her ville en brugerdefineret formular være langt mere effektiv.

 

For at lave sin egen formular, skal VBA editoren være åben. Herefter vælger man Insert – Userform. Så vises

 

 

Toolbox kan være placeret andre steder end her. Formularen er oprettet men ganske tom. Det skal vi nu have lavet om på ved hjælp af værktøjerne i Toolbox.

 

 

Toolbox (eller værktøjskassen) indeholder, som det ses, forskellige værktøjer.

 

  Markeringsværktøj til at marker objekter i formularen.

  Labelværktøj til at indsætte tekstetitketter (fx ledetekster) i formularen.

  Tekstboksværktøj til at indsætte tekstbokse, som brugeren kan skrive i.

 Kombinationsboksværktøj, som kan indsætte kombinationsbokse, som brugeren kan vælge fra.

  Listboksværktøj som bruges til at indsætte listbokse, som brugeren kan vælge fra.

  Checkbox værktøj til at indsætte afkrydsningsfelter.

  Valgmulighedsværktøj, til at indsætte "radioknapper"

  Tænd/sluk værktøj, som bruges til at indsætte "Enten/Eller-knapper"/"Tænd/Sluk-knapper".

  Rammeværktøj som bruges til at "indramme" sammenhørende funktioner.

  Kommandoknapværktøj som bruges til at indsætte kommandoknapper.

  Fanerækkeværktøj som bruges til at indsætte faner.

  Multisideværktøj, som bruges til at indsætte flere faneblade i en formular.

  Scrollbarværktøj som bruges til at indsætte en scrollbar.

  Spinværktøj, som bruges til at indsætte "bladringsknapper"

  Billedværktøj, som bruges til at indsætte et billede i en formular.

  RefEdit værktøj som bruges til at indsætte områdeudpegningsboks i en formular.

 

Jegvil ikke her gennemgå alle værktøjerne men nøjes med nogle få af dem. De virker alle på den måde, at man klikker på den relevante knap, og derefter trækker et objekt af en passende størrelse ud i formularen. Placeringen af det pågældende objekt kan senere ændres, ved at flytte det med musen, hvis det ikke er placeret korrekt. Også formularens størrelse kan ændres ved at trække i den.

 

 

Lad mig illustrere dette med et simpelt eksempel. I formularen til venstre er indsat tre tekstbokse og en knap. Desuden fem labels, én for hvert tal og én til forklaringen, foruden en label som lige nu er usynlig. Den er placeret til venstre for knappen, og skal bruges til at skrive resultatet af udregningen. Foreløbigt gør dialogboksen absolut ingenting, da man selv skal lægge den fornødne kode ind i denne.

 

Det vil vi se på om lidt, men først lidt om de anvende objekter.

 

Alle objekter i en formular, inklusive formularen selv, har en række egenskaber. Disse kan sættes i egenskabsvinduet til venstre i skærmbilledet. Egenskaberne i vinduet gælder for, og afhænger af, hvilket objekt, der er aktivt.

 

 

 

               

 

Til venstre nogle af formularens egenskaber, i midten egenskaber fra en tekstboks og til højre et udvalg af kommandoknappens egenskaber. I ruden til højre, ud for egenskabens navn, kan man ændre en given egenskabs værdi.  (Name) er objektets navn og bør altid ændres til noget sigende. "Caption" svarer til titel i en formular eller Tekst på en knap mm. Det vil føre for vidt at gennemgå alle de forskellige egenskaber, som hver af de mange objekter kan have.

 

I det første eksempel vil vi gerne havde den til at udføre den samme beregning, som i eksemplet først i dette afsnit. Den kode, der skal til, vælger vi at lægge på kommandoknappen.

 

Nu er det så bare at skrive den nødvendige kode. Da vi skal referere til de tre tekstbokse samt den usynlige etiket i koden, kan det betale sig at omdøbe disse til Tal1, Tal2, Tal3 og Resultat. Det gør det nemmere at skrive, og gør koden mere overskuelig.

 

Private Sub CommandButton1_Click()

    Me!Resultat.Caption = (CInt(Tal1.Value) + CInt(Tal2.Value)) / CInt(Tal3.Value)

End Sub

 

Her ses dialogboksen i anvendelse. Når der indtastes tal i de tre ruder og klikkes på knappen udføres beregningen. Koden skal læses som følger:

 

 

I etiketten Resultats titel skrives resultatet af denne beregning. Heltalsværdien af Tal1 + heltalsværdien af Tal2 divideret med heltalsværdien af Tal3. CInt() omdanner den tekst, som tastes i tekstboksen til en talværdi. Skulle der have været mulighed for decimaler, kunne CSng() have været brugt. Når man først har styr på funktionaliteten, er det langt nemmere end koden i begyndelsen af afsnittet.

 

Formularen kan afprøves ved at klikke på knappen  i værktøjslinjen.

 

I eksemplet nedenfor har jeg "leget" lidt med formularens og dens knapper og felters egenskaber.

 

 

 

 

 

 

 

 

 

 

 

Ikke så kønt, men det illustrerer princippet med egenskaber og det er vigtigt at prøve sig frem, da det kan være svært at læse sig konsekvenserne af alle ændringer.

 

Nu mangler vi så bare at få vores formular vist. Det gør vi med en almindelig makro i et helt almindeligt modul.

 

Sub VisRegnemaskine()

    Regnemaskine.Show

End Sub


Det handler altså bare om at vise det relevante formularobjekt.

 

I eksemplet her har vi knyttet kode til knappen, men der kan også knyttes kode til tekstbokse, etiketter og alle de andre objekter, der kan anbringes i en formular. Koden bør selvfølgelig også udbygges med fejlhåndteringsrutiner, der sikrer, at der kun indtastes tal og meget andet, men det gøres på samme måde som allerede omtalt andre steder.

 

Her til sidst endnu et eksempel på en hjemmelavet formular. Formularen har ingen egentlig funktion andet end at vise lidt af, hvad formularer kan bruges til:

 

 

I øverste venstre hjørne kan man vælge mellem tre forskellige baggrundsfarver til formularen. Ruden derunder indsætter tal i de celler, der afkrydses. Klik på "Indsæt formel" og der indsættes formler i F-kolonnen ud for de celler, hvor der både står noget i D og E kolonnen i samme række. "Ryd tal og formler" rydder alt, hvad der er af tal og formler i området.

 

I ruderne øverst til venstre i billedet kan man vælge dels en herre, dels en dame. Knappen "Dan par" skriver teksten " Dagens par: herre og dame" i celle D1, hvor herre og dame erstattes af de valgte navne. Knappen "Skift billede" er ikke, som de tre andre knapper, en kommandoknap, men en tænd/sluk knap, også kaldet en Togglebutton. Den skifter mellem to forskellige billeder. Er knappen ikke trykket ind vises billedet af diagrammet, er den trykket ind vises et andet billede. Sidst men ikke mindst er der en scrollbar og en tilhørende tekstboks. Når der scrolles på scrollbaren vil tallet i tekstboksen stige eller falde med 1 ad gangen.

 

Ruden i midten, øverst gør egentlig ikke noget, men er et eksempel på en RefEdit boks. Idéen med disse er at man kan klikke på knappen til højre og så kan man direkte udpege celler i regnearket, fx

 

 

som det kendes fra flere af Execels egne dialogbokse.

 

 

Det hele er styret at nogle egenskaber ved de forskellige objekter, samt noget kode. Reelt set er det stort set kun teksterne (caption) og så nogle få navne, der er indstillet og så i scrollbaren er der sat maksimun og minumværdier for hvor meget der kan tælles. Til gengæld indeholder formularen en hel del kode, som her gengives ukritisk.

 

Generer dagens par:

Private Sub CommandButton1_Click()

    ActiveSheet.Range("C1").Value = "Dagens par: " & CB1 & " og " & CB2

End Sub

 

Sæt formler i de celler, hvor både D og E er udfyldt

Private Sub CommandButton2_Click()

    For Each c In Range("d1:d4").Cells

        If Len(c) > 0 And Len(c.Offset(0, 1)) > 0 Then

            c.Offset(0, 2).Formula = "=" & c.Address & "*" & c.Offset(0, 1).Address

        End If

    Next c

End Sub

 

Tøm området D1:F4

Private Sub CommandButton3_Click()

    Range("D1:F4").Clear

End Sub

 

Skift mellem gul, rød og blå baggrundsfarve i formularen

Private Sub OptionButton1_Click()

    Demo.BackColor = vbYellow

End Sub

 

Private Sub OptionButton2_Click()

    Me.BackColor = vbRed

End Sub

 

Private Sub OptionButton3_Click()

    Me.BackColor = vbBlue

End Sub

 

Opdater tekstboksen når der scolles i scrollbaren

Private Sub ScrollBar1_Change()

    TalB.Value = ScrollBar1.Value

End Sub

 

Skift billede i billedfelt ved klik på tænd/sluk knappen

Private Sub ToggleButton1_Click()

    If ToggleButton1 = True Then

        I1.Picture = LoadPicture("c:\xx\pal.jpg")

    Else

        I1.Picture = LoadPicture("c:\xx\diagram.jpg")

    End If

End Sub

 

 

Sæt tal i afkrydsede celler

Private Sub xb1_Click()

    If xb1 = True Then

            Range("d1") = 1

    Else

            Range("d1") = ""

    End If

End Sub

 

Private Sub xb2_Click()

    If xb2 = True Then

            Range("d2") = 2

    Else

            Range("d2") = ""

    End If

End Sub

 

Private Sub xb3_Click()

    If xb3 = True Then

            Range("d3") = 3

    Else

            Range("d3") = ""

    End If

End Sub

 

Private Sub xb4_Click()

    If xb4 = True Then

            Range("d4") = 4

    Else

            Range("d4") = ""

    End If

End Sub

 

Private Sub xb5_Click()

    If xb5 = True Then

            Range("e1") = 5

    Else

            Range("e1") = ""

    End If

End Sub

 

Private Sub xb6_Click()

    If xb6 = True Then

            Range("e2") = 6

    Else

            Range("e2") = ""

    End If

End Sub

 

Private Sub xb7_Click()

    If xb7 = True Then

            Range("e3") = 7

    Else

            Range("e3") = ""

    End If

End Sub

 

Private Sub xb8_Click()

    If xb8 = True Then

            Range("e4") = 8

    Else

            Range("e4") = ""

    End If

End Sub

 

Brugen af såvel hjemmelavede som indbyggede dialogbokse, er det, som kan få dine makroer til at hænge sammen, og skabe en helt ny applikation, der udnytter alle Excels egenskaber. I yderste konksekvens behøver brugeren slet ikke at se Excel, men kan nøjes med dine dialogbokse.

 

 - Til top -
- Tilbage til Programmering -
- Tilbage til makroer -
- Tilbage til Excel -