Det ser umiddelbart værre ud end det i virkeligheden er ;o)
Du opretter først et nyt modul (Alt-F11, Insert, Module). Så hopper du over på den side, som jeg har lagt et link til, hvor du kopierer al koden, som du så sætter det ind i det nyoprettede modul.
Så opretter du en ny tabel, som SKAL hedde tblHolidays. I den opretter du et enkelt felt, som SKAL hedde HolidayDate, af typen Dato og klokkeslet. Du behøver som sådan ikke indtaste nogle helligdage; men du kunne jo muntre dig med at smide de helt indlysende ind.
Tilbage står bare at kalde funktionen i din forespørgsel, som er baseret på Table1. Opret et nyt felt, hvor du f.eks. skriver: AntalDage: fNetWorkdays([step3]; [step7])
Feltet [Dage] er vel overflødigt, idet forskellen jo let kan beregnes iflg. ovenstående. Hvis du af en eller anden årsag VIL gemme forskellen i [Dage], kan du jo oprette en opdateringsforespørgsel, hvor du opdaterer [Dage] til fNetWorkdays([step3]; [step7]); men pas på: hvis [step3] eller [step7] ændrer sig, vil [Dage] jo ikke vise den korrekte værdi (måske overflødig advarsel; men better safe than sorry).
Så her er lidt materiale der kan afgøre om en given dato er en helligdag. Og med lidt "lim og en saks" kan forrige kode gøre mere generel:
Helligdage
Beregning af hvor de forskydelige helligdage ligger er ikke nogen simpel opgave. Denne VBA-kode kan løse problemet. Algoritmen er imidlertid ikke specielt gennemskuelig - men den virker!
Function glrPåskedag(intYear As Integer) As Variant ' Udregner påskedag for et givet årstal ' Beregningsmetode ifl. Gauss Dim a As Integer Dim b As Integer Dim c As Integer Dim d As Integer Dim e As Integer Dim k As Integer Dim p As Integer Dim q As Integer Dim m As Integer Dim n As Integer Dim intDay As Integer Dim intMonth As Integer
k = intYear \ 100 p = (13 + 8 * k) \ 25 q = k \ 4 m = (15 - p + k - q) Mod 30 n = (4 + k - q) Mod 7 'Debug.Print k, p, q, m, n a = intYear Mod 19 b = intYear Mod 4 c = intYear Mod 7 d = (19 * a + m) Mod 30 e = (2 * b + 4 * c + 6 * d + n) Mod 7
If d + e <= 9 Then intDay = 22 + d + e intMonth = 3 ElseIf (d = 29) And (e = 6) Then intDay = 19 intMonth = 4 ElseIf (d = 28) And (e = 6) And (a > 10) Then intDay = 18 intMonth = 4 Else intDay = d + e - 9 intMonth = 4 End If glrPåskedag = DateSerial(intYear, intMonth, intDay) End Function
Function Helligdag(intYear As Integer, Helligdagstype As Integer) As Variant ' Returnerer datoen for de forskydelige helligdage. ' Helligdagstypen angives med en af de prædefinerede konstanter
Select Case Helligdagstype Case SKÆRTORSDAG Helligdag = glrPåskedag(intYear) - 3 Case LANGFREDAG Helligdag = glrPåskedag(intYear) - 2 Case PÅSKEDAG Helligdag = glrPåskedag(intYear) Case PÅSKEDAG2 Helligdag = glrPåskedag(intYear) + 1 Case BEDEDAG Helligdag = glrPåskedag(intYear) + 26 Case KRISTIHIMMELFARTSDAG Helligdag = glrPåskedag(intYear) + 39 Case PINSEDAG Helligdag = glrPåskedag(intYear) + 49 Case PINSEDAG2 Helligdag = glrPåskedag(intYear) + 50 End Select End Function
Function IsHelligdag(dtmDate As Variant) As Integer ' Returnerer TRUE hvis dtmDate er en helligdag Dim intYear As Integer Dim dtmPåskedag As Variant
Select Case dtmDate - dtmPåskedag Case -3, -2, 0, 1, 26, 39, 49, 50 IsHelligdag = True Case Else If Month(dtmDate = 1) And (Day(dtmDate) = 1) Then IsHelligdag = True ' Nytårsdag ElseIf Month(dtmDate = 12) And (Day(dtmDate) = 25) Then IsHelligdag = True ' Juledag ElseIf Month(dtmDate = 12) And (Day(dtmDate) = 26) Then IsHelligdag = True ' 2. juledag End If End Select End Function
Sub TestHelligdag(intStart As Integer, intSlut As Integer) Dim i As Integer
For i = intStart To intSlut Debug.Print i, Helligdag(i, PÅSKEDAG), Helligdag(i, BEDEDAG), Helligdag(i, KRISTIHIMMELFARTSDAG), Helligdag(i, PINSEDAG) Next i End Sub
Function TestIsHelligdag(intStart As Integer, intSlut As Integer) As Integer Dim i As Integer, j As Integer Dim result As Integer
result = True
For i = intStart To intSlut For j = SKÆRTORSDAG To PINSEDAG result = result And IsHelligdag(Helligdag(i, j)) 'If Not result Then Debug.Print i, j, Helligdag(i, j), IsHelligdag(Helligdag(i, j)) Next j Next i TestIsHelligdag = result End Function
Sub TestPåske(intStart As Integer, intSlut As Integer) 'Udskriver datoen for påskedag for alle år i et givent interval Dim i As Integer
For i = intStart To intSlut Debug.Print i, glrPåskedag(i) Next i End Sub
Skrevet af Stephen Biering-Sørensen, DTI Center for IT, tlf. 8943 8460.
Alt skal indsættes i et modul (se i tidligere besvarelse, hvordan dette sker).
I din forespørgsel skriver du derefter:
SELECT WorkingDays(table1.Step3;table1.Step7)
**********************************************
Public Function WorkingDays(datStart As Date, datSlut As Date) As Long
Dim intDays As Integer, l As Integer Dim datNew As Date
If datStart > datSlut Then WorkingDays = 0 Exit Function End If
intDays = DateDiff("d", datStart, datSlut, vbMonday, vbFirstFourDays) datNew = datStart For l = 0 To intDays datNew = DateAdd("d", l, datStart) If (IsBankHoliday(CLng(datNew), True, True) = True) Or (Weekday(datNew, vbMonday) > 5) Then intDays = intDays - 1 Next l If intDays < 0 Then intDays = 0 WorkingDays = intDays
End Function
Function IsBankHoliday(testDato As Long, InclSaturdays As Boolean, InclSundays As Boolean) As Boolean Dim InputYear As Integer, PD As Long, OK As Boolean If testDato <= 0 Then testDato = Date InputYear = Year(testDato) PD = EasterDay(InputYear) OK = True Select Case testDato Case DateSerial(InputYear, 1, 1) ' New Years Day Case PD - 7 ' Palm sunday Case PD - 3 ' Holy Thursday Case PD - 2 ' Good Friday Case PD ' Easterday Case PD + 1 ' Easter monday Case PD + 26 ' Prayer Day Case PD + 39 ' Ascension day Case PD + 49 ' Whit Case PD + 50 ' Whit monday Case DateSerial(InputYear, 12, 24) ' Christmas Eve Case DateSerial(InputYear, 12, 25) ' Christmas day Case DateSerial(InputYear, 12, 26) ' 2. Christmas day Case DateSerial(InputYear, 12, 31) ' New years eve Case Else OK = False
'****Below is indented for the current use of calculation workingdays. Can be activated for other purposes ' If InclSaturdays Then ' If Weekday(testDato, vbMonday) = 6 Then ' OK = True ' End If ' End If ' If InclSundays Then ' If Weekday(testDato, vbMonday) = 7 Then ' OK = True ' End If ' End If End Select IsBankHoliday = OK End Function
Function EasterDay(InputYear As Integer) As Long Dim d As Integer d = (((255 - 11 * (InputYear Mod 19)) - 21) Mod 30) + 21 EasterDay = DateSerial(InputYear, 3, 1) + d + (d > 48) + 6 - ((InputYear + InputYear \ 4 + d + (d > 48) + 1) Mod 7) End Function
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.