Intialiser un nombre à 2 décimales et l'afficher dans le userform

Mais je veux bien que tu prennes du temps à m'expliquer cet histoire de control de caractère ascii .

Pour la TextBoxHT€Adapable par exemple. Tu as plusieurs niveaux d'intéraction possible :

  1. TextBoxHT€Adapable_KeyPress --> se lance à chaque fois que tu appuies sur une touche dans ce champs
  2. TextBoxHT€Adapable_Change --> se lance à chaque fois que tu modifies la valeur de ce champs
  3. TextBoxHT€Adapable_AfterUpdate --> se lance en quittant le champs lorsqu'Excel enregistre sa valeur

J'utilise dans ces sub des fonctions avec des paramètres. Une fonction est un bloc de code unique qui pourra être exécuté plusieurs fois sans avoir à être dupliqué (comme ici tout tes champs numériques. Tu ne vas pas t'amuser à recopier x fois tes contrôles). Un paramètre est une valeur commune entre le code contenant la partie appelante de la fonction et la fonction elle même.

Le but est de n'autoriser que des nombres et "." et "," et éventuellement "-" selon champs.

Je vais donc intervenir dans TextBoxHT€Adapable_KeyPress en appelant une fonction avec des paramètres pour contrôler l'ASCII de la touche pressée et le forcer à 0 s'il ne correspond pas à la fourchette voulue. Les paramètres me permettent de définir précisément ce que j'autorise comme touche.

Private Sub TextBoxHT€Adapable_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)

Dim ascii_origine As Long

ascii_origine = KeyAscii

KeyAscii = fonctions_persos.verif_ascii(ascii_origine, False)

End Sub
Function verif_ascii(ascii_origine As Long, negatif_autorise As Boolean) As Integer

If ascii_origine = 46 Then

    ascii_origine = 44

ElseIf negatif_autorise = False And ascii_origine = 45 Then

    ascii_origine = 0

ElseIf ascii_origine < 48 Or ascii_origine > 57 Then

    ascii_origine = 0

End If

verif_ascii = ascii_origine

End Function

En sortie j'ai donc soit un ASCII à 0 qui ne mettra pas le champs à jour du coup soit un ASCII autorisé.

Le champs se met donc à jour avec mon ASCII contrôlé. Je peux maintenant contrôler si sa valeur correspond à ce que je veux avec TextBoxHT€Adapable_Change.

Private Sub TextBoxHT€Adapable_Change()

Dim valeur_actuelle As String

valeur_actuelle = Replace(TextBoxHT€Adapable, ".", ",")

If valeur_actuelle <> "" And fonctions_persos.verif_saisie(Me, "TextBoxHT€Adapable", 2, True, False) = "OK" Then

    TextBoxTTC€Adapable = Format(valeur_actuelle * (ThisWorkbook.Sheets("Code_VBA").Range("F8") + 1), "#,##0.00")

Else

    TextBoxTTC€Adapable = ""

End If

End Sub

Ici j'utilise Function verif_saisie(formulaire As Object, champs_principal As String, nbre_decimales_autorisees As Long, positif_autorise As Boolean, negatif_autorise As Boolean) As String qui me permet de faire des contrôles à chaque changement de valeur (après chaque insertion/suppression de caractère) dans le champs. Là encore les paramètres me permettent de définir ce que j'autorise ou non. De plus en fonction du retour de cette fonction le champs TextBoxTTC€Adapable est lui aussi mis à jour.

Function verif_saisie(formulaire As Object, champs_principal As String, nbre_decimales_autorisees As Long, positif_autorise As Boolean, negatif_autorise As Boolean) As String

Dim erreur As Long
Dim valeur_actuelle As String
Dim phrase_erreur As String
Dim nbre_decimales_saisies As Long

'début de la phrase d'erreur
phrase_erreur = "Ce champs ne doit être complété que par un nombre"

'concaténation du "signe" autorisé pour le champs contrôlé à la suite de la phrase d'erreur (selon paramètre)
If positif_autorise = True And negatif_autorise = True Then

    phrase_erreur = phrase_erreur & " positif ou négatif"

ElseIf positif_autorise = True Then

    phrase_erreur = phrase_erreur & " positif"

Else

    phrase_erreur = phrase_erreur & " négatif"

End If

'concaténation du "type" autorisé pour le champs contrôlé à la suite de la phrase d'erreur (selon paramètre)
If nbre_decimales_autorisees = 0 Then

    phrase_erreur = phrase_erreur & " entier."

