Avatar billede hnto Nybegynder
18. maj 2011 - 14:06 Der er 7 kommentarer og
1 løsning

datediff funktion minus weekend... haster gerne !

jeg bruger en datediff i en forespørgsel:

Expr1: DateDiff("d";[DateStep3];[DateStep7];2;1)

hvordan tilføjer man at den ikke skal medregne weekend (dag 7 og 1)
Avatar billede fdata Forsker
18. maj 2011 - 20:21 #1
Avatar billede hnto Nybegynder
19. maj 2011 - 08:50 #2
ville det være muligt for en guru som dig at tilrette koden så den passer direkte ind i min DB ud fra:

tabellen hedder table1
startdato feltet hedder [step3]
slutdatofeltet hedder [step7]
feltet til antal dage hedder [dage]

jeg kommer ikke i mål hvis jeg selv skal kage rundt i den kode, da jeg ikke er så skarp i VBA :-)
Avatar billede hnto Nybegynder
19. maj 2011 - 08:56 #3
det skal lige siges at jeg ej heller har en tabel med helligdage :-)
Avatar billede hnto Nybegynder
19. maj 2011 - 13:28 #4
er der virkelig ingen eksperter der kan knække denne ? :-)
Avatar billede fdata Forsker
21. maj 2011 - 22:57 #5
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).
Avatar billede sifuentes Nybegynder
22. maj 2011 - 12:57 #6
Og hvad så næste år?

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!

Const SKÆRTORSDAG = 1
Const LANGFREDAG = 2
Const PÅSKEDAG = 3
Const PÅSKEDAG2 = 4 ' 2. påskedag
Const BEDEDAG = 5
Const KRISTIHIMMELFARTSDAG = 6
Const PINSEDAG = 7
Const PINSEDAG2 = 8 ' 2. pinsedag

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

    intYear = Year(dtmDate)
    dtmPåskedag = glrPåskedag(intYear)

    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.
Avatar billede nhoff Nybegynder
24. maj 2011 - 14:16 #7
Et andet forslag til en kode følger nedenfor.

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
Avatar billede fdata Forsker
24. juni 2011 - 13:36 #8
Takker for point ;O)
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Dyk ned i databasernes verden på et af vores praksisnære Access-kurser

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester