OVH Cloud OVH Cloud

Weekday, bug si 1904

17 réponses
Avatar
Michel Gaboly
Bonjour,

Je viens de découvrir un bug lié aux options de classeur 1900/1904 ;-((

Je viens de l'évoquer dans un message précédent.

La fonction Weekday, native en VBA, pas celle de la feuille de calcul, JOURSEM()
renvoie un résultat erronné si dans les options de classeur, "Calendrier depuis
1904" est coché, ce qui est l'option par défaut dans les versions Mac d'Excel et
pas dans les versions Windows.

Weekday(Range("Réf")) renvoie le numéro d'un jour donné dans la semaine :
par défaut, 1 pour le dimanche, 2 pour le lundi, ...

Pour avoir une semaine commençant le lundi, il faut utiliser un second argument,
facultatif, et lui donner 2 comme valeur : Weekday(Range("Réf"), 2).

Tout va bien si le classeur est basé sur le calendrier 1900, mais s'il est basé sur
1904, on récupère la valeur attendue + 1 ;-((


L'explication est probablement la suivante : Excel considère les dates comme une
série de nombres, où une unité représente 24 heures.

Avec l'option 1900, les jours sont numérotés depuis début 1900, et le lundi 1er
décembre correspond au nombre (ou numéro de série) 37956.

Avec l'option 1904, cette même date est représentée par 36494. Il y a un écart
de1462 jours entre les 2 séries, soit 208 semaines et 6 jours.

Plus de détails ici : http://minilien.com/?WCiYNb8JqU

En ce qui concerne le numéro de jour dans la semaine, peu importent les 208
semaines d'écart ; seuls comptent les 6 jours. Par ailleurs - 6jours, c'est équi-
valent à + 1 jour (7 jours d'écart entre les 2, donc même jour de la semaine.

Il est probable que la fonction Weekday est basée sur la série de nombre associée
à l'option 1900. Dans un classeur basé sur 1904, c'est comme si la même date
était située 6 jours avant, ou, nous l'avons vu, le lendemain, ce qui expliquerait
le résultat obtenu, + 1 par rapport au résultat attendu.

Pour corriger cette anomalie, il faut donc retrancher 1 au résultat si le classeur
est basé sur 1904.

La propriété "Date1904" de l'objet "WorkBook" renvoie True si le classeur est
basé sur 1904, False, sinon.

Par ailleurs VBA interprête True comme égal à -1 et False comme égal à 0. Voici
donc une solution (la cellule active doit contenir une date) :

Private Sub Worksheet_Calculate()
Dim Delta As Integer
Delta = ThisWorkbook.Date1904
MsgBox WeekDay(ActiveCell, 2) + Delta)
End Sub

Le résultat sera correct dans tous les cas, grâce à la variable "Delta" qui permet de
retrancher 1 si nécessaire.


--
Cordialement,

Michel Gaboly
http://www.gaboly.com

7 réponses

1 2
Avatar
Daniel.M
Salut Isabelle,

justement la formule qui a été proposé ne fait pas disparaitre la
colonne contenant les dates, alors messieurs vous voulez bien
messeuplipliquer le fondement de se débat face à la question initiale,
juste question de remettre du chimblick :-))

isabelle


Quel est cet utilitarisme débridé? Et pourquoi faudrait-il toujours aider les
gens? ;-)
Pas le droit d'avoir une saine discussion ici? ;-))

AMA, l'observation de Michel et l'explication (comment VBA traite les nombres
selon qu'ils sont formatés en date ou non et les impacts pour un calendrier
1904) valent bien une ficelle. :-)

Quant à la question initiale, il y a plusieurs manières de la résoudre, des
solutions ont déjà été proposées (pour autant que le requérant accepte de mettre
de l'eau dans son vin).

Salutations,

Daniel M.

Avatar
AV
.........(pour autant que le requérant accepte de mettre
de l'eau dans son vin).


Si j'étais lui, je refuserais Absolument !
Pfff......... quelle hérésie !
C'est pas du sirop d'érable le vin (le Bordeaux bien sur...) !

;-)
AV

Avatar
Michel Gaboly
Bonjour Isabelle

J'avais proposé 2 solutions, l'une comparable à la tienne, et l'autre qui
tentait d'offrir au demandeur, comme dit Daniel, le beurre et l'argent
du beurre ;-))

Il s'agissait d'avoir dans les mêmes cellules à la fois le formatage et les
dates.

