Gérer les messages "Debug.Print" d'une fonction depuis une Sub
Re,
@Jean-Paul
Je me rends compte que si je veux réellement suivre votre conseil (penser Excel avant de penser VBA) toutes les vérifications de validité sur les mois 1 à 12 et 31 ou 30 jours… , devraient pouvoir être géré par des fonctions Excel ?
Je suis un peu dans l'inconnue.
Si votre temps le permet, pourrai-je avoir des pistes ou exemples supplémentaires ?
Re,
Quand tu te lance comme cela tu dois connaître le problème à résoudre.
Tester une date en chaine de caractères comme ceci "240200"
On a vu que l'on pouvais tester le jour avec la fonction IsDayValid par exemple
Public Function IsDayValid(ByVal Value As String) As Variant
Dim localYear As Integer
localYear = CInt(Left$(Value, 2))
Dim LocalMonth As Integer
LocalMonth = CInt(Mid$(Value, 3, 2))
Dim testedDay As Long
testedDay = CLng(Right$(Value, 2))
Dim resultDay As Long
If testedDay = 0 Then
resultDay = Day(Application.WorksheetFunction.EoMonth(DateSerial(localYear, LocalMonth, 1), 0))
Else
If testedDay <= Day(Application.WorksheetFunction.EoMonth(DateSerial(localYear, LocalMonth, 1), 0)) Then
resultDay = testedDay
Else
resultDay = -1
End If
End If
IsDayValid = resultDay
End Function
Elle renvoie :
- Le dernier jour du mois si le jour et à 0
- False si le jour est en dehors des limites 1 - dernier jour du mois exemple "240256"
Pour le mois c'est plus simple avec la fonction IsValidMonth
Public Function IsValidMonth(ByVal Value As String) As Boolean
Dim LocalMonth As Long
LocalMonth = CLng(Mid$(Value, 3, 2))
IsValidMonth = (LocalMonth >= 1 And LocalMonth <= 12)
End Function
Elle renvoie
- True si le mois est dans la plage 1 -12
- False autrement
Pour l'année cela devient plus compliqué avec une année sur deux chiffres avec tes recommendations. Imaginons cette date "740201"
Doit-on considérer que c'est 1974 et là on est dans les clous, ou bien 2074 qui est au delà de l'année en cours plus 50 ans ?
On doit entrer dans des considérations, par exemple une date de péremption ne peux pas être inférieure à la date du jour sinon pas bon, et ne doit pas être supérieure à la date du jour de plus de quelques années, OK. Mais qu'en est-il pour la date de fabrication d'une pièce ou autre, cela change la donne.
Tout cela pour dire que l'on doit bien connaître le contexte, avant de se lancer.
Concernant la mise en place de ce petit monde voici une procédure de test, c'est minimaliste, on pourrait renvoyer la chaine MaDate reformatée par exemple.
Public Sub TestDate()
Dim Madate As String
Madate = "240200"
Dim ValidString as String
' // test sur les jours
If IsDayValid(Madate) = -1 Then
MsgBox "Le jour renseigné n'est pas dans la plage autorisée !"
Else
If IsValidMonth(Madate) = -1 Then
MsgBox "Le mois renseigné n'est pas dans la plage autorisée !"
Else
' Todo "A faire test sur l'année
'If IsValidYear = -1 Then
MsgBox "L'année renseignée n'est pas dans la plage autorisée !"
'Else
'End If
End If
End If
End Sub
Voilà reste à poser le problème des années. Affaire à suivre...
Bonjour,
@Jean-Paul,
Tous vos exemples m'ont aidé pour comprendre la logique vers laquelle vous vouliez me guider !
De petites choses font que me vieux cerveau me dit stop quand je ne comprends pas, comme par exemple :
Dans la 1er fonction, vous déclarez IsDayValid As Variant
Dans la 2ème fonction, vous déclarez IsValidMonth As Boolean
Pour moi Is quelque chose attend une réponse vraie ou fausse, c'est donc un Boolean ?
Même chose pour :
Dim LocalMonth As Integer
LocalMonth = CInt(Mid$(Value, 3, 2))
Dim testedDay As Long
testedDay = CLng(Right$(Value, 2))
Veuillez m 'excuser, mais je ne comprends plus dans quel cas utiliser Integer ou Long ?
Je n'ai même pas su mettre en application la fonction IsValidMonth comme pour IsDayValid !
-
Concernant les années pour "740201" la fonction SetYear est faite pour ça et donne 01/02/1974
Soit 2023 - 49.
Pour 730201 la fonction SetYear donne 01/02/2073
Soit 2023 + 50.
Pour ce qui est des dates de péremption, fabrication … Je ne pensais pas aller plus loin que la vérification d'une date valide, car ces dates sont imposées par les fabricants et donc pas de réel action possible.
bonjour,
le debug.print fourni des informations intéressantes mais il ne faut pas crouler sous le nombres.
je te suggère d'utiliser l'espion avec arrêt de la macro selon critères.
si nom tu peux Numéroter tes lignes de code et envoyer les informations dans un fichier de log. Cette méthode te donnera des informations plus précises.
- .la date et heure
- Le Nº ligne de code
- Valeur d'une ou plusieurs variables
- Etc.
Salut,
Dans la 1er fonction, vous déclarez IsDayValid As Variant
Très bonne question, Jai modifier la fonction et oublié de changer cela, elle peut être de Type Long ou Boolean, dans la première version elle renvoyait, soit le jour qui était de Type Long, soit la Date, qui était je vous le donne en Mille Emile, de Type Date. Donc dans ce cas, ne pouvant pas choisir, c'est le Type Variant qui l'emporte.
Le Type Boolean correspond = 0 pour False et -1 pour True le Type Long va de -2 147 483 648 à 2 147 483 647 donc dans ce cas particulier les deux peuvent convenir.
Veuillez m 'excuser, mais je ne comprends plus dans quel cas utiliser Integer ou Long ?
Avant, il était très important d'économiser de la mémoire sur les anciens PC, donc, on utilisait les Type au plus prés des besoins, le type long prends 32 bits le type Integer 16bits deux fois moins. Maintenant les PC ont plus de mémoire et l'architecture des processeur et en 32 ou 64bits. Ils auront plus de facilité pour travailler avec du 32bits.
Voilà, part sur du type Long pour tout, et cela ira très bien.
Concernant les années pour "740201" la fonction SetYear est faite pour ça et donne 01/02/1974
je n'ai pas approfondi mais si elle te convient garde la..
Edit : Je viens de tester et ce n'est pas le résultat attendu je pense, c'est toi qui décide que cela correspond à 1974...
Je n'ai même pas su mettre en application la fonction IsValidMonth comme pour IsDayValid !
Comme celle des jour si le mois n'est pas compris entre 1 et 12 elle renvoie Faux
Bonjour,
@Jean-Paul, merci pour ces explications
Je regarde pour mettre tous cela en place dès que possible.
Concernant les années pour "740201" la fonction SetYear est faite pour ça et donne 01/02/1974
Edit : Je viens de tester et ce n'est pas le résultat attendu je pense, c'est toi qui décide que cela correspond à 1974...
Comme je l'ai expliqué dans l'un des messages précédents, la fonction SetYear traite la date de telle sorte que La chaîne "YY" ne peut spécifier qu'une date comprise entre 49 ans dans le passé et 50 ans dans le futur avec comme pivot, l'année en cours.
L'année en cours c'est "Year(Now)" soit 2023.
Dans la fonction CheckDate, je déclare:
YY = SetYear(YY, Year(Now))
Soit:
Re,
Je comprends bien, et je me suis mal expliqué, la fatigue peut-être, mais je reste sur ma position c'est toi, ou plutôt le code qui décide de la plage de date et cela n'est pas normal.
A part être un devin, et encore, personne ne peut trouver une date si elle est codée sur deux chiffres, c'est toi avec les calculs (compliqués je trouve pour arriver à ce résultat) qui détermine, quel plage de date va être appliquée.
Mais je le redis ci cela te convient c'est le principal.
Salut Jean-Paul, Léo39,
Si on réfléchi en terme de logistique, "40" pour l'année ne pourras être que 2040 et pas 1940
Je dis ça, je dis rien
Bon week-end
Re,
Si on réfléchi en terme de logistique, "40" pour l'année ne pourras être que 2040 et pas 1940
Je dis ça, je dis rien
Oui, C'est ce que je dis, on peut débattre des heures sur le sujet, si l'on entre 21 dans une cellule formatée en date elle est convertie en 2021, Ha bon pourquoi pas 1921, ou 2121, parce que c'est le plus logique bien évidemment, mais cela étant dit, Excel à fait un choix.
Bonjour,
Je comprends qu'un peu plus d'explication s'impose :
La fonction SetYear a été développée dans le but d'essayer de respecter les critères du standard GS1.
GS1 (abréviation de Global Standards 1) organisme mondial actif dans le domaine de la normalisation des méthodes de codage utilisées dans la chaîne logistique, notamment le code-barres.
Les dates sont toujours représentées dans le format YYMMDD, où le siècle de l'année est déterminé par les spécifications GS1. Seules les dates situées entre 49 ans dans le passé et 50 ans dans le futur (par rapport à l'année en cours) peuvent être représentées.
Un cas concret :
Le fabricant d'une machine, garantie la disponibilité des pièces de rechange pendant 40 ans.
Cette machine a été acquise il y a 30 ans donc en 1993.
Les pièces de rechange seront donc disponibles jusqu'en 2033.
Cette machine en obsolescence en 2034 sera remplacée, la disponibilité des pièces pour cette nouvelle machine suivra le même schéma ou l'année en cours sera 2034.
bonjour le fil,
une correction éventuelle
Public Function IsDayValid(ByVal Valeur As String)
Dim MaDate, Delta
IsDayValid = -1 'on commence avec cette valeur et on la corrige éventuellement
If Len(Valeur) <> 6 Or Not IsNumeric(Valeur) Then Exit Function 'mauvaise longueur ou contenu
MaDate = DateSerial(Mid(Valeur, 1, 2), Mid(Valeur, 3, 2), 1)
If Format(MaDate, "yymm") <> Left(Valeur, 4) Then Exit Function 'problème avec le mois
Delta = Sgn((Year(MaDate) - Year(Now)) \ 50)
If Delta <> 0 Then MaDate = WorksheetFunction.EDate(MaDate, -Delta * 1200) 'GS1-correction
If Right(Valeur, 2) = "00" Then
IsDayValid = Day(WorksheetFunction.EoMonth(MaDate, 0))
Else
If Format(MaDate + Right(Valeur, 2) - 1, "yymmdd") = Valeur Then IsDayValid = --Right(Valeur, 2)
End If
End Function
Bonjour BsAlv,
Une correction? pouvez-vous m'en dire un peux plus?
Bien cordialement
je n'ai pas lu tout le topic, mais je crois que vous voulez le dernier jour ou un jour du mois quand vous donnez un string de 6 chiffres et puis on a ce GS1-standard.
Bon, quand vous donnez "000200", donc pour l'année 2000, le mois février, le dernier jour est le 29.
Si votre question était différent, je l'ai pas bien compris.