Comparer deux cellules

Bonjour,

Votre validation de donnée devrait fonctionner aussi en effet. Le plus simple est de travailler avec des tables structurées qui permettent automatiquement d'étendre la formalisation de la ligne précédent à la nouvelle ligne (MEFC, type de donnée, validation des données, liste déroulante, etc etc ....) :

image

Si vous souhaitez tout dans une seule MEFC alors la formule à appliquer serait par exemple de tester si la cellule est vide, ou si la colonne est la 10 (colonne J) et si la valeur est inférieur a G2 :

=OU(B2="";ET(COLONNE(B2)=10;B2<=$G2))

A traduire en VBA.

Cdlt,

C'est à dire que si je mets mon onglet sous forme de tableau il va étendre ma validation de données de manière automatique sans que je demande mais tout en faisant bien les changements dans la formule par rapport aux lignes ?

Si vous souhaitez tout dans une seule MEFC alors la formule à appliquer serait par exemple de tester si la cellule est vide, ou si la colonne est la 10 (colonne J) et si la valeur est inférieur a G2 :

Je vais regarder ça mais le problème c'est que je ne vois pas comment je pourrais intégrer le message d'erreur dans la MsgBox car il est possible que ce ne soit pas toujours faux. Mon but serait par exemple de dire : "LES CELLULES SURLIGNEES DOIVENT ETRE REMPLIE ET LE PRIX DU METRE CARRE RECTO VERSO DOIT ETRE SUPERIEUR OU EGAL AU PRIX DU M2 RECTO" mais comme il est possible que la deuxième erreur ne soit pas toujours là comment faire ?

J'aurais une autre petite question j'essaie d'ajouter ma suppression d'accent dans le Worksheet_Change :

Private Sub Worksheet_Change(ByVal Target As Range)
    Application.EnableEvents = False
    If Not Intersect(Target, Range("A2:A" & Cells(Rows.Count, Target.Column).End(xlUp).Row)) Is Nothing Then
        For I = 1 To 10
            Target.Offset(0, I).Value = ""
        Next I
    End If
    Target.Value = UCase(Target.Value)
    Target.Value = SupprimerAccents(Target.Value)
    Application.EnableEvents = True
End Sub

Mais lorsque je sélectionne deux lignes et que je supprime je me retrouve avec un problème "13" et le message pointe :

Target.Value = UCase(Target.Value)

Qu'est-ce que j'ai fait de mal dans cette partie ?

Merci d'avance !

Bonjour,

Un exemple dans le fichier joint.

Pour ce qui est des messagesbox, vous vous compliquez la vie. Restez global dans son intitulé en indiquant que les données ne sont pas valides dans les cellules surlignées et ensuite c'est la liste de validation qui va afficher le message d'erreur plus spécifique. Vous pouvez de plus ajouter une infobulle sur la cellule pour aiguiller l'utilisateur (Cf colonne J fichier joint).

Pour l'erreur 13 elle arrive parfois lorsque l'on supprime une valeur qui est considéré comme un changement de valeur. Comment mettre une valeur vide en majuscule ? Donc j'ai rajouté une conditions dans le code. Je ne comprend pas pourquoi vous vous embêtez avec cette fonction personnalisé alors que votre liste de validation pourrait faire le travail ? J'ai du mal à voir le cas où elle va s'appliquer.

La plage a été transformée en table structurée. Comme vous pouvez le voir, si vous ajoutez une valeur en A5 alors les listes de validation sont également copiées de la ligne au dessus.

Pour simplifier le tout j'ai regrouper les codes en Feuille modèle et Module 1.

La formule de la MEFC a également été adaptée suivant notre échange.

Cdlt,

Pour l'erreur 13 elle arrive parfois lorsque l'on supprime une valeur qui est considéré comme un changement de valeur. Comment mettre une valeur vide en majuscule ? Donc j'ai rajouté une conditions dans le code. Je ne comprend pas pourquoi vous vous embêtez avec cette fonction personnalisé alors que votre liste de validation pourrait faire le travail ? J'ai du mal à voir le cas où elle va s'appliquer.

