Contrôler le nb de caractères de 2 cellules

Bonjour à tous.

J'ai beaucoup de mal avec la procédure que je souhaite coder.

Je voudrais simplement contrôler que le nombre de caractères d'une cellule saisie par l'opérateur ne dépasse pas un certain nombre de caractères.

J'ai :

  • Colonne A = Liste de fruits
  • Colonne B = Premier fournisseur (auchan, carefour....)
  • Colonne C = Deuxième fournisseur (auchan, carefour....)
  • Colonne D = Troisième fournisseur (auchan, carefour....)
fournisseur

Je peux avoir un ou plusieurs fournisseurs pour un fruit

La longueur totale du nombre de caractères d'un fruit + d'un fournisseur doit être absolument STRICTEMENT INFÉRIEURE À 15 (donc évidemment pour chaque cellule des colonnes B, C et D), donc:

NBCAR(A3) + NBCAR(B3) < 15

NBCAR(A3) + NBCAR(C3) < 15

NBCAR(A6) + NBCAR(D6) < 15

La longueur du nombre de caractères des fruits est fixe et invariable

La longueur du fournisseur doit "s'adapter" en fonction de la longueur du fruit. La limite est donc définie par:

NBCAR(fournisseur) = 14 - NBCAR (fruit)

J'ai tenté de passé par une macro événementielle (c'est la première fois que je m'y colle) mais ça ne fonctionne pas.

Je souhaite qu'à chaque fois qu'un opérateur modifie une cellule pour ajouter un fournisseur ou modifier un fournisseur, la règle du nb de caractère max soit respectée et contrôler par l’événement "CHANGE" de la macro.

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)

Dim LgAutorisee As Integer 'stocke la longueur autorisée du nb de caractères maximal que peut prendre la cellule target
Dim ColTarget As Integer 'stocke le n° de la colonne de la target

ColTarget = Target.Column

LgAutorisee = 15 - Len(Target.Offset(0, -ColTarget + 1)) 'longueur autorisée = Nb de caractères max - nb de caractères de l'élement en colonne A fixe et invariable
    If Not Application.Intersect(Target, Range("A" & Target.Row & ",C" & Target.Row)) Is Nothing Then
        If Len(Target) > LgAutorisee Then
            Target.Value = Left(Target.Value, LgAutorisee)
        End If
    End If

End Sub

Enfin pourquoi, je ne parviens pas à déclencher le pas à pas ou le déclenchement de ma macro alors que je modifie ma cellule ?

Rien ne se passe quand je modifie une cellule de ma feuille (j'ai bien regardé que la macro était enregistrée dans la sheet concernée !).

Merci d'avance pour votre aide et vos lumières.

Bonjour,

Devant C dans ta condition, pas une virgule, mais :

D'autre part, il serait plus rationnel de faire les précalculs si la condition est satisfaite, plutôt qu'avant le test.

Le cas où A est vide n'est pas pris en compte ? A mon avis cela devrait conduire à annuler l'opération. Par contre l'inclusion de A dans le test conduira à des erreurs.

Enfin, réécrivant dans la zone d'intervention de la proc. il conviendrait de suspendre les évènements durant cette écriture...

Cordialement.

Bonsoir MFerrand.

Pour ce qui concerne la virgule au lieu des 2 points, je voulais signifier le cas des cellules non contigües (Fruit de la colonne A et fournisseur de la colonne D, par exemple). Si je mets les 2 points, je vais "englober" les autres colonnes (B et C) dans la range alors que le calcul ne se fait que sur 2 cellules (Colonne A et une des 3 autres colonnes).

Pour ce qui concerne le cas où A est vide, c'est impossible. Je ne peux pas avoir de fournisseur sans fruit.

Le précalcul est juste là pour alimenter la variable et comme je me suis dit que l'événementiel n'est pas dans la logique de la programmation séquentielle, peu importe où se situe la "concrétisation" de la target puisqu'elle intervient dès lors qu'une cellule est en cours de modification.

"Enfin, réécrivant dans la zone d'intervention de la proc. il conviendrait de suspendre les évènements durant cette écriture..."

J'avoue ne pas avoir compris.

C'est la première fois que je me frotte aux événements et je ne sais pas si je dois raisonner comme avec du séquentiel (vu ce que j'ai osé affirmé un peu plus haut, je dirais non).

Ce code est une adaptation de ce que j'ai trouvé sur la toile.

Il me semble d'ailleurs que ce code tronque lui-même la valeur entrée dans la cellule si le nb de caractères n'est pas celui attendu au moment où l'utilisateur valide la cellule par "entrée".

Initialement, je voulais réaliser cela directement avec les validations des données dans excel mais je n'ai pas su faire.

Je "maitrise" bien mieux VBA que les fonctions excel.