ElseIf nbre_decimales_autorisees = 1 Then

    phrase_erreur = phrase_erreur & " à 1 décimale maximum."

Else

    phrase_erreur = phrase_erreur & " à " & nbre_decimales_autorisees & " décimales maximum."

End If

'récupération de la valeur saisie dans le champs contrôlé
valeur_actuelle = formulaire.Controls(champs_principal)

'si le champs contrôlé n'est pas vide
If valeur_actuelle <> "" Then

    'remplacer le "." par ","
    valeur_actuelle = Replace(valeur_actuelle, ".", ",")

    's'il y a une "," (indiquant des décimales)
    If InStr(valeur_actuelle, ",") > 0 Then

        'récupérer le nombre de décimales
        nbre_decimales_saisies = Len(valeur_actuelle) - InStr(valeur_actuelle, ",")

        'comparer ce nombre de décimales avec le nombre de décimales autorisées (transmis en paramètre)
        If nbre_decimales_saisies > nbre_decimales_autorisees Then

            'retenir qu'il y a erreur
            erreur = 1

        End If

        'cas où la saisie se termine par un "." ou "," sans encore de décimales derrières mais où seule une valeur entière est autorisée
        If Right(valeur_actuelle, 1) = "," And nbre_decimales_autorisees = 0 Then

            'retenir qu'il y a erreur
            erreur = 1

        End If

    End If

    'vérifier que la valeur saisie est numérique et si oui vérifier sa valeur par rapport au paramètre d'acceptabilité des positifs/négatifs
    If IsNumeric(valeur_actuelle) Then

        If valeur_actuelle * 1 > 0 And positif_autorise = False Then

            'retenir qu'il y a erreur
            erreur = 1

        End If

        If valeur_actuelle * 1 < 0 And negatif_autorise = False Then

            'retenir qu'il y a erreur
            erreur = 1

        End If

    Else

        'retenir qu'il y a erreur
        erreur = 1

    End If

End If

'si aucune erreur n'a été retenue la fonction renvoie "OK"
If erreur = 0 Then

    verif_saisie = "OK"

Else

    'si au moins 1 erreur a été retenue

    'vider le champs contrôlé
    formulaire.Controls(champs_principal) = ""

    'afficher la phrase d'erreur préconstruite en début de fonction
    MsgBox phrase_erreur & vbNewLine & vbNewLine & "Votre saisie " & Chr(34) & valeur_actuelle & Chr(34) & " ne convient pas.", vbCritical, "Attention erreur"

    'la fonction renvoie la valeur du champs contrôlé
    verif_saisie = valeur_actuelle

End If

End Function

La première partie de ce code me permet de créer une phrase d'erreur adaptée au cas précis du champs contrôlé puis viennent les contrôles. Selon le résultat des contrôles j'affiche la phrase d'erreur préconstruite et je vide ou non le champs contrôlé.

image

L'utilisateur saisi donc sa valeur (mettons 5000,5 pour l'exemple). Il n'y a pas de lettres puisque je les ai filtrés dans TextBoxHT€Adapable_KeyPress et il n'y a pas trop de décimales puisque j'ai vérifié avec TextBoxHT€Adapable_Change. Mais pour le moment la valeur "5000,5" apparait telle quelle. Sans le séparateur de milliers et sans le dernier "0" des décimales. Cette partie de mise en forme est faite via TextBoxHT€Adapable_AfterUpdate.

Private Sub TextBoxHT€Adapable_AfterUpdate()

TextBoxHT€Adapable = Format(Replace(TextBoxHT€Adapable, ".", ","), "#,##0.00")

End Sub

Ce code est très court. Il ne sert qu'à la mise en forme du champs. Ainsi l'utilisateur verra apparaitre "5 000,50" dans le champs.

Voilà c'est tout. Le fait d'avoir créé et utilisé des fonctions me permet de faire appel à ces mêmes fonctions et donc méthodologie pour tout tes champs à contrôler (ou presque). Pas besoin de dupliquer ces codes. On fait simplement un rappel de ces fonctions.

Il te reste encore des comprimés dans ton tube d'aspirine ? ;)

Bonsoir Alex,
Bonsoir BsAlv

Merci pour toutes ces explications.
Mon verre fait des bulles et ma pauvre cervelle aussi...

J'ai consulté la table des caractères ASCII et j'en ai déduis ceci :

Function verif_ascii(ascii_origine As Long, negatif_autorise As Boolean) As Integer

