Bonjour
Il m'a été donné, il y a 2 ou 3 jours, d'intervenir dans cette discussion :
https://www.developpez.net/forums/d8.../#post10902761
pour signaler une faille d'un didacticiel relatif aux saisies contrôlées de numériques.
Bien que peu adepte de ce genre (contrôles en cours de saisie) et privilégiant personnellement un contrôle en fin de saisie (suffisamment efficace et d'une plus grande légèreté), j'ai voulu écrire de quoi satisfaire (et pour le coup de manière plus flexible et complète) ceux qui s'intéressent à ce type de démarche. Et tant qu'à faire, j'ai délibérément choisi une démarche inhabituelle (histoire d'aborder différemment le problème)
============================== ~||~ =========================
------------------------------La fonction num_ok traite une valeur de type string et retourne une valeur de même type
La valeur traitée est une saisie. La valeur retournée est :
- soit la saisie acceptée d'une expression numérique valide
- soit la valeur antérieure à la modification de la saisie, si expression numérique non valide
Syntaxe de la fonction :
Code : Sélectionner tout - Visualiser dans une fenêtre à part ret = num_ok(Saisie, anterieur, [negatif_ok] , [nb_decimales],[sep_decimal]
PARAMETRES Nature Type Description Saisie obligatoire String la saisie à contrôler : la propriété Text de la zone d'édition (d'une
textbox, d'une combobox, ... par exemple)anterieur obligatoire String A passer tel quel et sous ce nom (auto-géré) negatif_ok facultatif Boolean spécifier à true pour gérer également les nombres négatifs
ou à false pour imposer un nombre positif.
= False si omisnb_decimales facultatif Byte nombre maximum de décimales autorisé.
= 2 si omis.
0 pour imposer un nombre entiersep_decimal facultatif String facultatif : "." ou "," pour imposer le point ou la virgule comme
séparateur décimal
Si omis : l'utilisateur pourra utiliser, à son gré, l'un ou l'autre
de ces deux séparateurs
-----------------------------------------------------------------------Le code de la fonction :
Il est à mettre dans un module standard, de sorte à être accessible depuis n'importe quelle feuille de calcul ou userform.
------------------------------------------------------- Comment appeler cette fonction :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 Public Function num_ok(ByVal Saisie As String, ByRef anterieur As String, _ Optional negatif_ok As Boolean = False, Optional nb_decimales As Byte = 2, Optional sep_decimal As String) As String Static ds As String num_ok = Saisie If ds = "" Then ds = Application.International(xlDecimalSeparator) ''''''''''''''''''''''''''''If (negatif_ok = False And InStr(num_ok, "-") > 0) Or (negatif_ok = True And InStrRev(num_ok, "-") > 1) Then num_ok = anterieur: Exit Function If InStr(num_ok, "-") > Abs(CInt(negatif_ok)) Then num_ok = anterieur: Exit Function If num_ok <> "" And num_ok <> "-" Then If num_ok Like "* *" Or Not IsNumeric(Replace(num_ok, ".", ds)) Then num_ok = anterieur If num_ok Like "*[,.]" & String(nb_decimales, "#") & "?" Or (nb_decimales = 0 And num_ok Like "*[,.]") Then num_ok = anterieur If sep_decimal = "." Then num_ok = Replace(num_ok, ",", sep_decimal) If sep_decimal = "," Then num_ok = Replace(num_ok, ".", sep_decimal) End If anterieur = Trim(num_ok) End Function
J'ai choisi de le faire dans l'évènement Change (d'une textbox, combobox, ...) car cette manière de faire accepte également les copiés/collés valides et rejette ceux qui ne le sont pas (sans nécessité de faire "jouer" des procédures complémentaires).
Voici quelques exemples suffisamment parlants :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 Private Sub TextBox1_Change() 'exemple pour n'accepter qu'un nombre entier positif Static anterieur As String TextBox1.Text = num_ok(TextBox1.Text, anterieur, , 0, ",") End Sub
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 Private Sub TextBox2_Change() 'exemple pour accepter nombre négatif ou positif avec 3 décimales et en imposant le "." pour séparateur décimal Static anterieur As String TextBox2.Text = num_ok(TextBox2.Text, anterieur, True, 3, ".") End SubRemarque : le choix du séparateur décimal est important car déterminant de l'utilisation que l'on veut ensuite faire de la saisie.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 Private Sub TextBox3_Change() 'exemple pour accepter nombre positif avec un 2 décimales en laissant l'utilisateur choisir son séparateur décimal Static anterieur As String TextBox3.Text = num_ok(TextBox3.Text, anterieur) End Sub
- Choisir le "." facilite cette démarche car la fonction Val suffit alors à convertir la saisie en numérique
- Choisir la virgule (pour des raisons de convivialité, par exemple) imposera alors une conversion par utilisation (selon le cas) des fonctions habituelles de conversion (Cint, Csng, etc ...)
- Laisser l'utilisateur choisir ce séparateur (également pour des raisons de convivialité dans un contexte de personnels de diverses nationalités) imposera l'utilisation de la fonction Replace (pour remplacer par un "." la "," éventuelle), puis de la fonction Val
EDIT :
1) je viens de remplacer la ligne 6 par ce que j'ai écrit en lieu et place en ligne 7 (juste pour alléger, mais aussi s'amuser un peu).
2) si j'ai fait ici (en non dans la section générale de VBA) cette contribution, c'est qu'il y a une bonne raison (utilisation d'une propriété propre à VBA/EXCEL)
Pour ceux qui voudraient utiliser cette fonction hors Excel (que ce soit en VBA ou VB6), voilà une manière que je n'aime personnellement pas trop : --->>
remplacer cette ligne de code :
par celles-ci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part If ds = "" Then ds = Application.International(xlDecimalSeparator)
3) cette fonction ne traite, telle quelle, que les deux séparateurs décimaux utilisés dans les pays qui les ont adoptés (tout l'occident et la plupart des autres pays).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 If ds = "" Then ds = IIf(IsNumeric("1.1"), ".", ",") End If
Elle ne traite pas le caractère momayyez (unicode U+066B) en vigueur dans quelques pays arabes du continent asiatique. Ceux qui souhaiteraient utiliser également ce caractère pourront le faire en complétant/modifiant (après analyse et compréhension) certaines lignes du code de cette fonction.
Partager