Kalenderwoche nach ISO bzw. DIN

In Excelver­sio­nen ab 2007 ist es ja recht ein­fach, die Kalen­der­woche nach ISO 8601 bzw. DIN EN 28601 (1993) zu berech­nen: =KALENDERWOCHE(Datum; 21) und das Ergeb­nis stimmt. In VBA lässt sich mit­tels Works­heet­Func­tion.Wee­k­Num(Da­tum, 21) ein kor­rek­tes Ergeb­nis berech­nen.

An­ders sieht das aber bei den Ver­sio­nen bis 2003 aus. Da gibt es noch nicht die „21” als Über­gabepa­ra­me­ter. Da­durch kann dur­chaus ein fehler­haftes Ergeb­nis aus­gegeben wer­den. Als Ex­cel-For­mel bie­tet sich solch eine Lö­sung an, wenn in A1 das Da­tum ste­ht:
=KÜRZEN((A1-DATUM(JAHR(A1+3-REST(A1-2; 7)); 1; REST(A1-2; 7)-9))/7)
Quel­le: Ex­cel­for­meln).

Eine Lö­sung per VBA gibt es natür­lich auch. Sog­ar di­ver­se Möglichkeit­en. Mir ge­fällt ge­fiel die­se (bis heu­te) am bes­ten:

Function KW_ISO(Datum)
   KW_ISO = DatePart("ww", Datum, vbMonday, vbFirstFourDays)
   'oder in (nicht besser lesbarer) Kurzform
   'KW_ISO = DatePart("ww", Datum, 2, 2)
End Function

Das Argu­ment Da­tum muss ein kalen­darisches Da­tum sein oder in ir­gend ein­er Form in ein solch­es umge­wan­delt wer­den kön­nen. Die Rück­gabe ist der nu­me­ri­sche Wert der Kalen­der­woche.

Hin­weis: Ein acht­samer Tüft­ler und Le­ser die­ses Fo­rums hat fest­gestellt, dass die vor­ge­nan­nte UDF KW_I­SO(Da­tum) in bes­timmten Fäl­len und für mich bis­lang nicht nachvol­lziehbaren Grün­den fal­sche Ergeb­nisse „pro­duziert”.  Dan­ke Jörg! (Der vol­le Name und die E‑Mail lie­gen mir vor.) Ich habe die kalen­darischen Dat­en vom 01.03.1900 (der Tag nach dem nur in Win­dows-Excel existieren­den 29.02.1900) bis heu­te (14.01.2021) mit ein­er klei­nen von Jörg erstell­ten VBA-Proze­dur ge­checkt und fol­gende kalen­darische Dat­en sind sind in Sa­chen DIN-Kalen­der­woche falsch berech­net wor­den:

Datum seriell Dif­ferenz
30.12.1907 2921  
29.12.1919 7303 4382
31.12.1923 8766 1463
30.12.1935 13148 4382
29.12.1947 17530 4382
31.12.1951 18993 1463
30.12.1963 23375 4382
29.12.1975 27757 4382
31.12.1979 29220 1463
30.12.1991 33602 4382
29.12.2003 37984 4382
31.12.2007 39447 1463
30.12.2019 43829 4382

Ich habe zusät­zlich zu den kalen­darischen Wer­ten noch die dazu pas­sen­de se­ri­el­le Zahl in di zwei­te Spal­te ge­schrie­ben und die Dif­ferenz in Ta­gen in der drit­ten Spal­te berech­nen las­sen. So ist eine ge­wis­se Rhyth­mik er­kenn­bar, wel­che ich aber der­zeit nicht ana­ly­sie­ren kann.

Für mich ist die­se UDF we­gen der nicgt durch­gän­gig kor­rek­ten Ergeb­nisse nicht ein­set­zbar, auch wenn es nur 3,178 Pro­mil­le Falschergeb­nisse sind. Ich hal­te es da wie beim Aut­o­fahren: nur 0,00‰ sind okay und über 3,1 ‰ kön­nen töd­lich sein. 💡  – Ich habe eben noch ein­mal in der Microsoft-Hil­fe zur Funk­tion DatePart() nachge­se­hen und fest­gestellt, dass MS die­sen Feh­ler auch schon erkan­nt hat und di­rekt zu Be­ginn eine ent­spre­chen­de War­nung einge­fügt hat  – Mein Tipp: Die­se Funk­tion und ent­spre­chend auch die von mir vor­ge­stell­te UDF nicht ver­wen­den. Alter­na­tiv kön­nte über eine WENN()-Funk­tion der Ergeb­niswert bei den betrof­fe­nen kalen­darischen Dat­en (sie­he Ta­bel­le oben) der Rück­gabe­w­ert an­ge­passt wer­den.

Alter­na­tiv mit Jah­res­zahl

Soll die Funk­tion option­al eine Jah­res­zahl mit aus­geben, dann wird beispiel­sweise solch ein Code eher hil­fre­ich sein:

 Function KW_ISO(Datum, Optional Jahr As Boolean = False)
   Dim Rc As Variant, J As Integer
   
   Rc = DatePart("ww", Datum, vbMonday, vbFirstFourDays)
   'Alternativ immer 2 - stellig:
   'Rc = Format(DatePart("ww", Datum, vbMonday, vbFirstFourDays), "00")
   J = Year(Datum)
   If Jahr Then
      If Month(Datum) = 1 And Rc > 10 Then J = J - 1
      Rc = Rc & "/" & J
   End If
   KW_ISO = Rc
End Function

Sie kön­nen als zwei­tes Argu­ment entwed­er 0 bzw. 1 ein­ge­ben, was ei­nem FALSCH bzw. WAHR ent­spricht. 0, FALSCH oder kei­ne An­ga­be sor­gen da­für, dass kei­ne Jah­res­zahl aus­gegeben wird, bei 1 oder WAHR wird die Jah­res­zahl des zur KW pas­sen­den Jah­res aus­gegeben. Das wür­de beispiel­sweise am 1. Jan­u­ar 2017 be­deu­ten: 522016, weil es die 52. KW des Jah­res 2016 ist, in welch­er der ers­te Tag des Da­tums liegt. Die Rück­gabe ist na­tur­ge­mäß ein String / Text.

Falls Sie Hil­fe bein Ein­binden der Be­nut­zer­de­fi­nier­ten Funk­tion brau­chen, schau­en Sie ein­fach hier im Blog nach.

▲ nach oben …

Hat Ih­nen der Bei­trag ge­fal­len?
Er­leich­tert die­ser Bei­trag Ihre Ar­beit?

Dann wür­de ich mich über ei­nen Bei­trag Ihrer­seits z.B. 2,00  freu­en … (← Klick mich!)

Dieser Beitrag wurde unter Code-Schnipsel, Datum und Zeit, Mit VBA/Makro, Ohne Makro/VBA, Tipps und Tricks veröffentlicht. Setze ein Lesezeichen auf den Permalink.