If ascii_origine = 46 Then    ' si c'est un point

    ascii_origine = 44    ' alors ça devient une virgule

ElseIf negatif_autorise = False And ascii_origine = 45 Then    ' et si c'est un - alors ce sera un caractère NUL

    ascii_origine = 0

ElseIf ascii_origine < 48 Or ascii_origine > 57 Then    ' et si ascii_origine est inférieur au caractère 0 ou bien ascii_origine supérieur au caractère 9 alors ce sera un caractère NUL 

    ascii_origine = 0

End If

verif_ascii = ascii_origine     ' là je ne comprends pas trop. le fait que la variable ait le même nom que la fonction. C'est obligatoire ? 

End Function

Dis moi si je me trompe.
Merci d'avance

En fait, ton code est compréhensible et je pourrais le dupliquer et au besoin l'adapter.
C'est plus long à écrire que celui de BsAlv, qui lui semble plus puissant, mais le tien plus facile à comprendre. Note que je suis à fond.


Désolé, @BsAlv mais là tu m'as perdu. refaire ton cheminement, j'en serai bien incapable.
Je ne comprends pas tout dans tes paramètres.
Certains contrôles te semblent simples à mettre en place pour toi, mais bien trop complexes pour moi.


Il me reste :

  1. à inclure des images dans le formulaire. (j'ai fais un autre sujet pour ça)
  2. faire un système de recherche pour sélectionner des références
  3. et aussi faire un semblant de devis selon les références sélectionnées (dans la case sélection, en mettant un caractère).
    Je faisais ça en 2 coups de cuillères à pots avec Works version 4,5, mais comme je ne peux plus l'installer depuis W10... , je dois me casser la tête pour faire ça avec Excel.

Bref, je ne suis pas au bout de mes peines.

"on error goto 0" ou "on error resume next"

J'essaie d'éviter aussi mais par flême des fois j'utilise. Notamment

On error resume next
thisworkbook.sheets().showall
On error goto 0

pour enlever l'application éventuelle de filtres. Pour être propre il faudrait utiliser une condition avec autofilter ou un truc du genre mais je ne retiens jamais alors...

Pareil avec

num_ligne = Application.WorksheetFunction.match()

s'il ne trouve rien alors erreur qu'on pourrait traiter avec un nothing. Je fais

On error resume next
num_ligne = Application.WorksheetFunction.match()
On error goto 0

puis si num_ligne>0.

Le contrôle de la date ne fonctionne pas. J'ai mis une date au 45/18/00 et ça a "passé crème" comme dirait ma fille. (24 ans).

et même si la date est correcte, elle n'est pas enregistrée.

Je te regarde ça.

Voilà. Tu avais raison. Par contre il faut l'année sur 4 caractères.

Tu m'as perdu Alex.
en fait, il se passe quoi avec cette instruction ?

"on error goto 0" 

ou

"on error resume next"

C'est ça que je ne comprends pas. (et c'est l'arbre qui cache la forêt du coup avec ton dernier message)

nan, mais laisse tomber pour la date !

  • Resume next dit au code de ne pas s'arrêter en cas d'erreur. Il passe à la ligne suivante sans te faire un message d'alerte et te surligner la ligne en jaune.
  • goto 0 dit au code de ne plus ignorer les erreurs (donc il annule resume next). Ca peut avoir son utilité mais à manier avec précautionS et surtout surtout surtout ne pas oublier de remettre goto 0 dès que tu ne souhaites plus ignorer les erreurs.
image

Pour la date, ne serait ce pas plus facile d'utiliser la fonction DatePiker ?

Oui tu peux mais de là à dire que c'est plus simple.....

C'est plus ergonomique mais pas forcément plus rapide d'aller chercher la bonne date dans DatePiker que de la saisir.

Avec DatePiker tu dois sélectionner la bonne année, puis le bon mois puis le bon jour. C'est peut-être plus sécurisé (puisque la date retournée est forcément valide) et ergonomique mais pas forcément plus rapide. Une question de choix développeur sur ce coup.

Et un TS, si on ajoute une ligne, il ne faut plus mettre à jour les numberformats et les formules.

@BsAlv : Normalement oui mais à condition que l'utilisateur soit sage et qu'il ne modifie pas lui-même la formule ou le format à son bon vouloir. Le fait que je refasse le format de cellule et réinsère la formule permet de forcer les modifications utilisateur.

on ouvre l'userform "ajouterhonda" et la macro "...initialize" appèle la macro "MesTags"

Je n'ai pas encore regardé une seule ligne de code de ce formulaire. A son visuel je ne vois pas de difficultés déjà traitées par le code de ModificationHonda. A priori on retrouve les contrôles de saisie en chiffre, la date puis un report dans la feuille Excel. Tout ceci est présent avec ModificationHonda et pourra donc être transposé.

@BsAlv : Après je suis tout à fait conscient qu'il n'y a pas qu'une seule façon de faire tant au niveau développement, qu'algorithmiquement que selon également les préférences développeur/utilisateur. Si tu peux apporter une autre façon de faire n'hésite pas.

à inclure des images dans le formulaire. (j'ai fais un autre sujet pour ça)

Pas encore regardé. As-tu le lien précis ?

Toute façon de mon point de vue je pense qu'il faut d'abord clore tout le reste de ce formulaire avant d'ouvrir une autre fonctionnalité.

@ papicx : je te laisse pointer le manquant dans le code existant par rapport à ce que tu voulais. Je crois qu'on a fait le tour.

Je me suis aperçu en regardant mieux ton fichier que la date est pour toi facultative. Dans mon dernier fichier je l'ai mise en obligatoire.

Voici en facultatif.

Bonjour,

je viens comme un cheveux sur la soupe, mais Steelson avait créé un fichier ici
Pour les Textebox à surveiller en numérique, il suffit de les nommer NumBox1 etc, et pour les texteBox à surveiller en date il suffit de les nommer en DateBox.
le code fait le reste et cela fonctionne bien.

Je sais cela va perturber un peu la conversation, mais il n'empêche...

@ bientôt

LouReeD

re, salut LouReed,

avec le fichier de Steelson, la macro "test"lance l'userform "AjouterHonda" et dans l'initialize on détermine 5 textboxes "numériques" et un textbox "date".

Cela se fait avec le tableau "Tabel19" de la feuille "Blad1". S'il y a encore des autres boxes à ajouter, il faut le faire dans la colonne 2.

Pour le reste de l'userform (sauvegarder, rechercher, ...) je n'ai pas encore vérifié

Bonjour à tous,

@LouReed : Mais comment tu as bien fait de nous rappeler qu'il y en a qui ont fait des petits fichiers efficaces !

@BsAlv : bien vu l'inclusion du fichier de Steelson dans le formulaire AjouterHonda. Là, pour la saisie de la date, je valide !

La case unique pour saisir la date et qui se met en rouge dès qu'une valeur n'est pas correcte, franchement, c'est top !

Je vais faire le point de toutes les fonctions et voir s'il en manque, mais je pense qu'on a fait le tour.
Reste à mettre à jour tout ça. (car entre-temps, j'ai ajouté des références et mis à jour quelques unes... )

Je reviens vers vous dans qq temps, car j'ai du taf de ouf par ailleurs.
Votre détermination à m'aider me touche.
MERCI à tous.
Bien à vous.

Bonjour,

Merci pour ce retour et bon courage pour la suite.

@ bientôt

LouReeD

https://excel-pratique.com/fr/telechargements/utilitaires/textbox-date-numerique-no517

Cool. Je ne connaissais pas ce fichier. J'aime bien en plus :

  • le modèle de format "__/__/____" qui s'affiche et dont les "_" se remplacent au fur et à mesure de la saisie
  • la saisie du nombre qui intègre automatiquement les séparateurs de milliers

Je n'y avais pas pensé pour le cas Papicx.

Je ne connais pas les modules de classe. Un jour faudra que je me penche dessus.

Papicx à toi de jouer en d'abord comprenant toutes les solutions proposées puis en en choisissant une (quitte à modifier un peu le code donné pour correspondre pile poil à ton besoin). Le but est qu'elle fasse ce que tu souhaites et que tu puisses la maintenir par la suite.

Bonjour BsAlv

avec le fichier de Steelson, la macro "test"lance l'userform "AjouterHonda" et dans l'initialize on détermine 5 textboxes "numériques" et un textbox "date".

Je ne parviens pas à trouver, donc comprendre, à quel ligne le fichier de Steelson (lequel ?) lance la macro. Je suis perdu.

Pourtant, la saisie de la date fonctionne et j'ai voulu le mettre dans le formulaire de modification, mais du coup j'ai été stoppé net dans mon élan, et c'est bien dommage.

J'ai cherché le nom "macro" pour la macro 3 et la macro "test" , je n'ai rien trouvé.
Le montage de ton code semble puissant, mais je galère vraiment à le comprendre.

Bon, j'ai , je pense, compris ce à quoi servait le Blad1
mais pour le fichier de contrôle des boxnumérique, si j'ai bien compris, je devrais renommer mes textbox de prix pour que ça fonctionne ?

re,

J'éspère que quelqu'un autre sait mieux éxpliquer un classe module que moi, français n'est pas ma language maternelle et c'est assez technique , mais savez que c'est un outil puissant.

Bon, au lancement d'un userform, dans le "UserForm_Initialize" on dit quels textboxes et comboboxes sont spéciaux et à traiter avec ces 2 Classemodules.

Vous voyez ici dessous que j'ai (mieux Steelson) 2 matrices NumBox et DateBax avec pour le moment 10 éléments (àmodifier si nécessaire) pour les noms des textboxes/comboboxes à traiter "numériques" ou "date". Pour la simplicité, j'ai créé le tableau "tableau19" sur la feuille "Blad1", comme je l'ai expliqué, il y a quelque jours.

Supposons maintenant l'userform "ModificationHonda" ici dessous. Avec le "UserForm_Initialize()" et X, on a la liste des "controls" qui sont "N" dans la 2eme colonne "Type" et un nom connu (cellule non-vide) dans la colonne 4 (ModificationHonda) et puis dans un boucle, on les ajoute à la matrice NumBox. Pour les dates, la même chose,mais pour le moment, je ne vois pas un textbox type "date" dans ModificationHonda, je pense que ce sont 3 textboxes individuels jour - mois - année. Donc le filtrage dans X a "erreur" comme solution, donc aucun control à traiter comme date.

Bon, à partir de ce moment, les 5 (numériques) et 0 (dates) textboxes , si on fait quelque chose avec eux, ils sont traités dans le classemodule ClasseNumBox et ClasseDateBox. Donc pour éviter chaque confusion, toutes les macros "change" ou "KeyPress" ou "AfterUpdate" de ces5 textboxes, vous devez les supprime. Le "UserForm_Initialize" original, j'ai modifié son nom en ajouter un "X", donc il n'est plus actif, s'il y a des choses nécessaires là-dedans, il faut les copier& coller dans le nouveau "UserForm_Initialize".

Je vois aussi des macros comme "TextBox_10_99Fr_Change", je ne sais pas si ce sont des textboxes spécifiques à traiter d'une manière commune, autrement, on peut créer un autre Classemodule pour ceux.

J'ai, en feuille "Blad1", déjà commencé à complèter le tableau19 avec les noms des textboxes/comboboxes de l'userform "ModificationHonda" dans la 4eme colonne. Les noms qui ne sont pas encore traités sont dans la colonne I. Supposons plus tard, que vous aurez un 3eme groupe de controls et donc un 3eme classemodule, on peut utiliser un autre charactère dans la colonne "Type".

' à mettre dans le code du userform en fonction du nombre de "NumBox"

Dim NumBox(1 To 10) As New ClasseNumBox      ' indiquer le nombre de NumBox
Dim DateBox(1 To 10) As New ClasseDateBox    ' indiquer le nombre de DateBox

Private Sub UserForm_Initialize()
     X = Evaluate("FILTER(Tabel19[ModificationHonda],(Tabel19[Type]=""N"")*(Tabel19[ModificationHonda]<>""""))")
     For i = 1 To UBound(X)
          If UBound(X) = 1 Then Set NumBox(i).NumSaisie = Me(X(i)) Else Set NumBox(i).NumSaisie = Me(X(i, 1))
     Next

     X = Evaluate("FILTER(Tabel19[ModificationHonda],(Tabel19[Type]=""Date"")*(Tabel19[ModificationHonda]<>""""),""Erreur"")")
     If VarType(X) = vbString Then
          MsgBox "il n'y a pas des controls type date", vbInformation, "ModificationHonda"
     Else
          For i = 1 To UBound(X)
               If UBound(X) = 1 Then Set DateBox(i).DateSaisie = Me(X(i)) Else Set DateBox(i).DateSaisie = Me(X(i, 1))
          Next
     End If

     '     Set NumBox(1).NumSaisie = Me("TextBox_Quantité")
     '     Set NumBox(2).NumSaisie = Me("TextBox_DPC_HT_€")

     'For n = 1 To UBound(NumBox): Set NumBox(n).NumSaisie = Me("NumBox" & n): Next
     'For n = 1 To UBound(DateBox): Set DateBox(n).DateSaisie = Me("DateBox" & n): Next
End Sub
Rechercher des sujets similaires à "intialiser nombre decimales afficher userform"