Fonction validation
Bonjour
Je cherche une solution pour rentrer mes dates sans faire des fautes de frappe. En utilsant la fonction validation, je pense que c'est le mieux mais comment dire que si la date est supérieure à 10 mais que si je rentre 32 c'est pas bon ou mettre le 29/02/2021 est fausse. Y a t il un moyen de répondre à ce problème
merci
Bonjour,
Il y a un menu "Autoriser" dans la barre de validation. Vous choisissez Date et ensuite vous mettez une date de début et une date de fin.
A priori les saisies qui ne sont pas des dates seront refusées.
Cdlt,
Salut,
Je ne comprends pas trop ton problème.
Tu as quels critères pour les dates que tu veux renseigner?
dans la "validation", si tu choisis le format date et que tu prends l'intervalle de temps qui te convient, tu ne pourra pas renseigner des dates qui n'existe pas dans la cellule (par exemple le 32 du mois, ou le 29/02/2021). Par contre,je ne sais pas si tu as d'autre contrainte que ça.
Dans l'intervalle, déjà les mauvaises dates devraient être refusées et en plus on peut choisir les dates, ex :
=aujourdhui()
en date de fin, toutes les dates supérieures à celle du jour sont bloquées.
en fait je pensais l'avoir mis dans ma question mais j'ai des dates < 1900
merci
D'accord, donc toutes les dates sont traités comme du texte, c'est ça ?
Dans ce cas, je reviens bientôt avec une solution...
Voici une solution, probablement à améliorer, mais qui devrait faire l'affaire :
'DANS LE MODULE DE LA FEUILLE CONCERNEE
Private Sub Worksheet_Change(byval target as range)
if not intersect(target, range("refcellulesconcernees")) is nothing then '<<<<<<<<<< ADAPTER
if target.value <> "" and target.count = 1 then
Call ValidationDate(target)
end if
end if
end sub
'DANS UN MODULE NORMAL
Sub ValidationDate(Cible As Range)
Dim Expreg As Object
Dim chaine$
Dim subdiv, jour, mois, annee
Set Expreg = CreateObject("vbscript.regexp")
chaine = Cible.Value
chaine = Replace(Replace(chaine, "-", "/"), ".", "/")
With Expreg
.Global = True
.Pattern = "^[0-9]{1,2}/[0-9]{1,2}(/([0-9]{1,2}|[0-9]{4}))?$"
If Not .test(chaine) Then GoTo Err
.Pattern = "[0-9]+"
Set subdiv = .Execute(chaine)
jour = subdiv(0)
mois = subdiv(1)
if subdiv.count = 3 then annee = subdiv(2) else annee = year(now)
If Len(annee) < 4 Then annee = 2000 + annee
End With
If jour = 0 Then GoTo Err
Select Case mois
Case 0, Is > 12: GoTo Err
Case 2
If annee Mod 4 = 0 And jour > 29 Then GoTo Err
If annee Mod 4 > 0 And jour > 28 Then GoTo Err
Case 4, 6, 9, 11: If jour > 30 Then GoTo Err
Case Else: If jour > 31 Then GoTo Err
End Select
chaine = Format(chaine, "DD/MM/YYYY")
Application.EnableEvents = False
If Cible.Value <> chaine Then Cible.Value = chaine
Application.EnableEvents = True
Exit Sub
Err:
MsgBox "Saisie de la date incorrecte !" & vbCrLf & vbCrLf & _
"Veuillez saisir une date existante au format JJ/MM/AAAA", vbCritical, "Validation des données"
With Cible
.ClearContents
.Activate
End With
End Sub
Cdlt,
Merci à tous pour votre travail qui nous facilite la vie
Bonne soirée
Alors, ça marche bien ?
Les dates avant JC ne sont pas autorisées pour l'instant...
Bonsoir…
Dans la fenêtre des codes de l’onglet considéré et pour une saisie dans une zone nommée Plage
Private Sub Worksheet_Change(ByVal R As Range)
If Not Intersect(R, [Plage]) Is Nothing And R.CountLarge = 1 Then
If Not IsDate(R) Then
Application.EnableEvents = 0 ‘plus d’évènements rappelés
R = ""
Application.EnableEvents = 1 ‘évènements rétablis (ne pas supprimer !)
End If
End If
End Sub
Je testerais demain car je suis au travail
merci
Bonjour
J'ai mis un peu de temps mais vos macro sont trop complexe pour moi. j'ai testé et je deviens fou.
Vous remercie pour votre travail mais je suis perdu. je m'en excuse
Mille merci.
Claude
Bonjour,
Je comprends. Il suffit de mettre ce code (modifié pour gérer les années non bissextiles centenaires et commenté) dans un module normal.
Sub ValidationDate(Cible As Range)
Dim Expreg As Object
Dim subdiv as Object
Dim chaine$
Dim jour, mois, annee
Set Expreg = CreateObject("vbscript.regexp")
chaine = Cible.Value
chaine = Replace(Replace(chaine, "-", "/"), ".", "/") 'remplace tous les points et tirets par slash (pour traiter indifferemment)
With Expreg
.Global = True
.Pattern = "^\d{1,2}/\d{1,2}(/\d{1,4})?$" 'modele : 1 ou 2 chiffres, "/", 1 ou 2 chiffres, (optionnel : "/", 1 à 4 chiffres)
If Not .test(chaine) Then GoTo Err
.Pattern = "\d+" 'modele de subdivision : toute sous-chaine composée exclusivement de chiffres
Set subdiv = .Execute(chaine)
jour = subdiv(0)
mois = subdiv(1)
If subdiv.Count = 3 Then annee = subdiv(2) Else annee = Year(Now) 'si 3 sous-chaines, annee = derniere sous-chaine, sinon annee = annee en cours
End With
If jour = 0 Then GoTo Err 'jour = 0, erreur
Select Case mois
Case 0, Is > 12: GoTo Err 'mois = 0 ou supérieur à 12, erreur
Case 2 'mois février
If annee Mod 400 = 0 Or (annee Mod 4 = 0 And annee Mod 100 > 0) Then 'années bissextiles (divisibles par 400 ou divisibles par 4 et non par 100)
If jour > 29 Then GoTo Err
Else
If jour > 28 Then GoTo Err 'années non bissextiles
End If
Case 4, 6, 9, 11: If jour > 30 Then GoTo Err 'mois à 30 jours
Case Else: If jour > 31 Then GoTo Err 'autres mois à 31 jours
End Select
chaine = jour & "/" & mois & "/" & annee 'reconstitution chaine
If Not (Len(annee) = 4 And annee < 100) Then 'conversion en date sauf pour années < 100
chaine = Format(chaine, "DD/MM/YYYY")
End If
Application.EnableEvents = False 'désactivation de l'évènement change
If Cible.Value <> chaine Then Cible.Value = chaine 'valeur cible mise au format souhaité
Application.EnableEvents = True 'réactivation évènement change
Exit Sub
Err: 'si erreur
MsgBox "Saisie de la date incorrecte !" & vbCrLf & vbCrLf & _
"Veuillez saisir une date existante au format JJ/MM/AAAA", vbCritical, "Validation des données" 'message
With Cible
.ClearContents 'contenu de la cible supprimé
.Activate 'cible activée
End With
End Sub
Ensuite, de mettre celui-ci dans un module de feuille. Si votre validation concerne la "Feuil1". Vous cliquez sur "Feuil1" de la fenêtre de projets juste à gauche (a priori) de l'éditeur. Et vous collez ce code :
Private Sub Worksheet_Change(byval target as range)
if not intersect(target, range("refcellulesconcernees")) is nothing then '<<<<<<<<<< ADAPTER
if target.value <> "" and target.count = 1 then
Call ValidationDate(target)
end if
end if
end sub
Dans le second code, vous modifiez "refcellulesconcernees" par "A1" par exemple si la validation porte sur la cellule A1 de la "Feuil1".
Et c'est bon...
Ensuite vous vous rendez en A1 et vous faites vous tests en saisissant des dates valides et invalides pour vérifier que la validation se passe comme vous le désirez.
Cdlt,
Bonjour à tous,
autre proposition, plus simple au niveau du contrôle de validité.
Permet 2 types de retour. Le 2nd avec année en tête permet le tri si besoin.
Private Sub Worksheet_Change(ByVal Target As Range)
' valide et retourne une date en texte (car certaines < 01/01/1900)
Const formatDate = 1
'formatDate = 1 : jj/mm/aaaa en texte
'formatDate = 2 : aaaa-mm-jj en texte, permet le tri
Dim dat, d As Date
If Target.Column = 2 Then ' adapter au besoin
dat = Split(Target, "/")
If UBound(dat) <> 2 Then GoTo erreur
d = DateSerial(dat(2) + 2000, dat(1), dat(0))
If Day(d) <> Val(dat(0)) Then GoTo erreur
If Month(d) <> Val(dat(1)) Then GoTo erreur
End If
Application.EnableEvents = False
Select Case formatDate
Case 1
Target = format(dat(0), "00") & "/" & format(dat(1), "00") & "/" & format(dat(2), "0000")
Case 2
Target = format(dat(2), "0000") & "-" & format(dat(1), "00") & "-" & format(dat(0), "00")
End Select
Application.EnableEvents = True
Exit Sub
erreur:
Target.Select: MsgBox ("Date non valide, ressaisir")
End Sub
Ici colonne B supervisée, à adapter
eric