j'ai donc essayé de comprendre le code que j'avais trouvé et j'ai aussi essayé d'appréhender la notion de l'événement et du target.

Pas simple, surtout que mon temps est ultra limité (en dehors de mon temps perso).

Bref, j'avance tout (trop) doucement et je pars essayer d'approfondir le "intersect".

Si vous savez pourquoi quand je touche n'importe quelle cellule de mon tableau, rien ne se produit dans la fenêtre éditeur VBA...

Merci d'être là à veiller...

Bonne soirée.

Re,

Tu testes l'intersection de Target (source du Change) avec la plage où est suceptible d'être inscrit un fournisseur !

Selon ton image, cela inclut au moins les colonnes B C D E et peut-être au-delà. Cela exclut A (fruit et non fournisseur).

Il faut exclure l'en-tête :

If Target.Row < 4 Then Exit Sub

et cadrer l'intervention sur l'inscription d'un fournisseur :

If Not Intersect(Target, Me.Columns("B:E")) Is Nothing Then

Pour ce qui concerne le cas où A est vide, c'est impossible. Je ne peux pas avoir de fournisseur sans fruit.

C'est certainement vrai dans la réalité, mais pas sur le tableau ! Il suffit d'avoir omis de le taper ! Donc si l'utilisateur n'a pas servi A il faut le rappeler à l'ordre !

    Application.EnableEvents = False
    If Me.Range("A" & Target.Row) <> "" Then
        LgAutorisee = 15 - Len(Me.Range("A" & Target.Row))
        If Len(Target) > LgAutorisee Then  Target.Value = Left(Target.Value, LgAutorisee)
    Else
        Application.Undo
    End If
    Application.EnableEvents = True

Donc si A est vide, annuler l'opération. Si OK tu peux alors calculer la longueur autorisée et tronquer s'il y a lieu.

Le tout après avoir suspendu les évènements car sinon ton intervention déclenchera un évènement, ce qu'il vaut mieux éviter !

NB- Je commence par <>"" plutôt que l'inverse, car c'est l'objectif principal et qu'il y a donc lieu de le prioriser (c'est de la logique, mais aussi VBA devrait pouvoir être un chouia plus rapide sur les réactions de choix positif...)

Cordialement.

Bonjour,

en supposant que les fruits sont saisis en premier, une simple validation de donnée personnalisée sur B4:Dxx suffit :

=NBCAR($A4&B4)<15

eric

Bonjour,

Annulé, pas vu les réponses précédentes.

Cdlt.

Bonjour MFerrand, Eriiiic (le vrai frère de Patriiiick ?) et Jean-Eric.

@ MFerrand: Merci pour vos éclaircissements ! J'ai pu faire fonctionner ce code grâce à vous.

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)

Dim LgAutorisee As Integer 'stocke la longueur autorisée du nb de caractères maximal que peut prendre la cellule target
Dim ColTarget As Integer 'stocke le n° de la colonne de la target

ColTarget = Target.Column

If Target.Row < 4 Then Exit Sub 'exclusion de l'en-tête (ligne 3) dans le cas de "Intersect"

    If Not Application.Intersect(Target, Me.Columns("B:E")) Is Nothing Then 'Intersection entre le target (source du change) et plage où est susceptible d'être inscrit un fournisseur
        Application.EnableEvents = False
        If Me.Range("A" & Target.Row) <> "" Then
            LgAutorisee = 31 - Len(Me.Range("A" & Target.Row))
            If Len(Target) > LgAutorisee Then
                Target.Value = Left(Target.Value, LgAutorisee)
                MsgBox "Nombre maximum de caractères du fournisseur dépassé." & Chr(10) & Chr(10) & _
                "Le nom du fournisseur que vous avez saisi a été tronqué volontairement." & Chr(10) & Chr(10) & _
                "Si ce nom de fournisseur tronqué ne vous convient pas, veuillez en saisir un dont la longueur ne dépasse pas:" _
                & LgAutorisee & " caractères."
            End If
        Application.EnableEvents = True
        Else: Application.Undo
        MsgBox "Il ne peut pas y avoir de fournisseur sans élément."
        Application.EnableEvents = True
        End If
    End If

End Sub

J'ai juste rajouté un "Application.EnableEvents = True" dans le cas où il y a un A vide.

@ Eriiiic: J'avais utilisé une validation des données avec NBCAR qui faisait la différence entre la nb total de caractères et celui de la la colonne A mais je ne sais pas à quel moment je n'ai pas su finaliser ma validation.

Et puis je me suis penché à nouveau dessus et j'ai trouvé.

Mais la tentation de me frotter aux événements était trop forte...

2017 04 13 capture137

@ Jean-Eric : je n'ai pas compris.

@ tous: Merci à fond pour vos contributions !

Rechercher des sujets similaires à "controler caracteres"