Wer sich schon einmal mit Datumsberechnungen beschäftigen musste (und wer musste das noch nicht...), wird sich sicherlich darüber geärgert haben, das VB keine Funktion bietet, mit der sich bewegliche Feiertage einfach (und zuverlässig...) berechnen lassen. Bedenkt man jedoch, wie viele unterschiedliche bewegliche Feiertage es international gibt, wird rasch klar, warum sich Microsoft diesbezüglich zurückgehalten hat... Das Problem jedoch bleibt: Wer z.B. "mal eben" berechnen will, wie viele Arbeitstage ein bestimmter Monat oder Zeitraum hat bzw. wissen muss, ob ein bestimmter Wochentag vielleicht gleichzeitig ein Feiertag ist, wird relativ schnell verzweifeln und mit festen Werten arbeiten, die einfach vom Kalender abgelesen werden. Ist es z.B. noch relativ einfach, die Anzahl der Tage eines Monats - unter Berücksichtigung von Schaltjahren -nach dem altbekannten "Fingerknöchelsystem" festzusetzen, hat uns leider niemand eine ähnliche Eselsbrücke beigebracht, wenn es um die Berechnung von beweglichen Feiertagen geht... Dabei ist es relativ einfach: Alle beweglichen deutschen Feiertage lassen sich sehr einfach anhand des Ostersonntags berechnen. So errechnet sich der Pfingstmontag z.B. per "Ostersonntag + 50" oder Frohnleichnahm per "Ostersonntag + 60". Wie aber ermittelt man nun den Ostersonntag? Ich musste seinerzeit ziemlich lange suchen, bis ich herausfand, auf welchen seltsamen Pfaden die Kalenderfuzzies auf dieses Datum kommen... Ich will euch nicht weiter mit Details langweilen, aber die Berechnung ist deshalb so komplex, weil sie nicht anhand des Sonnen- sondern des Mondkalenders durchgeführt wird. Die bekannte Abweichung zwischen diesen beiden Zeitsystemen führt übrigens auch zu den mitunter enormen Datumsdifferenzen zwischen den Ostersonntagen verschiedener Jahre. Ok, genug der Theorie: ' Berechnung des Ostersonntags Public Function Ostern(X As Integer) As Date Dim K As Integer Dim M As Integer Dim S As Integer Dim D As Integer Dim R As Integer Dim A As Integer Dim OG As Integer Dim SZ As Integer Dim OE As Integer Dim OSI As Integer Dim OS1 As Double Dim OS2 As String K = Int(X / 100) M = 15 + Int((3 * K + 3) / 4) - Int((8 * K + 13) / 25) S = 2 - Int((3 * K + 3) / 4) A = X Mod 19 D = (19 * A + M) Mod 30 R = Int(D / 29) + (Int(D / 28) - Int(D / 29)) * Int(A / 11) OG = 21 + D - R SZ = 7 - (X + Int(X / 4) + S) Mod 7 OE = 7 - (OG - SZ) Mod 7 OSI = ((OG + OE) - 1) OS2 = "01.03." & X OS2 = CDate(OS2) OS1 = CDate(OS2) OS1 = CDbl(OS1) OS1 = OS1 + OSI OS1 = CDate(OS1) Ostern = OS1 End Function Jetzt versteht ihr sicherlich, warum ich die Funktion nicht im Detail erkläre Was noch fehlt, sind z.B. Funktionen, die anhand des Ostersonntages die anderen beweglichen Feiertage berechnen. Eine solche Funktion könnte so aussehen: ' Ermitteln, ob Datum "x" ein Arbeitstag ist ' (Sa/So zählt nicht als Arbeitstag!) ' ' Aufruf per: ' Rückgabewert = Arbeitstag(ÜbergabeDatum) ' ' Ist der Rückgabewert = 0, handelt es sich um einen Samstag, Sonntag oder/und Feiertag ' Ist der Rückgabewert = 1, handelt es sich um einen normalen Arbeitstag Public Function Arbeitstag(X As Date) As Integer Dim Feiertage(12) As Date Dim Feiertag As String Dim Jahr As Integer Dim SaSo As Integer Dim i As Long ' Jahr aus übergebenem Datum ermitteln Jahr = CInt(Format(X, "yyyy")) ' Wochentag ermitteln SaSo = CInt(Weekday(X)) ' Arbeitstag = 1 / normaler Werktag ' Arbeitstag = 0 / Samstag, Sonntag und/oder Feiertag Arbeitstag = 1 ' Ist der Tag ein Samstag oder Sonntag ? If (SaSo = 1 Or SaSo = 7) Then ' Ja, kein Arbeitstag Arbeitstag = 0 Else ' Nein - ist der Tag ein beweglicher oder fester gesetzlicher Feiertag ? ' Bewegliche Feiertage ermitteln ' Karfreitag Feiertage(1) = (Ostern(Jahr)) - 2 ' Ostermontag Feiertage(2) = (Ostern(Jahr)) + 1 ' Pfingstmontag Feiertage(3) = (Ostern(Jahr)) + 50 ' Himmelfahrt Feiertage(4) = (Ostern(Jahr)) + 39 ' Frohnleichnam Feiertage(5) = (Ostern(Jahr)) + 60 ' Feste Feiertage ermitteln ' Neujahr Feiertage(6) = CDate("01.01." & Jahr) ' 1.Mai Feiertage(7) = CDate("01.05." & Jahr) ' Tag der deutschen Einheit Feiertage(8) = CDate("03.10." & Jahr) ' Allerheiligen Feiertage(9) = CDate("01.11." & Jahr) ' 1. Weihnachtstag Feiertage(10) = CDate("25.12." & Jahr) ' 2.Weihnachtstag Feiertage(11) = CDate("26.12." & Jahr) ' Stimmt das übergebene Datum mit einem der Feiertage überein ? For i = 1 To 11 If X = Feiertage(i) Then ' Ja, kein Arbeitstag Arbeitstag = 0 Exit For End If Next i End If End Function Jetzt wird es z.B. auch möglich, die "wahre" Anzahl der Arbeitstage eines beliebigen Monats zu errechnen. Hierzu brauchen wir noch eine weitere Funktion, welche die beiden vorangegangenen nutzt: ' Ermitteln der Arbeitstage eines Monats ' Übergeben wird ein Datum, z.B. 01.05.2005 Public Function ArbeitsTage(X As Date) As Integer Dim Monat As Integer Dim Tage As Integer Dim AT As Integer Dim Start As Date Dim Ende As Date Dim i As Long ' Tage des Monats ermitteln Monat = CInt(Format(X, "mm")) Tage = Choose(Monat, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) If Monat = 2 Then ' Speziallfall: Februar (auf Schaltjahr prüfen) Tage = Day(DateAdd("d", -1, X)) End If ' Start und Enddatum des Monats ermitteln Start = CDate("01." & Format(Monat, "00") & "." & Format(X, "yyyy")) Ende = CDate(Start) + (Tage - 1) ' Arbeitstage ermitteln For i = Start To Ende AT = AT + Arbeitstag(CDate(i)) Next i ArbeitsTage = AT End Function Wie werden die Funktionen nun genutzt? Das Datum von Ostern berechnet man nun z.B. per: Dim Ostersonntag as Date Ostersonntag = Ostern(2004) Prüfen ob ein bestimmter einzelner Tag ein Arbeitstag oder kein Arbeitstag (Sa, So oder Feiertag) ist: Dim Datum As Date Datum = "16.01.2005" If Arbeitstag(Datum) = 0 then ' Datum Ist ein Feiertag Else ' Datum ist kein Feiertag End If Und schließlich noch das Berechnen der Arbeitstage eines Monats (Datum ist ein Datum im Format dd.mm.yyyy): Dim Datum As Date Datum = "01.01.2005" MsgBox Arbeitstage(Datum) So, ich hoffe, dass euch diese Routinen bei zukünftigen Projekten helfen werden. Anwendungsgebiete (z.B. auch als Formel in Excel!!) und Erweiterungsmöglichkeiten gibt es sicherlich genug. Dieser Tipp wurde bereits 47.351 mal aufgerufen.
Anzeige
![]() ![]() ![]() (einschl. Beispielprojekt!) Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
sevISDN 1.0 ![]() Überwachung aller eingehender Anrufe! Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Tipp des Monats ![]() Dieter Otter sevTabStrip: Rechtsklick auf Reiter erkennen Eine Funktion, mit der sich prüfen lässt, auf welchen Tab-Reiter ein Mausklick erfolgte sevAniGif (VB/VBA) ![]() Anzeigen von animierten GIF-Dateien Ab sofort lassen sich auch unter VB6 und VBA (Access ab Version 2000) animierte GIF-Grafiken anzeigen und abspielen, die entweder lokal auf dem System oder auf einem Webserver gespeichert sind. |
||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |