tirsdag den 15. november 2016

Dialoger og makroer

Jeg har skrevet om dialog med brugeren i en tidligere artikel her: http://libreofficedk.blogspot.dk/2016/11/dialog-med-brugeren.html

Men den vigtigste og mest avancerede form for dialog med brugeren er...dialoger.

Når vi skal arbejde med dialoger i LibreOffice makroer, skal vi igennem en række trin:

1) Designe dialogen
2) Programmere eksekvering af dialogen
3) Programmere eksekvering af OK og aflæse brugerens valg
4) Programmere Annuller
5) Knytte makroerne til (OK og Annuller) knapper i dialogen

Vi starter fra toppen og hen ad vejen lærer vi begreberne lidt hen ad vejen.

1) Oprette og designe dialog

Du kan oprette en dialog fra LibreOffice med Funktioner - Makroer - Administrer dialoger... eller fra Funktioner - Makroer - Administrer makroer...

Fra makroeditoren ser du i bunden en omvendt fane, med navnet "Module1" Der er fordi du har et enkelt makromodul med navnet Module1. Højreklik og vælg Indsæt - BASIC-dialog.

Nu er der endnu en omvendt fane, sandsynligvis med navnet "Dialog1". Samtidig ser du i det store vindue en dialog-editor. Nederst i skærmbilledet ser du en palette af værktøj, som du kan bruge til at designe din dialog. Her finder du også de kontrolelementer, som du kan indsætte i dialogen. På værktøjslinjen er også et ikon med navnet Forhåndsvisningsdialog, som du kan bruge til at vise hvordan dialogen ser ud når den eksekveres.


Hvis du markerer dialogen, ser du i venstre side af skærmbilledet et område, hvod du kan indtaste forskellige egenskaber om dialogen, blandt andet give den et nyt navn (ikke synligt i dialogen) eller tildele en titel (synligt i dialogen).

Nu kan du tilføje kontrolelementer til dialogen, blandt andet felter og knapper. Eksperimenter med forskellige typer af kontrolelementer.

Rullelisten fodrer du med valgmuligheder i egenskaben Listeelementer - en valgmulighed per linje.




2) Eksekvere af dialogen

Dialogen kan vi eksekvere fra programkode i BASIC. Der er to forskellige måder:

Sub Dialog1Show
    BasicLibraries.LoadLibrary("Tools")
    oDialog1 = LoadDialog("Standard", "Dialog1")
    oDialog1.Execute()
End Sub

Hvis dialogen opbevares i et dokument, skal du anvende GlobalScope.BasicLibraries.LoadLibrary("Tools") i den første linje.

Uden brug af "LoadDialog" kan du kalde koden som følger:

Sub Dialog1Show
    DialogLibraries.LoadLibrary("Standard")
    oDialog1 = CreateUnoDialog( DialogLibraries.Standard.Dialog1 )
    oDialog1.Execute()
End Sub

Sidstnævnte eksempel er sikrest og lettest at få til at fungere, specielt hvis makroen benytter dokumentet som makrobibliotek.

3) Programmere eksekvering af OK og aflæse brugerens valg

Eksekvering af OK-knappen skal igangsætte en række begivenheder, som skal foregå i den rigtige rækkefølge.

Først skal vi finde data i de forskellige kontrolelementer for til sidst at lukke dialogen.

Når vi skal aflæse hvad brugeren har udfyldt i formularen, skal vi kende lidt til hvordan LibreOffice "tænker". Dialogen har nogle egenskaber, som vi kan aflæse af variablen oDialog1. F.eks. er oDialog.Title= "Min helt egen dialog" og oDialog1.Size.Height=235.

Dialogens indhold derimod, finder vi i dialogens model.

oModel= oDialog.Model

F.eks. kan vi ændre dialogens baggrundsfarve sådan:

oModel.BackgroundColor = rgb(255,255,255)

De enkelte kontrolelementer kan vi få fat i med deres navn:

oModel.getByName("TextField1")

Det vi skal nå frem til er at aflæse indholdet af de forskellige kontrolelementer. Vi skal oprette en ny subrutine, som eksekveres når OK-knappen trykkes på. Fordi variablen oDialog1 blev dimensioneret udenfor subrutinen, er den global og eksisterer altså stadig når vi kommer ud af den subrutine som åbner dialogen.

Sub OK_trykket
    oModel= oDialog1.Model
    Navn= oModel.getByName("TextField1").Text

    Print Navn

    oDialog1.endExecute()
End sub

Det skal vi gøre for hver enkelt felt brugeren kan udfylde. For tekstfeltet (TextField1) skal vi hente indformationen med .text, men for de øvrige felttyper er det lidt anderledes.

Radioknapperne håndterer vi ved for hver enkelt at aflæse .State:

    Linux= oModel.getByName("OptionButton1").State
    Mac= oModel.getByName("OptionButton2").State
    Windows= oModel.getByName("OptionButton3").State

Listboksen (Region) er lidt speciel, fordi vi skal håndtere at der ikke behøver at være noget vlagt. Heldigvis er det forholdsvis let. Desuden får vi i første omgang kun oplysninger om hvilket element (nummer i rækken) der er valgt (RegionNumber). Det skal vi så efterfølgende oversætte til noget brugbar tekst. Det gør vi sådan:

    Region= oModel.getByName("ListBox1").StringItemList(RegionNumber)

Tjekboksen Nyhedsbrev aflæser vi også med .State

Til sidst skal vi så aflevere informationerne, hvilket jeg af praktiske årsager går ved at vise en MsgBox. Måske skulle vi indsætte resultatet i celler i et regneark? Det må blive en anden dag.

Hele makroen (som starter med den subrutine som eksekverer dialogen) tilknyttes OK-knappen. I dialog-editoren vælger du OK-knappen og kigger i venstre side. Her ser du egenskaber for knappen. Vælg fanen "Hændelser" og find hændelsen "Museknap trykket". Tilknyt makroen til hændelsen.

4) Programmere Annuller-knappen

Programmet som vi skal bruge til at lukke dialogen uden videre er temmelig meget mere overskuelig:

Sub CloseDialog
  oDialog1.endExecute()
End Sub

Denne makro skal så tilknyttes til Annuller-knappen.

Hele makroen


Herunder er hele makroen:

REM  *****  BASIC  *****


Dim oDialog1 as Object

Sub Dialog1Show
    DialogLibraries.LoadLibrary("Standard")
    oDialog1 = CreateUnoDialog( DialogLibraries.Standard.Dialog1 )   
    oModel= oDialog1.Model
    oModel.BackgroundColor = rgb(255,255,255)
    oDialog1.Execute()
End Sub

Sub CloseDialog
  oDialog1.endExecute()
End Sub

Sub OK_trykket
    oModel= oDialog1.Model
    Navn= oModel.getByName("TextField1").Text
    Linux= oModel.getByName("OptionButton1").State
    Mac= oModel.getByName("OptionButton2").State
    Windows= oModel.getByName("OptionButton3").State

    If ubound (oModel.getByName("ListBox1").SelectedItems) >-1 then
        RegionNumber=oModel.getByName("ListBox1").SelectedItems(0)
        Region= oModel.getByName("ListBox1").StringItemList(RegionNumber)
    End if

    Nyhedsbrev=oModel.getByName("CheckBox1").State

    oDialog1.endExecute()

    MsgBox("Navn: " & Navn & Chr(13) & "Linux: " & Linux & Chr(13) & "Mac: " & Mac  & Chr(13) & "Windows: " & Windows  & Chr(13) & "Region: " & Region & Chr(13) & "Nyhedsbrev: " & Nyhedsbrev)

End sub