tiistai 27. tammikuuta 2009

Miksi Excel laskee viikon numeron väärin?

Excelissä on funktio, joka laskee päivämäärän perusteella viikon numeron: VIIKKO.NRO (WEEKNUM). Sen valinnaisena argumenttina oleva palauta_tyyppi (Return_type) sallii viikon alkamispäivän valinnan: Kun argumentti on 1 tai puuttuu, viikon oletetaan alkavan sunnuntaista. Argumentin ollessa 2 viikko katsotaan alkavaksi maanantaista. Jälkimmäinenhän on se tapa, jota pääasiassa noudatetaan meillä myytävissä kalentereissa. Ensiriemastuksen jälkeen kuitenkin käy ilmi, että funktio tekee virheitä molempia argumentteja käytettäessä!

Selitys löytyy eurooppalaisesta ISO 8601 -standardista, jota ei ole huomioitu Excelin VIIKKO.NRO-funktiossa. ISO 8601 -standardin mukaisesti viikko alkaa maanantaista ja päättyy sunnuntaihin. Tämän luulisi hoituvan argumentilla 2, mutta on muutakin: Eurooppalaisen standardin mukaisesti vuoden ensimmäisessä viikossa on oltava vähintään 4 päivää. Näin viikko numero 1 on se viikko, jolle vuoden ensimmäinen torstai tai tammikuun 4. päivä sijoittuvat. Jos 1.1. on perjantai, lauantai tai sunnuntai, kyseinen viikko saa numeron 52 tai 53.

ISO 8601 -standardista johtuvan virheen korjaa kaava, jonka löysin keväällä 2006 Pearson Software Consulting LLC:n verkkosivulta:

=1+INT((A2-DATE(YEAR(A2+4-WEEKDAY(A2+6));1;5)+WEEKDAY(DATE(YEAR(A2+4-WEEKDAY(A2+6));1;3)))/7)

Ja suomenkielisessä Excelissä näin:

=1+KOKONAISLUKU((A2-PÄIVÄYS(VUOSI(A2+4-VIIKONPÄIVÄ(A2+6));1;5)+VIIKONPÄIVÄ(PÄIVÄYS(VUOSI(A2+4-VIIKONPÄIVÄ(A2+6));1;3)))/7)

Helpoimmalla tietysti pääset kun kopioit käyttämäsi kieliversion mukaisen litanian kaavariville ja kopioit kaavan alaspäin niin moneen soluun, kuin tarvitaan.

Kuvassa B-sarakkeessa oleva viikon numero on katsottu kalenterista. Sarakkeessa C se on laskettu VIIKKO.NRO-funktion argumentilla 1, sarakkeessa D argumentilla 2 ja sarakkeessa E kaavalla.


Tallennus omaksi funktioksi

VBA-ohjelmoinnista kiinnostunut ehkä haluaisi lisätä tämän omaan funktiokokoelmaansa ja Pearson Softwaren sivulta löytyykin valmis VBA-listaus. Lisäksi MSDN-artikkelissa Implementing Week-Numbering Systems and Date/Time Representations in Excel on muun viikon numerointia koskevan tiedon ohella lyhyempi VBA-listaus, jonka pohjalta kirjoittamaani ViikkoNro8601-funktiota olen käyttänyt yllä olevan kuvan mukaisen taulukon sarakkeessa F:

Public Function ViikkoNro8601(Paivays As Date) As Integer

Dim Paivays2 As Long

Paivays2 = DateSerial(Year(Paivays - Weekday(Paivays - 1) + 4), 1, 3)

ViikkoNro8601 = Int((Paivays - Paivays2 + Weekday(Paivays2) + 5) / 7)

End Function


Lisätietoja ISO 8601 -standardista

ISO 8601 -standardista löytyy lisätietoja tietenkin googlettamalla sekä yksityiskohtaisemmin Jukka Korpelan artikkelista Info on ISO 8601, the date and time representation standard. Suomeksi kirjoitettu Juha Auteron ja Antti-Juhani Kaijanahon artikkeli Vastauksia tietokoneohjelmoinnista usein esitettyihin kysymyksiin sisältää mm. tietoa ISO 8601 -standardista, mutta myös paljon muuta numeroihin ja tietokoneohjelmointiin liittyvää asiaa.

2 kommenttia:

Don Aberione kirjoitti...

Tämä Viikko.nro hässäkkä oli näköjään mennyt väärin omissa taulukoissa. Hauska huomata vanhoista taulukoista ettei viikot olekaan menneet oikein sitten tänä vuonna. Vastahan tässä neljä kuukautta on mennyt.

Outi kirjoitti...

No, neljä kk on vasta vähemmän kuin puolet vuodesta :)