ursprüngliche Aufgabe war, den letzten Arbeitstag eines Quartals zu errechnen. Ich habe ein bisschen weitergebastelt und der Code unten kann jetzt Folgendes: Es wird
1. nicht nur das Datum, sondern auch der Wochentag des Quartalsletzten errechnet
2. auch der nächste Quartalserste darf entsprechend mitspielen
3. werden natürlich die unvermeidlichen Hasen- und Popenparties berücksichtigt. Wobei letztere den einzig beteiligten gesetzlichen Feiertag Neujahr meint.
Code: Alles auswählen
Option Explicit
Sub WorkdaysQuartsEnd()
Dim i As Integer, sCase As String, wsf As WorksheetFunction, aDays
Dim dKey As Date, dLast As Date, dNext As Date, dEgg As Date
Dim iKey As Integer, iLast As Integer, iNext As Integer, iEgg As Integer
Dim sKey As String, sLast As String, sNext As String, sEgg As String
Set wsf = WorksheetFunction
aDays = Array("Mo", "Di", "Mi", "Do", "Fr", "Sa", "So")
dEgg = HasenParty(Year(Date))
For i = 3 To 12 Step 3
'Quartalsletzer
sKey = "01." & i & "." & Year(Date)
dKey = DateSerial(Year(sKey), Month(sKey) + 1, 1) - 1
iKey = wsf.Weekday(dKey, 2)
sKey = aDays(iKey - 1)
'Hasenfall
Select Case dKey
Case dEgg - 2, dEgg - 1, dEgg, dEgg + 1
Select Case True
Case dKey = dEgg + 1
dLast = dKey - 4: iLast = wsf.Weekday(dLast, 2): sLast = aDays(iLast - 1)
iKey = wsf.Weekday(dKey, 2): sKey = aDays(iKey - 1)
dNext = dEgg + 1: iNext = wsf.Weekday(dNext, 2): sNext = aDays(iNext - 1)
Case dKey = dEgg
dLast = dKey - 3: iLast = wsf.Weekday(dLast, 2): sLast = aDays(iLast - 1)
iKey = wsf.Weekday(dKey, 2): sKey = aDays(iKey - 1)
dNext = dEgg + 2: iNext = wsf.Weekday(dNext, 2): sNext = aDays(iNext - 1)
Case dKey = dEgg - 1
dLast = dKey - 2: iLast = wsf.Weekday(dLast, 2): sLast = aDays(iLast - 1)
iKey = wsf.Weekday(dKey, 2): sKey = aDays(iKey - 1)
dNext = dEgg + 3: iNext = wsf.Weekday(dNext, 2): sNext = aDays(iNext - 1)
Case dKey = dEgg - 2
dLast = dKey - 1: iLast = wsf.Weekday(dLast, 2): sLast = aDays(iLast - 1)
iKey = wsf.Weekday(dKey, 2): sKey = aDays(iKey - 1)
dNext = dEgg + 4: iNext = wsf.Weekday(dNext, 2): sNext = aDays(iNext - 1)
End Select
sCase = ">>> HasenParty <<<"
MsgBox "Letzter: " & vbTab & vbTab & sLast & vbTab & dLast & vbNewLine & _
"Stichtag: " & vbTab & sKey & vbTab & dKey & vbNewLine & _
"Nächster: " & vbTab & sNext & vbTab & dNext, , sCase
i = i + 3
End Select
'Normalfall -> Zurücksetzen der Variablen aus'm Hasenfall
sKey = "01." & i & "." & Year(Date)
dKey = DateSerial(Year(sKey), Month(sKey) + 1, 1) - 1
iKey = wsf.Weekday(dKey, 2)
sKey = aDays(iKey - 1)
Select Case sKey
Case "Sa"
dLast = dKey - 1: iLast = wsf.Weekday(dLast, 2): sLast = aDays(iLast - 1)
iKey = wsf.Weekday(dKey, 2): sKey = aDays(iKey - 1)
dNext = dKey + 2: iNext = wsf.Weekday(dNext, 2): sNext = aDays(iNext - 1)
Case "So"
dLast = dKey - 2: iLast = wsf.Weekday(dLast, 2): sLast = aDays(iLast - 1)
iKey = wsf.Weekday(dKey, 2): sKey = aDays(iKey - 1)
dNext = dKey + 1: iNext = wsf.Weekday(dNext, 2): sNext = aDays(iNext - 1)
Case Else
dLast = dKey: iLast = wsf.Weekday(dLast, 2): sLast = aDays(iLast - 1)
iKey = wsf.Weekday(dKey, 2): sKey = aDays(iKey - 1)
dNext = dKey + 1: iNext = wsf.Weekday(dNext, 2): sNext = aDays(iNext - 1)
End Select
sCase = ">>> Normalfall <<<"
'Popenfall
If dNext > "31.12." & Year(Date) Then
dNext = dNext + 1: sNext = aDays(iNext)
sCase = ">>> PopenParty <<<"
End If
MsgBox "Letzter: " & vbTab & vbTab & sLast & vbTab & dLast & vbNewLine & _
"Stichtag: " & vbTab & sKey & vbTab & dKey & vbNewLine & _
"Nächster: " & vbTab & sNext & vbTab & dNext, , sCase
Next i
End Sub
Public Function HasenParty(iYear As Integer) As Date
Dim a As Integer, b As Integer, c As Integer, d As Integer, e As Integer
Dim iDay As Integer, iMonth As Integer
a = iYear Mod 19: b = iYear Mod 4: c = iYear Mod 7
d = (19 * a + 24) Mod 30: e = (2 * b + 4 * c + 6 * d + 5) Mod 7
iDay = 22 + d + e: iMonth = 3
If iDay > 31 Then
iDay = d + e - 9
iMonth = 4
End If
If iDay = 26 And iMonth = 4 Then iDay = 19
If iDay = 25 And iMonth = 4 And d = 28 And e = 6 And a > 10 Then iDay = 18
HasenParty = DateSerial(Year:=iYear, Month:=iMonth, Day:=iDay)
End Function
Viel Spaß damit!
lg