🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA Weekday & DatePart dans Excel — extraire les parties d'une date, et pourquoi lundi n'est pas 1

|

VBA Weekday & DatePart dans Excel — extraire les parties d'une date, et pourquoi lundi n'est pas 1

TL;DRYear(d), Month(d), Day(d), Hour(t), Minute(t), Second(t) renvoient chacun un entier tiré d'une date — simple et sans ambiguïté. Weekday(d) est le piège : il renvoie 1 à 7, mais la numérotation dépend d'un second argument qui vaut vbSunday (1) par défaut, si bien que par défaut lundi vaut 2, pas 1. Passez vbMonday (ou comparez aux constantes vb*) et la logique de week-end cesse d'être discrètement fausse.

Sub PartsDemo()
    Dim d As Date: d = #2026-08-26#        ' un mercredi
    Debug.Print Year(d), Month(d), Day(d)  ' 2026  8  26
    Debug.Print Weekday(d)                 ' 4  - dimanche=1 par defaut, donc mer=4
    Debug.Print Weekday(d, vbMonday)       ' 3  - lundi=1, donc mer=3
    Debug.Print DatePart("ww", d)          ' 35 - numero de semaine (pas de fonction dediee)
End Sub

Extraire les parties, c'est l'inverse de construire une date à partir de ses éléments : vous avez le Double, et vous voulez l'année, le mois, le jour de la semaine. La plupart de ces fonctions sont aussi ennuyeuses qu'elles devraient l'être — Year, Month, Day ne font que lire le nombre. Weekday est celle qui a mis fin à plus de macros qu'elle ne le devrait, entièrement à cause d'une valeur par défaut que personne ne retient.

Ce que vous allez apprendre

  • Les extracteurs simples — Year, Month, Day, Hour, Minute, Second — un entier chacun
  • Pourquoi Weekday renvoie 2 pour lundi par défaut, et l'unique argument qui corrige cela
  • Comment écrire des tests de week-end et de jour ouvré qui ne sont pas secrètement faux
  • DatePart — l'extracteur général qui atteint le numéro de semaine et le trimestre
  • Pourquoi les numéros de semaine de DatePart("ww", …) peuvent être décalés d'un à la limite de l'année (ISO 8601)
  • WeekdayName et MonthName renvoient des noms localisés — pour l'affichage, pas pour l'analyse

Les extracteurs simples : un entier chacun

Year, Month et Day découpent une date en ses composantes calendaires ; Hour, Minute et Second découpent la fraction horaire. Chacun renvoie un simple Integer, et il n'y a rien qui accroche :

Dim d As Date: d = Now                 ' 2026-08-26 14:30:07
Debug.Print Year(d)      ' 2026
Debug.Print Month(d)     ' 8   (un nombre 1-12, pas le nom)
Debug.Print Day(d)       ' 26
Debug.Print Hour(d)      ' 14  (24 heures)
Debug.Print Minute(d)    ' 30
Debug.Print Second(d)    ' 7

Month renvoie 8, pas "August" — c'est un nombre. Ce sont les briques que vous réinjectez dans DateSerial pour construire des dates liées (le premier du mois, le même jour l'an prochain, et ainsi de suite). Aucune surprise ici — et c'est justement pour cela que Weekday prend les gens au dépourvu.

Pourquoi Weekday renvoie 2 pour lundi

Weekday(date, [firstDayOfWeek]) renvoie un nombre de 1 à 7 — mais quel jour vaut 1 est fixé par le second argument, et quand vous l'omettez VBA prend vbSunday, donc dimanche = 1 et lundi = 2 :