En fait la personne va venir mettre un nom dans la colonne D (Modèle), mais ce nom doit forcément être différent de la matière, et le problème c'est que par exemple si je sélectionne : HETRE ABOUTE en matière (pas présent sur le fichier actuel à moins de changer le numéro dans l'onglet généralités avec celui-ci : 200002) alors j'ai déjà eu une personne qui derrière à mit en colonne D : hêtre abouté. Sauf que ce n'est pas la valeur attendu et sans suppression d'accent plus mise en majuscule je ne peux pas vérifier que ce n'est pas le cas (je ne sais pas si je suis plus clair comme ça haha)

Du coup j'ai essayé avec votre code mais j'ai :

image image

Pour la partie tableau j'observe que je risque de créer des erreurs en effet si je descend pas le tableau très bas la personne va pouvoir rentrer n'importe quelle valeur et faire "sauter le code" car ça ne correspondra pas à mes données dans les listes déroulantes c'est pour ça que je descend jusque environ 500/600 lignes de manière automatique et ensuite je verrouille le fichier pour éviter les copier/coller ou autre abus

Merci encore à vous du temps :)

Bonjour,

Ben pourquoi en D2 vous ne faîtes pas = A2 dans ce cas ? A quoi elle sert cette colonne D ? Liste de validation ou champ libre ? Il est réutilisé où ? Dans quel but ?

Je me rend compte que je me suis planté dans mon bout de code :

Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If IsEmpty(Target) Then Exit Sub
Target = UCase(Target)
Target = SupprimerAccents(Target)
Application.EnableEvents = True
End Sub

Pour le tableau peut importe, mais il faut que vous anticipiez les listes de validation sur toutes les lignes alors. C'est à vous de voir comment vous souhaitez le construire en fonction du besoin. Je ne propose que des pistes de réflexions les plus "simples" à appréhender.

Cdlt,

Justement la colonne D2 doit être totalement différente de la colonne A2, le problème c'est que j'ai des fournisseurs qui renseignent le même c'est pour cela que je veux mon message d'erreur, leur disant que ça doit être un nom qui n'est pas la matière renseignée

J'ai une autre petite question sur ça :

=OU(B2="";ET(COLONNE(B2)=10;B2<=$G2))

Je ne comprends pas trop, vous dites en soit que la colonne J se transforme en colonne B ce qui fait qu'elle ne doit pas être vide c'est ça ? mais le problème c'est que si je rentre quand même une donnée inférieure je n'ai pas la MEFC qui opère

Pour le tableau peut importe, mais il faut que vous anticipiez les listes de validation sur toutes les lignes alors. C'est à vous de voir comment vous souhaitez le construire en fonction du besoin. Je ne propose que des pistes de réflexions les plus "simples" à appréhender.

