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....)
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 !
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...
@ Jean-Eric : je n'ai pas compris.
@ tous: Merci à fond pour vos contributions !