Puisque tu veux "remettre du chimblick :-))", je t'envoie 2 fichiers
exemples.

Je ne sais pas si l'adresse du trombinoscope est à jour. Si oui cela ne
devrait pas tarder.



Rebonsoir,
Mais la demande initiale ne l'était pas non plus ; je ne sais pas si tu as suivi le
fil initial; il s'agissait de quelqu'un qui avait une version d'Excel en anglais,
mais voulait pouvoir afficher le jour de semaine sous la forme "Lu", "Ma", ...
TOUT EN VOULANT pouvoir continuer à faire des calculs de dates sur le contenu
des cellules.


justement la formule qui a été proposé ne fait pas disparaitre la
colonne contenant les dates, alors messieurs vous voulez bien
messeuplipliquer le fondement de se débat face à la question initiale,
juste question de remettre du chimblick :-))

isabelle


Bonne journée,

--
Cordialement,

Michel Gaboly
http://www.gaboly.com


Avatar
isabelle
bonjour Michel,

pour suivre à la lettre les informations donnée dans l'aide
1 Dimanche
2 Lundi
3 Mardi
4 Mercredi
5 Jeudi
6 Vendredi
7 Samedi

il faudrait peut être mieux modifier comme ça,

Private Sub Worksheet_Calculate()
Dim c As Range, Mat
Mat = Array("Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa")
For Each c In Range("Dates")
c.NumberFormat = """" &
Application.WorksheetFunction.Index(Mat, WeekDay(c, 2)) & """"
c.Offset(1) = WeekDay(c, 2)
c.Offset(2) = WeekDay(c, 2) + ThisWorkbook.Date1904
c.Offset(3) = CDate(c)
Next c
End Sub

isabelle


Bonjour Isabelle

J'avais proposé 2 solutions, l'une comparable à la tienne, et l'autre qui
tentait d'offrir au demandeur, comme dit Daniel, le beurre et l'argent
du beurre ;-))

Il s'agissait d'avoir dans les mêmes cellules à la fois le formatage et les
dates.

Puisque tu veux "remettre du chimblick :-))", je t'envoie 2 fichiers
exemples.

Je ne sais pas si l'adresse du trombinoscope est à jour. Si oui cela ne
devrait pas tarder.



Rebonsoir,
Mais la demande initiale ne l'était pas non plus ; je ne sais pas si tu as suivi le
fil initial; il s'agissait de quelqu'un qui avait une version d'Excel en anglais,
mais voulait pouvoir afficher le jour de semaine sous la forme "Lu", "Ma", ...
TOUT EN VOULANT pouvoir continuer à faire des calculs de dates sur le contenu
des cellules.


justement la formule qui a été proposé ne fait pas disparaitre la
colonne contenant les dates, alors messieurs vous voulez bien
messeuplipliquer le fondement de se débat face à la question initiale,
juste question de remettre du chimblick :-))

isabelle


Bonne journée,

--
Cordialement,

Michel Gaboly
http://www.gaboly.com




Avatar
Michel Gaboly
Rebonjour,

Cela ne résoud pas le problème, Isabelle ;-((

Ce que tu indiques est la correspondance par défaut, si le second
argument, facultatif, de Weekday n'est pas utilisé ou s'il est à 1.

Dans le code, j'utilise WeekDay(c, 2), le second argument permet-
tant de faire commencer la semaine le lundi.

La correspondance est donc bien

1 Lundi
2 Mardi
3 Mercredi
4 Jeudi
5 Vendredi
6 Samedi
7 Dimanche

Tu peux le vérifier en entrant une date, sans formatage person-
nalisé et en utilisant

MsgBox WeekDay(ActiveCell, 2).

Debug.Print à la place de MsgBox fait gagner du temps ;-))