Depuis le début vous ne faites que me donner de très bons conseils et j'en apprends plus donc ce n'est pas contre vous mon message, je réfléchis aussi par écrit j'ai peur d'éventuel erreur (quand je vois comment des fois les fichiers sont remplis et renvoyer un peu à l'arrache je préfère voir toutes les éventualités et encore là je peux être surpris haha)

Merci à vous !

EDIT : Je viens de tester votre bout de code

Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If IsEmpty(Target) Then Exit Sub
Target = UCase(Target)
Target = SupprimerAccents(Target)
Application.EnableEvents = True
End Sub

Malgré tout j'obtiens toujours l'erreur si je supprimes plusieurs lignes en une fois, je suis en train de me dire que je risque de devoir faire sans cette vérification (peut être une bulle suffira a expliquer ..)

Bonjour,

Oui mais la valeur en D2 vous l'analysez ensuite ? Ou vous vous en fichez ?
- Si vous l'analysez > Liste de validation différente de celle en colonne A
- Si vous ne l'analysez pas > On laisse le champ libre car on s'en "fiche"

Pour la MEFC : Non. Elle s'applique dans 2 cas :
- Cellule vide (B2 = "")
- Colonne = 10 ET valeur de la cellule <=$G2 ce qui me permet de me limiter à la colonne J via le colonne = 10. En effet quand on regarde sur B2, la colonne c'est 2, donc forcément renvoie faux. Quand on arrive a J2 alors le numéro est bien 10. Dans ce cas on regarde aussi si J2<=$G2. Car B2 n'était pas une référence absolue, donc quand on est en J2 alors on regarde la valeur de J2.

Ici elle ne fonctionne pas car je me suis planté dans la plage d'application de la MEFC, en effet elle ne s'étend que jusqu'à la colonne 9, soit la I. Donc modifier ce passage du code :

        With Range(.Cells(2, 2), .Cells(LR, 11))
            .FormatConditions.Add xlExpression, , "=OU(B2="""";ET(COLONNE(B2)=10;B2<=$G2))"
            .FormatConditions(1).Interior.COLOR = 7697919
        End With

Cdlt,

Edit : C'est sûr que si vous supprimer une plage votre code ne pourra fonctionner car il faudra itérer le code pour chaque cellule de la selection target. C'est pour ça que j'insiste pour que vous vous posiez la question de l'intérêt de ce passage. Au lieu d'autoriser des libertés à l'utilisateur puis de les contrôler, restreignez les dès le début !

Pourquoi du coup il faut mettre B2<=$G2 ?

Je suis perdu sur cette formule mon cerveau fait un arrêt je ne sais pas pourquoi

En tout cas pour cette partie :

Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If IsEmpty(Target) Then Exit Sub
Target = UCase(Target)
Target = SupprimerAccents(Target)
Application.EnableEvents = True
End Sub

C'est un peu choux blanc je ne trouve pas de solution j'ai essayé en faisant Not IsEmpty aussi en me disant qu'en faisant l'inverse ça serait peut être ok mais non l'erreur 13 ressort tout le temps ce qui fait qu'au final, même en quittant l'erreur le texte ne passe plus du tout en majuscule etc ça fait planter le fichier

EDIT : Oui mais le problème c'est que même si je fais validation différente de colonne A si la personne ne passe pas par des majuscules pour la validation ça sera ok c'est ça le problème et pareil si l'utilisateur utilise des accents je me sens bloqué à cause de ça ..

Bonjour,

Car ma plage d'application débute en B2. Si je met J2<=$G2 en débutant ma plage d'application en B2 alors B2 sera coloré en fonction de la valeur de J2 ! Donc si je mets B2, je le compare à G2 mais je m'en fiche, la colonne n'est pas 10. Quand j'arrive sur J2 alors la colonne de J2 est bien 10, et je le compare bien a G2. Ici la colonne n'est pas décalée car j'ai le $ devant le G, donc toutes mes colonnes seront comparées à G2.

Bien sûr qu'il ne passe pas en majuscule, la macro événementielle n'étant pas executée. Lisez mon EDIT de mon post précédent et posez vous la question du pourquoi j'ai besoin d'avoir des majuscules ? Qu'est ce que je fais de cette data ? Parce que je n'ai toujours pas compris son objectif ..

Cdlt,

Car ma plage d'application débute en B2. Si je met J2<=$G2 en débutant ma plage d'application en B2 alors B2 sera coloré en fonction de la valeur de J2 ! Donc si je mets B2, je le compare à G2 mais je m'en fiche, la colonne n'est pas 10. Quand j'arrive sur J2 alors la colonne de J2 est bien 10, et je le compare bien a G2. Ici la colonne n'est pas décalée car j'ai le $ devant le G, donc toutes mes colonnes seront comparées à G2.

Merci je comprends mieux maintenant

Je veux bien restreindre dès le début mais comment faire ? Car si je mets que ça ne doit pas être égal à A2 il peut contourner, et comme c'est une donnée qui provient de leur data à eux je ne peux pas prévoir déjà les noms qu'ils vont rentrer (impossible de faire une liste déroulante). Donc c'est pour ça que je galère Le fait de restreindre dès le début me permettra d'éviter 40 allers retours avec eux. Mais le problème c'est que je n'ai pas de solution de restriction ou je ne les vois clairement pas (sans passer par suppression d'accent et de majuscule)

Bonjour,

Mais si ça vient de chez eux, et que tu t'en "fiche" alors pourquoi tu t'embêtes à standardiser sans accents/majuscule, et tout le bordel ? Si il t'écrit un jour hetre hérable, l'autre etre hérable et l'autre etre erable, tu vas faire quoi ? Tu as tes références à toi c'est tout ce qui compte non ?

C'est là où j'ai du mal à comprendre cette détermination à vouloir formaliser un champ donc tu te fiches (et c'est pour ça que je m'obstine lol)

Cdlt,

En fait,

Bien souvent c'est juste que le fournisseur ne fait pas attention et remet de lui même le même nom que la matière sauf qu'il va l'écrire en minuscule ou avec des accents, mais c'est impossible que son nom de produit soit le même que la matière du produit.

Par exemple il va mettre :

Matière

Modèle

STRATIFIEStratifié

Alors qu'en vrai ça devrait être :

Matière

Modèle

STRATIFIEZèbre

C'est ça le gros soucis et moi derrière je suis obligé de retourner vers eux en disant : "non la colonne modèle correspond au nom de votre produit ou à l'huile appliquée et non pas à la matière"

Sauf que ça fait faire des aller-retour pour rien et potentiellement sur plusieurs centaines de lignes (et plusieurs fichiers) je risque de ne pas voir l'erreur si elle n'est faite que sur une ligne.

Je ne sais pas si je suis plus clair dans mes explications. En fait ce n'est pas que je m'en fou de la colonne au contraire c'est que le nom ne vient pas de moi donc si en vrai le fournisseur à appeler son produit "champignon mario" ça me regarde pas mais il est impossible que ce soit le même nom que la matière et donc que la colonne A (sauf que comme ils tapent des fois en minuscule ou avec des accents je suis obligé de faire un Ucase et SupprimerAccents).

Dis-moi si j'ai réussis à mieux expliquer le problème :)

Merci à toi !

Bonjour,

Alors il faut l’aiguiller dans ce sens via infobulle ou renommer l'intitulé de la colonne pour le rendre plus explicite quitte à mettre un exemple. En attendant d'avoir un retour sur l'utilisation d'un fichier :

Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Target, [D2:D500]) Is Nothing Then
    If Selection.Count > 1 Then
    Application.EnableEvents = False
        Application.Undo
        MsgBox "Vous ne pouvez pas supprimer plusieurs cellules à la suite", vbCritical
        Exit Sub
        Application.EnableEvents = True
    End If
    If UCase(SupprimerAccents(Target)) = Target.Offset(0, -3) Then
        Application.Undo: MsgBox "Merci d'inscrire votre modèle et non notre référence"
        Else
        Application.EnableEvents = False
        Target = UCase(SupprimerAccents(Target))
        Application.EnableEvents = True
    End If
End If
End Sub
Function SupprimerAccents(ByVal sChaine As String) As String
Dim sTmp As String, i As Long, p As Long
Const sCarAccent As String = "ÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöùúûüýÿ"
Const sCarSansAccent As String = "AAAAACEEEEIIIINOOOOOUUUUYaaaaaaceeeeiiiinooooouuuuyy"
    sTmp = sChaine
    For i = 1 To Len(sTmp)
        p = InStr(sCarAccent, Mid(sTmp, i, 1))
        If p > 0 Then Mid$(sTmp, i, 1) = Mid$(sCarSansAccent, p, 1)
    Next i
    SupprimerAccents = sTmp
End Function

Comme vous pouvez le constater, envisager toutes les possibilités d'un évènement Worksheet_Change prend de plus en plus de place. Je me demande si au final il ne vaudrait mieux pas le mettre dans la macro de vérification des data.

A vous de voir ..

Cdlt,

Hello

Effectivement je vois que c'est plutôt compliqué d'intégrer directement dans un worksheet_change, donc soit je repasse sur ma méthode précédente c'est à dire dans la vérification de data dans ce cas je me dis que j'accepte un temps augmenté car il va devoir check toutes les cellules une par une (enfin sur mon premier fichier c'est surtout ça qui me donnait un temps long dans l'exécution) ou alors je mets des infobulles sur toute la colonne avec aussi le message dans l'intitulé et si le fournisseur se trompe alors j'accepte un temps d'aller-retour

En tout cas et même si ce n'est pas beaucoup à mon sens je te dis un énorme merci à toi Ergotamine tu as passé énormément de temps à m'aider et m'expliquer et franchement ça m'a beaucoup fait progresser !

J'aurais une dernière question sais-tu si il est possible de verrouiller la MEFC et la validation de données, c'est à dire rendre impossible de le fait de supprimer sur une cellule la validation de données ou la MEFC tout en laissant forcément la possibilité de rentrer une valeur dans cette cellule ?

Merci encore,

Cordialement,

Bonjour,

Ne limitez la macro qu'à la colonne D jusqu'à la dernière ligne remplie du tableau, ça réduira drastiquement le temps d’exécution.

Si je ne dis pas de bêtises, la MEFC et la validation de données sont protégées lorsque vous activez la protection de la feuille. En tout cas c'est moi cela devient grisé. Par contre il faudra anticiper cette protection/deprotection dans la macro VBA également au niveau de la vérification des données comme nous intégrons une MEFC.

Cdlt,

Ne limitez la macro qu'à la colonne D jusqu'à la dernière ligne remplie du tableau, ça réduira drastiquement le temps d’exécution.

Avec cette partie de code je me limite bien qu'à la colonne D je me trompe ?

Cells(a, 4).Value = UCase(Cells(a, 4)): Cells(a, 4).Value = SupprimerAccents(Cells(a, 4))

Par contre il faudra anticiper cette protection/deprotection dans la macro VBA également au niveau de la vérification des données comme nous intégrons une MEFC.

C'est à dire ? Je ne comprends pas trop ? Il faut que j'ôte la protection pendant l'exécution de la macro puis qu'à la fin je remette la protection c'est ça ?

Je viens de modifier le code pour faire comme ça :

With Sheets("Modèle")
LR = .Cells(.Rows.Count, 4).End(xlUp).Row
For L = 2 To LR
If .Cells(L, 4).Value <> "" Then
.Cells(L, 4).Value = UCase(Cells(L, 4)): Cells(L, 4).Value = SupprimerAccents(Cells(L, 4))
End If
Next L
End With

Qu'en penses-tu ?

C'est peut-être moi mais j'ai l'impression que c'est plus rapide qu'avec l'autre

Cordialement

Bonjour,

Oui c'est normal que ce soit plus rapide dès lors qu'on limite la plage d’exécution.

En soit le code final devrait ressembler à ça :

Sub verifier_finitions_V2()
Dim ERREUR As Boolean, L%, i%, LR%
With Sheets("Modèle")
    LR = .Cells(.Rows.Count, 1).End(xlUp).Row
    For L = 2 To LR
        If .Cells(L, 4) <> "" Then
            .Cells(L, 4) = UCase(SupprimerAccents(.Cells(L, 4)))
            If .Cells(L, 4) = .Cells(L, 1) Then ERREUR = True
        End If
    Next L
    For L = 2 To LR
        For i = 2 To 9
            If .Cells(L, i).Value = "" Then
                ERREUR = True
                Exit For
            End If
        Next i
    Next L
    If ERREUR = True Then
        .Unprotect "MDP"
        If .Cells.FormatConditions.Count > 0 Then
            .Cells.FormatConditions.Delete
        End If
        With Range(.Cells(2, 2), .Cells(LR, 9))
            .FormatConditions.Add xlExpression, , "=OU(B2="""";ET(COLONNE(B2)=10;B2<=$G2);ET(COLONNE(B2)=4;B2=$A2))"
            .FormatConditions(1).Interior.COLOR = 7697919
        End With
        MsgBox "LES CELLULES SURLIGNEES NE SONT PAS VALIDES", vbCritical, "CELLULES ATTENDANT DES VALEURS"
        .Protect "MDP"
        Else
        MsgBox "LA VALIDATION EST CONFORME", vbInformation
        Worksheets("Dimensions").Visible = xlSheetVisible
    End If
End With
End Sub

Avec une feuille initialement protégée via le mot de passe "MDP". J'ai re modifié la MEFC pour qu'on ai une vérification colonne D VS colonne A, et passé la suppression de la MEFC que dans le cas où ERREUR = True afin de ne pas avoir à déprotéger pour supprimer la MEFC, reprotéger puis redéprotéger pour réappliquer la MEFC.

Cdlt,

J'ai une petite question, j'ai fait un test mais lorsque je fais un copier/coller dans la cellule J2 avec une valeur inférieur à G2 alors il me valide la donnée et en plus la vérification avec la macro me dit ok aussi, est-ce parce que je dois étendre la partie :

With Range(.Cells(2, 2), .Cells(LR, 9))
            .FormatConditions.Add xlExpression, , "=OU(B2="""";ET(COLONNE(B2)=10;B2<=$G2);ET(COLONNE(B2)=4;B2=$A2))"
            .FormatConditions(1).Interior.COLOR = 7697919

Ou alors aucun rapport ?

J'aimerais en faites que si ma cellule J2 est remplie alors la vérification doit avoir lieu (aussi bien dans la colonne J que K)

Merci à toi !

Bonjour,

Un copier/coller n'est pas considéré comme une validation de donnée, en effet on ne "rentre pas" dans la cellule, on dépose juste quelque chose dessus. Alors on pourrait contrôler via un Worksheet_Change, etc ... Mais on revient à la problématique d'hier et ce matin.

Pour ce qui est de la MEFC en effet je suis parti d'un ancien code et vu le nombre de modification que nous avons eu j'ai oublié d'étendre la plage et vous avez parfaitement identifié l'endroit à modifier, félicitations :

Sub verifier_finitions_V2()
Dim ERREUR As Boolean, L%, i%, LR%
With Sheets("Modèle")
    LR = .Cells(.Rows.Count, 1).End(xlUp).Row
    For L = 2 To LR
        If .Cells(L, 4) <> "" Then
            .Cells(L, 4) = UCase(SupprimerAccents(.Cells(L, 4)))
            If .Cells(L, 4) = .Cells(L, 1) Then ERREUR = True
        End If
    Next L
    For L = 2 To LR
        For i = 2 To 9
            If .Cells(L, i).Value = "" Then
                ERREUR = True
                Exit For
            End If
        Next i
    Next L
    If ERREUR = True Then
        .Unprotect "MDP"
        If .Cells.FormatConditions.Count > 0 Then
            .Cells.FormatConditions.Delete
        End If
        With Range(.Cells(2, 2), .Cells(LR, 11))
            .FormatConditions.Add xlExpression, , "=OU(B2="""";ET(COLONNE(B2)=10;B2<=$G2);ET(COLONNE(B2)=4;B2=$A2))"
            .FormatConditions(1).Interior.COLOR = 7697919
        End With
        MsgBox "LES CELLULES SURLIGNEES NE SONT PAS VALIDES", vbCritical, "CELLULES ATTENDANT DES VALEURS"
        .Protect "MDP"
        Else
        MsgBox "LA VALIDATION EST CONFORME", vbInformation
        Worksheets("Dimensions").Visible = xlSheetVisible
    End If
End With
End Sub

Cdlt,

Rechercher des sujets similaires à "comparer deux"