9 réponses
SarahFistol
- Messages postés
- 80
- Date d'inscription
- dimanche 6 janvier 2013
- Statut
- Membre
- Dernière intervention
- 21 janvier 2021
Bonjour,
merci à tous les deux mais lorsque je rempli ma textbox je continue d'avoir le message format de date incorrect;
Il doit y avoir une autre erreur dans ma fonction ?
merci à tous les deux mais lorsque je rempli ma textbox je continue d'avoir le message format de date incorrect;
Il doit y avoir une autre erreur dans ma fonction ?
ccm81
- Messages postés
- 9680
- Date d'inscription
- lundi 18 octobre 2010
- Statut
- Membre
- Dernière intervention
- 3 mars 2021
Bonjour à tous
Peut être plus simple avec la fonction isDate
Dim d As String, OK As Boolean
d = TextBox1.Value
OK = IsDate(d)
MsgBox OK
If OK Then Cells(1, 1) = CDate(d)
Cdlmnt
Peut être plus simple avec la fonction isDate
Dim d As String, OK As Boolean
d = TextBox1.Value
OK = IsDate(d)
MsgBox OK
If OK Then Cells(1, 1) = CDate(d)
Cdlmnt
Sarafistol
Merci mais ça ne répond pas a mon besoin :
Il me faut contrôler les fautes de frappes des dates d ou ma fonction.
Mon userform alimente un onglet base de Donnees qui alimente lui même un onglet av des formules.
Pour éviter les erreurs dans mes résultats dues a des erreurs de saisies de dates je dois contrôler à la source (la saisie).
Quelqu un aurait une idée svp pour que la fonction et/ou mas sub fonctionne(nt) ???
Merci par avance
Il me faut contrôler les fautes de frappes des dates d ou ma fonction.
Mon userform alimente un onglet base de Donnees qui alimente lui même un onglet av des formules.
Pour éviter les erreurs dans mes résultats dues a des erreurs de saisies de dates je dois contrôler à la source (la saisie).
Quelqu un aurait une idée svp pour que la fonction et/ou mas sub fonctionne(nt) ???
Merci par avance
ccm81
- Messages postés
- 9680
- Date d'inscription
- lundi 18 octobre 2010
- Statut
- Membre
- Dernière intervention
- 3 mars 2021
Déjà la fonction isDate(texte) permet de savoir si texte peut être interprété comme une date ce qui rend inutile
If Len(naval) < 10 Then ctr = False
If Mid(maval, 3, 1) <> "/" Then ctr = False
If Mid(maval, 6, 2) <> "/" Then ctr = False
If CDate(Mid(maval, 4, 2)) > 12 Then ctr = False
sans compter le test sur le jour ...
et si oui, tu es sûr d'avoir une date, tu peux alors affiner sa validité apres l'avoir converti en date avec cdate ....
If Len(naval) < 10 Then ctr = False
If Mid(maval, 3, 1) <> "/" Then ctr = False
If Mid(maval, 6, 2) <> "/" Then ctr = False
If CDate(Mid(maval, 4, 2)) > 12 Then ctr = False
sans compter le test sur le jour ...
et si oui, tu es sûr d'avoir une date, tu peux alors affiner sa validité apres l'avoir converti en date avec cdate ....
ccm81
- Messages postés
- 9680
- Date d'inscription
- lundi 18 octobre 2010
- Statut
- Membre
- Dernière intervention
- 3 mars 2021
par exemple
Private Sub CommandButton1_Click()
Dim dt As String, dok As Boolean
dt = Me.TextBox1.Value
dok = dateok(dt)
MsgBox dok
End Sub
Public Function dateok(dt As String) As Boolean
Dim dok As Boolean, dtest As Date, d As Date
dtest = Sheets(1).Range("A1").Value
dok = True
If IsDate(dt) Then
d = CDate(dt)
If Year(d) > Year(dtest) Then dok = False
Else
dok = False
End If
dateok = dok
End Function
Utilisateur anonyme
Bonjour SarahFistol,
1) "/" est un seul caractère !
Remplace : If Mid(maval, 6, 2) <> "/" Then ctr = False
par : If Mid$(maval, 6, 1) <> "/" Then ctr = False
2) Test an, mois, jour
' Test du jour : à cause de février, il faut tester si l'année est bissextile
ou non (29 ou 28 jours) ; pour les autres mois, ce sera 31 ou 30 jours.
À toi de faire la suite ! Cordialement. 😊
1) "/" est un seul caractère !
Remplace : If Mid(maval, 6, 2) <> "/" Then ctr = False
par : If Mid$(maval, 6, 1) <> "/" Then ctr = False
2) Test an, mois, jour
Dim an As Integer, mois As Integer an = Val(Right$(maval, 4)): If an < 1900 Or An > WorkSheets("Bd").[A1] Then ctr = False ' remplace 1900 par ton année minimum mois = Val(Mid$(maval, 4, 2)): If mois < 1 Or mois > 12 Then ctr = False
' Test du jour : à cause de février, il faut tester si l'année est bissextile
ou non (29 ou 28 jours) ; pour les autres mois, ce sera 31 ou 30 jours.
À toi de faire la suite ! Cordialement. 😊
sarahfistol
>
Utilisateur anonyme
Super !!!! c'est exactement ce que je voulais. merciiiii
J'ai plusieurs petites questions :
- Mid$ : à quoi sert le $ ?
- pourquoi déclarer djm en tant que byte et pas integer ou pourquoi ne pas déclarer le mois ... comme byte ?
- pourquoi au sein de "djm = Choose(mois, 31, 0, 31, ..." djm février =0 ?
- "an Mod 4 = 0 And an Mod 400 > 0", je ne comprends pas très bien. "Mod" renvoie à quoi ?
- "If verifdate(Me.TextBox8) Then Exit Sub" comment lis tu ce morceau de Sub ?
- Je dois utiliser cette sub pour plusieurs TextBox. Dois-je répéter le code autant de fois qu'il y a de TextBox ou y a t-il une astuce ?
- par la suite le contenu de mes textbox va alimenter une base de données qui va elle même faire l'objet de calculs poussés du type calculs de délais entre les dates. Les dates vont bien se mettre au format date dans ma base de données ?
Merci bcp
J'ai plusieurs petites questions :
- Mid$ : à quoi sert le $ ?
- pourquoi déclarer djm en tant que byte et pas integer ou pourquoi ne pas déclarer le mois ... comme byte ?
- pourquoi au sein de "djm = Choose(mois, 31, 0, 31, ..." djm février =0 ?
- "an Mod 4 = 0 And an Mod 400 > 0", je ne comprends pas très bien. "Mod" renvoie à quoi ?
- "If verifdate(Me.TextBox8) Then Exit Sub" comment lis tu ce morceau de Sub ?
- Je dois utiliser cette sub pour plusieurs TextBox. Dois-je répéter le code autant de fois qu'il y a de TextBox ou y a t-il une astuce ?
- par la suite le contenu de mes textbox va alimenter une base de données qui va elle même faire l'objet de calculs poussés du type calculs de délais entre les dates. Les dates vont bien se mettre au format date dans ma base de données ?
Merci bcp
Utilisateur anonyme
>
sarahfistol
Bonsoir Sarah,
Je suis très content que tu aies apprécié mes deux messages #12 et #14 ! 😊
Cependant, pour mon message #12, j'étais un peu fatigué, et j'ai oublié
de simplifier le code de ton UserForm en enlevant les préfixes « Me. » :
Private Sub TextBox1_AfterUpdate() If verifdate(TextBox1) Then Exit Sub TextBox1 = "": TextBox1.SetFocus MsgBox "Veuillez saisir une date au format JJ/MM/AAAA", 48, "Date erronée" End Sub
Tu as écris : « Je dois utiliser cette sub pour plusieurs TextBox. Dois-je répéter
le code autant de fois qu'il y a de TextBox ou y a-t-il une astuce ? ». Réponse :
Non, pour utiliser la sub verifdate() du Module1 (ou d'un autre Module), tu peux
l'appeler aussi souvent que nécessaire, sans avoir à répéter son code ; mais
chacune de tes TextBox devra être écrite sur le même modèle que la 1ère :
Private Sub TextBox2_AfterUpdate() If verifdate(TextBox2) Then Exit Sub TextBox2 = "": TextBox2.SetFocus MsgBox "Veuillez saisir une date au format JJ/MM/AAAA", 48, "Date erronée" End Sub
De plus, avec au moins 3 TextBox identiques, je te conseille vivement de mettre
en constante la longue chaîne de caractères servant de prompt ; donc au tout
début du code de ton UserForm, mets :
Option explicit Const msgdate As String * 45 = "Veuillez saisir une date au format JJ/MM/AAAA"
Le « * 45 » n'est pas une erreur de frappe : c'est pour déclarer une chaîne de
caractères de longueur fixe, ici de 45 caractères : ça prend en mémoire juste
la place qu'il faut => économie de RAM (mémoire vive). Bien sûr, attention à
bien mettre le bon nombre de caractères, sans te tromper !
Tu peux aussi mettre :
Option explicit Const msgdate As String = "Veuillez saisir une date au format JJ/MM/AAAA"
Mais sans indication de longueur fixe, ça utilise une chaîne de caractères de
longueur variable, ce qui prend plus de place en RAM ; à toi de choisir ! 😉
Grâce à cette constante, écris tes TextBox avec cette nouvelle dernière ligne :
Private Sub TextBox1_AfterUpdate() If verifdate(TextBox1) Then Exit Sub TextBox1 = "": TextBox1.SetFocus: MsgBox msgdate, 48, "Date erronée" End Sub
C'est à la fois plus court et plus lisible, hein ? 😉
------------------------------------------------------------------
Tu as aussi demandé comment lire la 1ère ligne de cette sub. Si je l'avais écrite
de façon classique, j'aurais mis : If verifdate(TextBox1) = True Then Exit Sub
Or tu sais qu'un test avec « If » est ainsi : Si condition est vraie alors ...
On peut donc enlever « = True » car :
a) verifdate(TextBox1) retourne vrai car la date est bonne ; puisque c'est vrai,
alors ... ; cette suite étant que Exit Sub fait sortir aussitôt de la Sub, évitant
ainsi d'exécuter les instructions qui suivent.
b) verifdate(TextBox1) retourne faux car la date n'est pas bonne ; puisque
c'est faux, on n'exécute pas le alors ... ; et on passe aussitôt à la ligne qui
suit : celle avec l'affichage du message d'erreur.
------------------------------------------------------------------
Pour ta dernière question : la date saisie dans une TextBox est bien évidemment
une chaîne de caractères et pas une « vraie » date (dans le sens où c'est ni un
format date, ni un numéro de série de date). Cependant, VBA fait dans certains
cas une conversion automatique en date (selon le contexte, par exemple si ajout
ou retrait par rapport à une autre date).
Je ne peux pas te dire s'il y aura une telle conversion automatique lors de
la reprise de tes dates dans ta base de données ; si oui, tant mieux ! sinon,
tu devras faire toi-même une conversion explicite (la conversion auto par
VBA en est une implicite).
------------------------------------------------------------------
Les fonctions de chaînes de caractères telles que Left, Mid, Right... existent sous
deux formes : l'une sans le signe « $ » retourne une chaîne de caractères de type
variant ; l'autre avec le signe « $ » retourne une chaîne de caractères de type
string ; or un type variant (pour une chaîne de caractères) prendra toujours
plus de place en mémoire que la même chaîne de type string ; donc là encore,
économie de RAM en mettant le signe « $ ». D'où le Mid$ ; et tu t'es trompée
si tu as cru que j'étais fan des billets de l'oncle Sam (les dollars américains) ! 😉
------------------------------------------------------------------
Tu as aussi écris : « "an Mod 4 = 0 And an Mod 400 > 0", je ne comprends pas
très bien. "Mod" renvoie à quoi ? ».
« + » est une opération (addition) ; de même, Mod est aussi une opération
(abréviation de Modulo).
Soient 2 nombres entiers a et b ; alors : a mod b (prononcer a modulo b)
retourne le reste de la division de a par b.
Si cette opération n'existait pas en VBA, on devrait la programmer soi-même ;
au lieu de : c = a Mod b on devrait mettre : c = a - b * INT(a / b)
avec : * pour une multiplication (comme : ×) et INT pour Partie Entière ;
selon la priorité des opérations, ça fait que c'est équivalent à :
c = a - (b * INT(a / b)) et pas à : c = (a - b) * INT(a / b) !!!
Sur une feuille de calcul Excel, utiliser ENT() au lieu de INT() ;
mais c'est inutile car par exemple, sur une feuille vierge :
a) mets en B2 : 2016 ; mets en C2 : 400 ; mets en D2 : =MOD(B2;C2) => 16
2016 est divisible par 4 sans être divisible par 400 => 29/02/2016
b) mets en B2 : 2000 => 0 en D2
2000 est divisible par 4 et divisible par 400 => 28/02/2016
Comme on est en 2016, si tu arrives à survivre et à patienter pendant encore
384 ans, tu auras la chance de vivre en 2400, la prochaine année à venir qui
sera à la fois divisible par 4 et par 400, donc non bissextile ! Inutile de te dire
que tu auras battu le record de Jeanne Calmant haut la main !!! 😉
Ah ben zut, alors ! Moi qui ai acheté ta maison en viager, c'est pas demain
la veille que je pourrai emménager chez toi !!! 😉
Maintenant que tu sais ce qu'est Mod, dis-moi si tu comprends ceci :
If mois = 2 Then djm = 28 - (an Mod 4 = 0 And an Mod 400 > 0)
Ça aidera pour une de mes prochaines réponses.
------------------------------------------------------------------
Vu qu'il est maintenant 2 h du matin et que ce message est déjà très long,
je répondrai à tes 2 autres questions une autre fois (promis, sans faute !).
Cordialement. 😊
Utilisateur anonyme
>
SarahFistol
- Messages postés
- 80
- Date d'inscription
- dimanche 6 janvier 2013
- Statut
- Membre
- Dernière intervention
- 21 janvier 2021
Bonjour SarahFistol,
Lis d'abord mon message #12 ; ensuite, j'ai oublié de te préciser ceci :
Quand tu écris une fonction NomX (par exemple), alors :
a) Tu passes à cette fonction tous les arguments que tu veux, comme pour
une sub ; exemple : Function verifdate(maval As String) As Boolean
b) Ta fonction doit retourner une valeur, dont tu indiques le type avec As Type ;
exemple pour verifdate() : Function verifdate(maval As String) As Boolean
c) De plus, comme ta fonction doit retourner une valeur, n'oublies pas de lui
affecter cette valeur de retour avec NomX = ... ; c'est ce que tu as justement
omis de faire : à chaque fois tu affectes monctr = ... mais avant la sortie de
ta fonction, tu aurais dû mettre verifdate = monctr ; cependant, tu verras que
dans mon propre code, je n'ai pas eu besoin d'utiliser monctr car j'affecte
directement verifdate ; en principe, une fonction ne comporte qu'une seule
instruction d'affectation NomX = ... mais compte tenu des spécificités de
cette fonction, il y a plusieurs instructions d'affectation verifdate = ...
N'oublies pas de me dire ce que tu penses de mon code VBA ; si tu as besoin
de plus d'infos, n'hésites pas ; si ton problème est réglé, merci d'aller en haut
de page pour cliquer sur « Marquer comme résolu ».
Cordialement. 😊
Utilisateur anonyme
>
SarahFistol
- Messages postés
- 80
- Date d'inscription
- dimanche 6 janvier 2013
- Statut
- Membre
- Dernière intervention
- 21 janvier 2021
Bonjour Sarah,
Je suis ravi que tu aies apprécié, et je viens de t'écrire un autre long message :
mon message #23 ; alors, je te souhaite une bonne lecture au coin du feu,
pendant tes longues soirées d'hiver devant la cheminée ! 😉
Cordialement. 😊
michel_m
- Messages postés
- 16393
- Date d'inscription
- lundi 12 septembre 2005
- Statut
- Contributeur
- Dernière intervention
- 3 mars 2021
Bonjour,
source:
https://silkyroad.developpez.com/VBA/ControlesUserForm/#LII-E
le "/" est écrit par le code lors de la saisie
a la rigueur , après
TextBox1 = ""
tu peux programmer un "set focus" pour retourner sur le textbox; tu as les explications sur le lien indiqué
Michel
source:
https://silkyroad.developpez.com/VBA/ControlesUserForm/#LII-E
le "/" est écrit par le code lors de la saisie
Private Sub TextBox1_Change()
Dim Valeur As Byte
TextBox1.MaxLength = 10 'nb caractères maxi autorisé dans le textbox
Valeur = Len(TextBox1)
If Valeur = 2 Or Valeur = 5 Then TextBox1 = TextBox1 & "/"
End Sub
'Ensuite pour vérifier que c'est bien une date qui a été saisie
Private Sub CommandButton1_Click()
If Not IsDate(TextBox1) Then
MsgBox "Format incorrect"
TextBox1 = ""
Exit Sub
Else
MsgBox "Format correct"
'...la suite de la procédure
End If
End Sub
a la rigueur , après
TextBox1 = ""
tu peux programmer un "set focus" pour retourner sur le textbox; tu as les explications sur le lien indiqué
Michel
michel_m
- Messages postés
- 16393
- Date d'inscription
- lundi 12 septembre 2005
- Statut
- Contributeur
- Dernière intervention
- 3 mars 2021
- Messages postés
- 80
- Date d'inscription
- dimanche 6 janvier 2013
- Statut
- Membre
- Dernière intervention
- 21 janvier 2021
Bonjour Sarah,
Curieux! je viens d'essayer sur une petite maquette et c'est OK
le piège quand on a pas l'habitude est que les "/" se mettent automatiquement
mais la syntaxe écrite doit être
jjmmaaaa qui renvoie jj/mm/aaaa
A l'époque où l'auteur a écrit cette astuce, il était MVP (Most Valuable Professionnal- titre annuel décerné par MS aux meilleurs exceliens)
remarque "au cas où":
les dates sur XL commencent à partir du 1° janvier 1900
La maquette de W
http://www.cjoint.com/c/FGehavOp7dt
Edit 9h30
si tu n'as pas de commandbutton
tu peux employer
Private Sub TextBox1_AfterUpdate()
au lieu de
Private Sub CommandButton1_Click()
il faudra alors cliquer sur un autre contrôle pour déclencher la vérif
Mais, en général, lorsqu'on saisit une série de données dans un Usf pour les envoyer dans une feuille, il ya un commandbutton "valider"
Curieux! je viens d'essayer sur une petite maquette et c'est OK
le piège quand on a pas l'habitude est que les "/" se mettent automatiquement
mais la syntaxe écrite doit être
jjmmaaaa qui renvoie jj/mm/aaaa
A l'époque où l'auteur a écrit cette astuce, il était MVP (Most Valuable Professionnal- titre annuel décerné par MS aux meilleurs exceliens)
remarque "au cas où":
les dates sur XL commencent à partir du 1° janvier 1900
La maquette de W
http://www.cjoint.com/c/FGehavOp7dt
Edit 9h30
si tu n'as pas de commandbutton
tu peux employer
Private Sub TextBox1_AfterUpdate()
au lieu de
Private Sub CommandButton1_Click()
il faudra alors cliquer sur un autre contrôle pour déclencher la vérif
Mais, en général, lorsqu'on saisit une série de données dans un Usf pour les envoyer dans une feuille, il ya un commandbutton "valider"
SarahFistol
- Messages postés
- 80
- Date d'inscription
- dimanche 6 janvier 2013
- Statut
- Membre
- Dernière intervention
- 21 janvier 2021
@Michel :
et oui en effet, j'ai un commandbutton "valider" pour enregistrer toutes les données de mes controls dans ma base de données.
Désolée, je n'avais pas fait le lien ... j'étais restée sur ma TextBox
et oui en effet, j'ai un commandbutton "valider" pour enregistrer toutes les données de mes controls dans ma base de données.
Désolée, je n'avais pas fait le lien ... j'étais restée sur ma TextBox
michel_m
- Messages postés
- 16393
- Date d'inscription
- lundi 12 septembre 2005
- Statut
- Contributeur
- Dernière intervention
- 3 mars 2021
le + complet mais ca ne se lit pas comme un roman policier:
https://excel.developpez.com/cours/?page=prog#environnement
https://excel.developpez.com/cours/?page=prog#environnement
pijaku
- Messages postés
- 12248
- Date d'inscription
- jeudi 15 mai 2008
- Statut
- Modérateur
- Dernière intervention
- 3 mars 2021
Bonjour tout le monde,
Le sujet est résolu (j'arrive une fois de plus trop tard), mais, voyant que vous utilisez tous un contrôle de saisie à posteriori, j'apporte ma petite contribution pour un contrôle de saisie en temps réel.
Pour cela, il existe la solution d'ucfoutu : ICI. A tester sur un nouvel userform dans un classeur vierge.
Sinon, en passant par des modules de classe (beaucoup plus complexe...), vous pouvez regarder par ICI. Cet exemple implémente plusieurs types de contrôles de saisie pour vos UserForm.
Le sujet est résolu (j'arrive une fois de plus trop tard), mais, voyant que vous utilisez tous un contrôle de saisie à posteriori, j'apporte ma petite contribution pour un contrôle de saisie en temps réel.
Pour cela, il existe la solution d'ucfoutu : ICI. A tester sur un nouvel userform dans un classeur vierge.
Sinon, en passant par des modules de classe (beaucoup plus complexe...), vous pouvez regarder par ICI. Cet exemple implémente plusieurs types de contrôles de saisie pour vos UserForm.
D'où l'intérêt de commencer chaque module par :
Cdlt
Patrice