Ta méthode permet de compenser l'anomalie sur un classeur basé
sur 1904, mais bien évidemment elle entraîne un décalage d'un
jour si le classeur est basé sur 1900 ;-((

Comme le disait Daniel le problème vient de ce que, à cause du for-
matage, IsDate renvoie False pour les cellules concernées, ce qui
entraîne l'habituel décalage de 1462 jours lors de l'interprétation
des dates si le classeur est basé sur 1904, ce que montre bien

c.Offset(3) = CDate(c)

C'est pourquoi "l'astuce"

WeekDay(c, 2) + ThisWorkbook.Date1904

permet de donner un résultat qui est toujours bon, quel que soit le
calendrier du classeur.



bonjour Michel,

pour suivre à la lettre les informations donnée dans l'aide
1 Dimanche
2 Lundi
3 Mardi
4 Mercredi
5 Jeudi
6 Vendredi
7 Samedi

il faudrait peut être mieux modifier comme ça,

Private Sub Worksheet_Calculate()
Dim c As Range, Mat
Mat = Array("Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa")
For Each c In Range("Dates")
c.NumberFormat = """" &
Application.WorksheetFunction.Index(Mat, WeekDay(c, 2)) & """"
c.Offset(1) = WeekDay(c, 2)
c.Offset(2) = WeekDay(c, 2) + ThisWorkbook.Date1904
c.Offset(3) = CDate(c)
Next c
End Sub

isabelle


Bonjour Isabelle

J'avais proposé 2 solutions, l'une comparable à la tienne, et l'autre qui
tentait d'offrir au demandeur, comme dit Daniel, le beurre et l'argent
du beurre ;-))

Il s'agissait d'avoir dans les mêmes cellules à la fois le formatage et les
dates.

Puisque tu veux "remettre du chimblick :-))", je t'envoie 2 fichiers
exemples.

Je ne sais pas si l'adresse du trombinoscope est à jour. Si oui cela ne
devrait pas tarder.



Rebonsoir,
Mais la demande initiale ne l'était pas non plus ; je ne sais pas si tu as suivi le
fil initial; il s'agissait de quelqu'un qui avait une version d'Excel en anglais,
mais voulait pouvoir afficher le jour de semaine sous la forme "Lu", "Ma", ...
TOUT EN VOULANT pouvoir continuer à faire des calculs de dates sur le contenu
des cellules.


justement la formule qui a été proposé ne fait pas disparaitre la
colonne contenant les dates, alors messieurs vous voulez bien
messeuplipliquer le fondement de se débat face à la question initiale,
juste question de remettre du chimblick :-))

isabelle


Bonne journée,

--
Cordialement,

Michel Gaboly
http://www.gaboly.com



--
Cordialement,

Michel Gaboly
http://www.gaboly.com




Avatar
isabelle
bonjour Michel,

C'est pourquoi "l'astuce"

WeekDay(c, 2) + ThisWorkbook.Date1904

permet de donner un résultat qui est toujours bon, quel que soit le
calendrier du classeur.


oui, c'est bien vrai,
c'est pour cette raison qu'il y a la remarques au bas de la page sur
WeekDay ?

Si la valeur de la propriété Calendar est Grégorien, le nombre entier
renvoyé représente le jour Grégorien de la semaine pour l'argument date.
S'il s'agit d'un calendrier Hijri, le nombre entier renvoyé représente
le jour Hijri de la semaine pour l'argument date. Dans le cas des dates
Hijri, l'argument number est une expression numérique pouvant
représenter une date et/ou heure comprise entre le 1/1/100 (2 août 718
pour le calendrier Grégorien) et le 4/3/9666 (31 décembre 9999 pour le
calendrier Grégorien).

isabelle

Avatar
Michel Gaboly
Re, Isabelle,

Pas exactement ;-)))

Je viens de faire une recherche sur Google avec "calendrier Hijri".
Il s'agit du calendrier musulman, basé sur 12 mois lunaires (un
peu plus de 29 jours chacun).

Cela doit concerner des versions d'Excel très exotiques pour nous ;-))



bonjour Michel,

C'est pourquoi "l'astuce"

WeekDay(c, 2) + ThisWorkbook.Date1904

permet de donner un résultat qui est toujours bon, quel que soit le
calendrier du classeur.


oui, c'est bien vrai,
c'est pour cette raison qu'il y a la remarques au bas de la page sur
WeekDay ?

Si la valeur de la propriété Calendar est Grégorien, le nombre entier
renvoyé représente le jour Grégorien de la semaine pour l'argument date.
S'il s'agit d'un calendrier Hijri, le nombre entier renvoyé représente
le jour Hijri de la semaine pour l'argument date. Dans le cas des dates
Hijri, l'argument number est une expression numérique pouvant
représenter une date et/ou heure comprise entre le 1/1/100 (2 août 718
pour le calendrier Grégorien) et le 4/3/9666 (31 décembre 9999 pour le
calendrier Grégorien).

isabelle


--
Cordialement,

Michel Gaboly
http://www.gaboly.com


1 2