Efter at vi tidligere har gennemgået en række dato-funktioner i Calc regneark, vil jeg vise et praktisk eksempel. Makroen herunder danner en to-sidet kalender med helligdage, med seks måneder på hver side. Der er forklarende kommentarer i koden.
Eksempel:
REM ***** BASIC *****
Sub Main
this_year = InputBox ("Indtast årstal mellem 1583 og 3000", "Vælg årstal", year(date))
'Kontroller at årstallet brugbart
If (1583 > val(this_year) OR val(this_year) > 3000) then
MsgBox("Årstallet skal være mellem 1583 og 3000", 48, "Fejl")
Stop
End If
Cal_name="Kalender " & this_year
'Kontroller at dokumentet er et regneark
my_doc = ThisComponent
If not my_doc.SupportsService("com.sun.star.sheet.SpreadsheetDocument") then
MsgBox("Dokumentet skal være et regneark", 48, "Fejl")
Stop
End if
my_sheets = my_doc.Sheets
antal=my_sheets.count
If NOT my_sheets.hasbyName(Cal_name) Then
my_sheets.insertNewByName(Cal_name, antal)
End If
the_sheet = my_sheets.getByName(Cal_name)
'Formatér siden
oStyles = my_doc.StyleFamilies.getByName("PageStyles")
oPstyle = oStyles.getByName(the_sheet.PageStyle)
oPstyle.FooterIsOn = False
oPstyle.FooterIsOn = False
oPstyle.TopMargin=500
'Første linje
oRange = the_sheet.getCellRangeByName("A1:L1")
oRange.merge(True)
oCell= the_sheet.getCellByPosition(0, 0)
oCell.String = Cal_name
FormatDark(oCell)
oRange = the_sheet.getCellRangeByName("M1:X1")
oRange.merge(True)
oCell= the_sheet.getCellByPosition(12, 0)
oCell.String = Cal_name
FormatDark(oCell)
'Nederste linje
oRange = the_sheet.getCellRangeByName("A34:X34")
oRange.merge(True)
oCell = the_sheet.getCellRangeByName("A34")
FormatDark(oCell)
For m = 1 to 12
'Overskriften
oRange = the_sheet.getCellRangeByPosition(m*2-1-1,1,m*2-1,1)
oRange.merge(True)
the_cell = the_sheet.getCellByPosition(m*2-1-1, 1)
the_cell.String=TheMonthName(m)
the_cell.HoriJustify = 2
the_cell.CellBackColor=rgb(150,150,150)
the_cell.CharColor=rgb(255,255,255)
'Justerer kolonnebredder
Column= the_sheet.Columns(m*2-1-1)
Column.Width=550
Column= the_sheet.Columns(m*2-1)
Column.Width=4000
Next m
'For hver måned...
For m = 1 to 12
'Dag for dag...
For d= 1 to Day(LastDayOfMonth(DateValue("1-" & m & "-" & this_year))
the_date=DateValue(d & "-" & m & "-" & this_year)
'Skriv datoen i første kolonne
the_cell = the_sheet.getCellByPosition(m*2-1-1, d + 1)
the_cell.Value=the_date
the_cell.NumberFormat=109
'Formatter cellen
FormatLight(the_cell)
'Skriv ugedagens bogstav i anden kolonne
the_Othercell = the_sheet.getCellByPosition(m*2-1, d + 1)
'Lørdag og søndag formateres
Select Case WeekDay(the_date)
Case 1
FormatLight(the_Othercell)
the_Othercell.String="S"
Case 2
the_Othercell.String="M"
Case 3
the_Othercell.String="T"
Case 4
the_Othercell.String="O"
Case 5
the_Othercell.String="T"
Case 6
the_Othercell.String="F"
Case 7
FormatLight(the_Othercell)
the_Othercell.String="L"
End Select
'Tilføj helligdage
generic_date= left(STR(the_date),5)
oFA = createUnoService( "com.sun.star.sheet.FunctionAccess" )
'Faste helligdage
Select Case generic_date
case "01-01"
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String & " Nytårsdag"
case "05-06"
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" Grundlovsdag"
case "24-12"
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" Juleaften"
case "25-12"
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" Juledag"
case "26-12"
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" 2. Juledag"
'Skæve helligdage
'Der findes ingen påske-beregning i Basic, men vi kan eksekvere regnearksfunktionen =Påskedag)
the_Othercell.String=the_Othercell.String &" Påskedag"
case Left(STR(CDate(oFA.callFunction( "EASTERSUNDAY", array( this_year ) )+1 ) ),5)
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" 2. Påskedag"
case Left(STR(CDate(oFA.callFunction( "EASTERSUNDAY", array( this_year ) )-2 ) ),5)
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" Langfredag"
case Left(STR(CDate(oFA.callFunction( "EASTERSUNDAY", array( this_year ) )-3 ) ),5)
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" Skærtorsdag"
case Left(STR(CDate(oFA.callFunction( "EASTERSUNDAY", array( this_year ) )+49 ) ),5)
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" Pinsedag"
case Left(STR(CDate(oFA.callFunction( "EASTERSUNDAY", array( this_year ) )+50 ) ),5)
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" 2. Pinsedag"
case Left(STR(CDate(oFA.callFunction( "EASTERSUNDAY", array( this_year ) )+26 ) ),5)
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" St. Bededag"
case Left(STR(CDate(oFA.callFunction( "EASTERSUNDAY", array( this_year ) )+39 ) ),5)
FormatLight(the_Othercell)
the_Othercell.String=the_Othercell.String &" Kr. Himmelfartsdag"
End Select
Next d 'Dags-loopet slutter
Next m 'Måneds-loopet slutter
End Sub
Function LastDayOfMonth(d As Date) As Date
'Beregn hvor mange dage i måneden
Dim nYear As Integer
Dim nMonth As Integer
nYear = Year(d) 'Current year
nMonth = Month(d) + 1 'Next month, unless it was December.
If nMonth > 12 Then 'If it is December then nMonth is now 13
nMonth = 1 'Roll the month back to 1
nYear = nYear + 1 'but increment the year
End If
LastDayOfMonth = CDate(DateSerial(nYear, nMonth, 1)-1)
End Function
Function TheMonthName(m)
'Omsætter månedstal til månedsnavn
CompatibilityMode(True)
TheMonthName=MonthName(m)
End Function
Sub FormatLight(oCell)
'Formatér lys grå
oCell.CellBackColor=rgb(200,200,200)
oCell.CharColor=rgb(255,255,255)
End Sub
Sub FormatDark(oCell)
'Formatér overskrift
oCell.CharHeight=18
oCell.HoriJustify = 2
oCell.CellBackColor=rgb(100,100,100)
oCell.CharColor=rgb(255,255,255)
End Sub
Her kan du læse artikler fra LibreOffice i Danmarks månedlige nyhedsbrev. Du kan tilmelde dig nyhedsbrevet ved at sende en mail til nyhedsbrev+subscribe@da.libreoffice.org
tirsdag den 25. oktober 2016
Regneark i Calc (Årskalender)
fredag den 21. oktober 2016
Datoer i Calc med makroer
I makroen hvor vi importerede CSV-filen ved at indlæse linje for linje, anvendte vi the_cell.Value = [datoværdi]. Lad os kige lidt mere på, hvordan datoer håndteres i LibreOffice i makroer.
Vi skal se dato-format problemet i to perspektiver:
1) Datoformatet i variable i makroen
2) Datoen, når den indsættes i eller læses fra en celle.
Det er vigtigt at skelne tydeligt mellem de to perspektiver, da resultatet ellers kan vise sig overraskende (forkert).
Denne artikel omhandler andet punkt, nemlig håndtering af datoer i regnearkets celler.
I eksemplet importerede vi datoen fra en CSV-fil, og derfor var udgangspuntket en tekststreng, som vi så behandlerede således:
t= split(s, "-", 3)
s=DateSerial(t(2), t(1), t(0))
Og vi indsatte så resultatet i cellen sådan:
my_cell.String=s
Det betyder at resultatet er en tekststreng (.String).
Vi burde have gjort det anderledes, nemlig med
my_cell.Value=s
Problemet er dog at resultatet vises i regnearket som datoværdier, f.eks. 42659
Det håndterer vi ved at formatere cellen således:
my_cell.Value=s
my_cell.NumberFormat=36
Tallet .NumberFormat=36 viser datoen som 09-10-2016, hvilket er præcist som ønsket. Tallet 36 fandt jeg frem til ved at formatere en celle manuelt, og så aflæse tallet
Print my_cell.NumberFormat
Her er en makro som demonstrerer det meste:
REM ***** BASIC *****
Sub Main
Dim my_date As Date
my_doc = ThisComponent
my_sheets = my_doc.Sheets
antal=my_sheets.count
If NOT my_sheets.hasbyName("Dato") Then
my_sheets.insertNewByName("Dato", antal)
End If
the_sheet = my_sheets.getByName("Dato")
the_sheet.TabColor= RGB(0, 0, 100)
rem --------------------
my_date = DateValue("20 Jan 2016")
my_cell = the_sheet.getCellbyPosition(1,1)
my_cell.Value = my_date
my_cell.NumberFormat=36
Print my_cell.Value
Print CDate(my_cell.Value)
Print IsDate(my_cell.Value)
End Sub
Vi skal se dato-format problemet i to perspektiver:
1) Datoformatet i variable i makroen
2) Datoen, når den indsættes i eller læses fra en celle.
Det er vigtigt at skelne tydeligt mellem de to perspektiver, da resultatet ellers kan vise sig overraskende (forkert).
Denne artikel omhandler andet punkt, nemlig håndtering af datoer i regnearkets celler.
I eksemplet importerede vi datoen fra en CSV-fil, og derfor var udgangspuntket en tekststreng, som vi så behandlerede således:
t= split(s, "-", 3)
s=DateSerial(t(2), t(1), t(0))
Og vi indsatte så resultatet i cellen sådan:
my_cell.String=s
Det betyder at resultatet er en tekststreng (.String).
Vi burde have gjort det anderledes, nemlig med
my_cell.Value=s
Problemet er dog at resultatet vises i regnearket som datoværdier, f.eks. 42659
Det håndterer vi ved at formatere cellen således:
my_cell.Value=s
my_cell.NumberFormat=36
Tallet .NumberFormat=36 viser datoen som 09-10-2016, hvilket er præcist som ønsket. Tallet 36 fandt jeg frem til ved at formatere en celle manuelt, og så aflæse tallet
Print my_cell.NumberFormat
Her er en makro som demonstrerer det meste:
REM ***** BASIC *****
Sub Main
Dim my_date As Date
my_doc = ThisComponent
my_sheets = my_doc.Sheets
antal=my_sheets.count
If NOT my_sheets.hasbyName("Dato") Then
my_sheets.insertNewByName("Dato", antal)
End If
the_sheet = my_sheets.getByName("Dato")
the_sheet.TabColor= RGB(0, 0, 100)
rem --------------------
my_date = DateValue("20 Jan 2016")
my_cell = the_sheet.getCellbyPosition(1,1)
my_cell.Value = my_date
my_cell.NumberFormat=36
Print my_cell.Value
Print CDate(my_cell.Value)
Print IsDate(my_cell.Value)
End Sub
Lidt om datoer (i makro)
I makroen hvor vi importerede CSV-filen ved at indlæse linje for linje, anvendte vi the_cell.Value = [datoværdi]. Lad os kigge lidt mere på, hvordan datoer håndteres i LibreOffice i makroer.
Vi skal se dato-format problemet i to perspektiver:
1) Datoformatet i variable i makroen
2) Datoen, når den indsættes i eller læses fra en celle.
Det er vigtigt at skelne tydeligt mellem de to perspektiver, da resultatet ellers kan vise sig overraskende (forkert).
Denne artikel omhandler første punkt, nemlig håndtering og bearbejdning af datoer med makroer. Datofunktionerne er ikke afhængige af Calc, men fungerer også med datoer i f.eks. Writer.
I makroen, når vi arbejder med datoer i variable, kan vi tænk på datoer som to forskellige typer tekst: En lokaliseret (dansk, engelsk, ...) version og en international version (ISO 8601 date format). I bund og grund fungerer begge typer fuldstændig uden problemer, men lokaliseret dato er standard, og ISO 8601 (YYYY-MM-DD) er kun relevant, når vi vælger det eksplicit.
Ikke desto mindre regner LibreOffice med en intern dato-værdi, hvor 0 svarer til 29/12/1899: -1
30/12/1899: 0
31/12/1899: 1
01/01/1900: 2
01/02/1900: 3
01/01/2001: 36892
Datokonvertering:
Når vi så har en dato(værdi), kan vi udlede nogle interessante informationer:
Sub test
my_date=DateValue("19 Januar 1965")
Print isDate(my_date) 'True
Print my_date '19/01/1965
Print year(my_date) '1965
End sub
Funktionen DatePart gør noget lignende, nemlig udleder en konkret information
Print DatePart("yyyy",my_date) 'Årstal
Print DatePart("q",my_date) 'Kvartal
Print DatePart("m",my_date) 'Måned
Print DatePart("y",my_date) 'dag i året
Print DatePart("w",my_date) 'Ugedag
Print DatePart("d",my_date) 'Dag
DatePart splitter altså en dato ad i enkeltdele, og vi har en tilsvarende funktion til at samle delene i en dato igen:
Print DateSerial(1965, 1, 19) '19/01/1965
Vær opmærksom på at DateSerial har en fejl, som betyder at datoen før år 100 konverteres forkert, idet der lægges 1900 til årstallet:
Print DateSerial(90, 1, 19) '19/01/1990
Vi kan manipulere datoen med funktionen DateAdd sådan:
DateAdd("d", 3, my_date) 'Læg tre dage til datoen
DateAdd("m", 3, my_date) 'Læg 3 måneder til datoen
DateAdd("yyyy", -3, my_date) 'Træk 3 år fra datoen
DateDiff anvender tilsvarende tekstparameter til at formatere svaret fra en subtraktion:
my_date=DateValue("19 Januar 1965")
Print DateDiff("yyyy", my_date, Date) 'Jeg er 51 år
Print DateDiff("d", my_date, Date) 'Mere præcist 18903 dage
Vi skal se dato-format problemet i to perspektiver:
1) Datoformatet i variable i makroen
2) Datoen, når den indsættes i eller læses fra en celle.
Det er vigtigt at skelne tydeligt mellem de to perspektiver, da resultatet ellers kan vise sig overraskende (forkert).
Denne artikel omhandler første punkt, nemlig håndtering og bearbejdning af datoer med makroer. Datofunktionerne er ikke afhængige af Calc, men fungerer også med datoer i f.eks. Writer.
I makroen, når vi arbejder med datoer i variable, kan vi tænk på datoer som to forskellige typer tekst: En lokaliseret (dansk, engelsk, ...) version og en international version (ISO 8601 date format). I bund og grund fungerer begge typer fuldstændig uden problemer, men lokaliseret dato er standard, og ISO 8601 (YYYY-MM-DD) er kun relevant, når vi vælger det eksplicit.
Ikke desto mindre regner LibreOffice med en intern dato-værdi, hvor 0 svarer til 29/12/1899: -1
30/12/1899: 0
31/12/1899: 1
01/01/1900: 2
01/02/1900: 3
01/01/2001: 36892
Datokonvertering:
- CDate: Konverter et tal (datoværdi) eller en tekst til en dato.
- DateValue: Konverterer en formateret tekst (i intervallet 1. december 1, 1582 til 31 December 9999) til en dato-værdi, som ikke har tidsinformationer. Datoen 1. december 1582 svarer ca. til det tidspunkt, hvor den gregorianske kalender blev indført. Se https://da.wikipedia.org/wiki/Gregorianske_kalender
- CDateFromIso: Konverterer til en dato fra en ISO 8601-dato.
- CDateToIso: Konverterer en dato til en ISO 8601-dato.
- IsDate: Er teksten korrekt formateret som dato? Brug IsDate til at afprøve om en tekst indeholder en korrekt formateret dato.
Når vi så har en dato(værdi), kan vi udlede nogle interessante informationer:
- Year(date): Returnerer årstallet af en dato som et heltal.
- Month(date): Returnerer månedsnummeret af en dato som et heltal.
- Day(date): Returnerer dagstallet af en dato som et heltal.
- WeekDay(date): Returnerer et heltal fra 1 til 7, som svarer til dage i ugen (søndag til lørdag).
Sub test
my_date=DateValue("19 Januar 1965")
Print isDate(my_date) 'True
Print my_date '19/01/1965
Print year(my_date) '1965
End sub
Funktionen DatePart gør noget lignende, nemlig udleder en konkret information
Print DatePart("yyyy",my_date) 'Årstal
Print DatePart("q",my_date) 'Kvartal
Print DatePart("m",my_date) 'Måned
Print DatePart("y",my_date) 'dag i året
Print DatePart("w",my_date) 'Ugedag
Print DatePart("d",my_date) 'Dag
DatePart splitter altså en dato ad i enkeltdele, og vi har en tilsvarende funktion til at samle delene i en dato igen:
Print DateSerial(1965, 1, 19) '19/01/1965
Vær opmærksom på at DateSerial har en fejl, som betyder at datoen før år 100 konverteres forkert, idet der lægges 1900 til årstallet:
Print DateSerial(90, 1, 19) '19/01/1990
Vi kan manipulere datoen med funktionen DateAdd sådan:
DateAdd("d", 3, my_date) 'Læg tre dage til datoen
DateAdd("m", 3, my_date) 'Læg 3 måneder til datoen
DateAdd("yyyy", -3, my_date) 'Træk 3 år fra datoen
DateDiff anvender tilsvarende tekstparameter til at formatere svaret fra en subtraktion:
my_date=DateValue("19 Januar 1965")
Print DateDiff("yyyy", my_date, Date) 'Jeg er 51 år
Print DateDiff("d", my_date, Date) 'Mere præcist 18903 dage
tirsdag den 18. oktober 2016
Sjældent brugt: Lad tekst følge en streg
Lidt ovre i DTP-afdelingen har jeg eksperimenteret lidt med at lave sjove og dekorative skrifteffekter. Fontwork-galleriet giver en række gode standardløsninger, men du har faktisk mulighed for at skrive tekst, som flyder langs en frihåndstegnet streg eller en bue.
Første trin er at tegne en streg ved hjælp af en af funktionerne Streg, Fihåndslinje, Kurve eller Polygon. Jeg vælger i dette tilfælde at tegne en simpel kurve med Kurveværktøjet.
Nu dobbeltklikker jeg på kurven og tilføjer en tekst: ”LibreOffice nyhedsbrev”. Resultatet er at teksten vises skråt (lidt tilfældigt) inde i kurven.
Marker nu kurven og vælg fra menuen Formater – Tekstboks og figur – Fontwork, hvorefter du ser en flydende dialogboks, med navnet Fontwork. Dialogen er kun synlig, når din figur er markeret.
I dialogens øverste linje kan du vælge hvordan teksten skal følge stregen.
Det er også muligt at benytte figurer som udgangspunkt for Fontwork, men det kræver lidt ekstra arbejde. Vi skal f.eks. bruge Draw i stedet for Writer.
Første udfordring for os er at værktøjet Fontwork (Fontwork-dialogen) ikke er aktiv i Draw, hvilket vi kan reparere selv. Vi skal ind i Funktioner - Tilpas og tilføje Fontwork enten til en menu eller en værktøjslinje. Du finder Fontwork i kategorien Formater. Jeg har tilføjet Fontwork til menuen Formater.
Når du er færdig kan du klippe-klistre resultatet til et Writer-dokument, eller du kan tilføje resultatet til Galleriet.
Første trin er at tegne en streg ved hjælp af en af funktionerne Streg, Fihåndslinje, Kurve eller Polygon. Jeg vælger i dette tilfælde at tegne en simpel kurve med Kurveværktøjet.
Nu dobbeltklikker jeg på kurven og tilføjer en tekst: ”LibreOffice nyhedsbrev”. Resultatet er at teksten vises skråt (lidt tilfældigt) inde i kurven.
Marker nu kurven og vælg fra menuen Formater – Tekstboks og figur – Fontwork, hvorefter du ser en flydende dialogboks, med navnet Fontwork. Dialogen er kun synlig, når din figur er markeret.
I dialogens øverste linje kan du vælge hvordan teksten skal følge stregen.
- Vælg f.eks. ikon nr. 2 fra venstre, som hedder ”Rotèr”.
- Vælg nu på anden ikonlinje det sidste (længst til højre) ikon ”Automatisk tekststørrelse”.
- På den nederste ikonlinje, klik på det første ikon ”Kontur” for at fravælge dette. Linje du tegnede er nu skjult.
- Fortsæt selv med eksperimenter, f.eks. ændre skriftfarve og tilføje tekstkontur eller slagskygge.
Det er også muligt at benytte figurer som udgangspunkt for Fontwork, men det kræver lidt ekstra arbejde. Vi skal f.eks. bruge Draw i stedet for Writer.
Første udfordring for os er at værktøjet Fontwork (Fontwork-dialogen) ikke er aktiv i Draw, hvilket vi kan reparere selv. Vi skal ind i Funktioner - Tilpas og tilføje Fontwork enten til en menu eller en værktøjslinje. Du finder Fontwork i kategorien Formater. Jeg har tilføjet Fontwork til menuen Formater.
- Opret nu en figur, f.eks. en cirkel eller lignende.
- Højreklik på cirklen og vælg Konverter - Til kurve.
- Dobbeltklik og skriv den tekst du ønsker at få vist
- Marker objektet og aktiver Fontwork-dialogen (som du placerede i en menu eller på en værktøjslinje tidligere.
- Vær kreativ!
Når du er færdig kan du klippe-klistre resultatet til et Writer-dokument, eller du kan tilføje resultatet til Galleriet.
Abonner på:
Opslag (Atom)