Weekday(#2026-08-24#)             ' 2  - ce lundi-la, car dimanche=1 par defaut
Weekday(#2026-08-24#, vbMonday)   ' 1  - maintenant lundi=1 ... dimanche=7

C'est le bug vedette de toute la famille. Un code comme If Weekday(d) = 1 Then ' lundi est faux — 1 c'est dimanche dans un appel par défaut — et un code comme If Weekday(d) = 6 Or Weekday(d) = 7 Then ' week-end dépend entièrement d'une hypothèse sur le premier jour, invisible au point d'appel. Il y a deux correctifs robustes, et les deux suppriment la devinette :

' Correctif 1 - fixez le premier jour explicitement, alors lundi vaut vraiment 1 :
If Weekday(d, vbMonday) >= 6 Then MsgBox "weekend"   ' 6 = sam, 7 = dim

' Correctif 2 - comparez aux constantes nommees, jamais des nombres magiques :
If Weekday(d) = vbSaturday Or Weekday(d) = vbSunday Then MsgBox "weekend"

Les constantes vb* (vbSunday, vbMonday, … vbSaturday) sont correctes quel que soit l'argument du premier jour, et c'est pourquoi les comparer est l'habitude la plus sûre. La règle : n'écrivez jamais un nombre nu pour un jour de la semaine — soit vous passez vbMonday pour que la numérotation soit celle que vous attendez, soit vous comparez à une constante vb*.

DatePart : l'extracteur général

DatePart(interval, date, [firstDayOfWeek], [firstWeekOfYear]) est la version couteau suisse : il prend les mêmes codes d'intervalle que DateAdd et DateDiff et en extrait l'unité. Pour l'année, le mois, le jour et l'heure, il fait doublon avec les fonctions dédiées — mais c'est le seul moyen intégré d'atteindre deux parties qui n'ont pas de fonction propre :

DatePart("q", d)     ' trimestre de l'annee (1-4) - aucune fonction Quarter() n'existe
DatePart("ww", d)    ' numero de semaine de l'annee (1-53)
DatePart("y", d)     ' jour de l'annee (1-366) - le "y" qui veut dire jour-de-l'annee
DatePart("m", d)     ' 8 - identique a Month(d)

Recourez à DatePart quand vous avez besoin du trimestre ou du numéro de semaine, et utilisez les fonctions Year / Month / Day pour les parties courantes car elles se lisent plus clairement. Notez le même piège de code que dans DateAdd : "y" c'est le jour de l'année et "ww" la semaine — dites-les à voix haute une fois.

Le piège du numéro de semaine à la limite de l'année

DatePart("ww", …) a sa propre valeur par défaut qui surprend : la première semaine de l'année et le premier jour de la semaine valent tous deux une règle à l'américaine (vbSunday, vbFirstJan1), qui n'est pas ISO 8601 — la norme qu'utilisent la majeure partie de l'Europe et la plupart des calendriers d'entreprise. Ainsi, les derniers jours de décembre et les premiers de janvier peuvent tomber dans un numéro de semaine inattendu :

DatePart("ww", #2026-12-31#)                          ' 53  (regle US par defaut)
DatePart("ww", #2026-12-31#, vbMonday, vbFirstFourDays) ' la reponse facon ISO

Si vos numéros de semaine comptent — semaines de paie, numéros de sprint, tout ce qui doit concorder avec un calendrier au mur — passez vbMonday comme premier jour de la semaine et vbFirstFourDays comme règle de première semaine pour coller à l'ISO 8601. Le classique « mes numéros de semaine sont décalés d'un autour du Nouvel An » vient toujours de ces deux valeurs par défaut.

WeekdayName et MonthName sont localisés

Pour transformer un numéro de jour ou de mois en nom, utilisez WeekdayName et MonthName. Tous deux renvoient le nom dans la langue de la machine, ce qui les rend parfaits pour l'affichage et néfastes pour tout ce que vous analysez ensuite :

WeekdayName(2)              ' "Monday" sur une machine anglaise, "Montag" sur une allemande
MonthName(8)               ' "August" / "August" / "aout" selon les parametres regionaux
WeekdayName(2, True)       ' abrege : "Mon"

Parce que la sortie suit les paramètres régionaux de l'utilisateur, ne la comparez jamais à une chaîne anglaise fixe et ne l'écrivez pas dans un fichier qu'un autre système lira — c'est un bug de localisation en germe. Pour un libellé stable que vous maîtrisez, formatez plutôt la date : Format(d, "dddd") donne le nom complet du jour et Format(d, "mmmm") le nom du mois, toujours sensibles aux paramètres régionaux mais explicites, via Format. Utilisez WeekdayName / MonthName pour l'affichage à l'écran ; utilisez des nombres (Weekday, Month) pour la logique.

Le verdict honnête : les parties sont faciles, les valeurs par défaut non

Extraire les parties d'une date est la chose la moins mystérieuse des dates VBA — avec un astérisque qui cause une part démesurée des bugs :

  • Parties simples, fonctions simplesYear, Month, Day, Hour, Minute, Second. Chacune renvoie un entier ; Month est un nombre, pas un nom.
  • Weekday a une valeur par défaut cachée → c'est vbSunday, donc lundi vaut 2. Passez vbMonday, ou comparez à vbSaturday / vbSunday — jamais un nombre nu.
  • DatePart pour ce qui n'a pas de fonction → le trimestre ("q") et le numéro de semaine ("ww") ; alignez les semaines ISO avec vbMonday + vbFirstFourDays.
  • Les noms sont localisésWeekdayName / MonthName suivent la langue de la machine ; servez-vous-en pour afficher, jamais pour analyser.

L'unique habitude qui prévient le plus de bugs : un numéro de jour de la semaine ne devrait jamais être un littéral. Dites quel jour vient en premier, ou nommez le jour que vous visez.

Comment ExcelMaster aide

Les bugs d'extraction de parties sont sournois parce que le code a l'air manifestement juste : un filtre de week-end qui teste Weekday = 1, une colonne de numéro de semaine qui contredit le calendrier de paie chaque janvier, un rapport qui écrit WeekdayName dans un fichier qu'un système d'une autre langue ne parvient ensuite pas à relire. Chacun est une valeur par défaut que personne n'a retenue.

ExcelMaster écrit l'extraction juste du premier coup. Décrivez la règle — « ignore les week-ends », « regroupe les lignes par trimestre », « étiquette chaque ligne avec sa semaine ISO » — et il utilise Weekday(d, vbMonday) ou les constantes vb* pour la logique de jour de la semaine, DatePart avec les arguments ISO pour les numéros de semaine, et garde les noms d'affichage séparés des nombres sur lesquels vous branchez. Vous décrivez la règle calendaire ; il écrit l'extraction de parties qui ne repose pas sur une valeur par défaut cachée.

Questions fréquentes

Pourquoi Weekday renvoie-t-il le mauvais numéro de jour en VBA ?

Parce que Weekday numérote la semaine à partir de son second argument, qui vaut vbSunday par défaut — donc dimanche vaut 1 et lundi 2. Si vous supposiez que lundi vaut 1, chaque résultat est décalé d'un. Passez le premier jour explicitement, Weekday(d, vbMonday), pour que lundi soit 1 jusqu'à dimanche 7, ou comparez le résultat aux constantes nommées vbSaturday et vbSunday plutôt qu'à des nombres codés en dur.

Comment vérifier qu'une date est un week-end en VBA ?

Utilisez les constantes pour que la valeur par défaut du premier jour ne puisse pas vous piéger : If Weekday(d) = vbSaturday Or Weekday(d) = vbSunday Then …. Les constantes vb* sont correctes quel que soit l'argument de premier jour de la semaine en jeu. Autrement, Weekday(d, vbMonday) >= 6 traite 6 (samedi) et 7 (dimanche) comme le week-end — assurez-vous simplement d'avoir passé vbMonday.

Comment obtenir le trimestre ou le numéro de semaine d'une date en VBA ?

Utilisez DatePart, car il n'existe pas de fonction Quarter ni Week dédiée. DatePart("q", d) renvoie le trimestre de 1 à 4, et DatePart("ww", d) renvoie le numéro de semaine. Pour des numéros de semaine ISO 8601, passez les arguments supplémentaires : DatePart("ww", d, vbMonday, vbFirstFourDays), sinon la semaine autour du Nouvel An peut être décalée d'un.

Quelle est la différence entre Month et MonthName en VBA ?

Month(d) renvoie le mois sous forme de nombre (1 à 12) pour la logique ; MonthName(n) transforme un numéro de mois en son nom sous forme de texte (MonthName(8) donne « August »). MonthName suit la langue de la machine, alors ne l'utilisez que pour l'affichage — pour brancher ou comparer, servez-vous du nombre issu de Month.

WeekdayName renvoie-t-il des noms anglais en VBA ?

Seulement sur une machine en anglais. WeekdayName et MonthName renvoient les noms dans les paramètres régionaux du système, si bien que le même code produit « Monday », « Montag » ou « lundi » selon les machines. Ne comparez jamais leur sortie à une chaîne anglaise fixe ; pour un libellé maîtrisé, utilisez Format(d, "dddd"), et pour la logique, le Weekday numérique.

Testé dans

Testé dans : Excel 365 (Windows 11), VBA 7.1 — vérifié le 26/08/2026.

Guides connexes : VBA DateAdd & DateDiff · VBA Now, Date & Time · VBA Format · VBA CStr, CDate & Val · Boucle For VBA