Grand Défi VBA - Comparaison et formattage conditionnel assez délicat

Bonjour tout le monde,

je suis tout nouveau dans le monde de vba..j'ai un tableau d'une centaines de lignes et colonnes où je dois faire un formattage conditionnel.

la première colonne dresse les années (2015-2016-2017), la deuxième colonne (les clients) et les autres colonnes, les montants des contrats.

on me demande de chercher si la valeur de contrat a diminué d'une anné à l'autre et si c'est le cas colorer la cellule correspondant à la valeur qui contient le montant le plus bas.

il s'agit pas de chercher la valeur la plus bas pour tout une colonne mais pour chaque client pour trois années (A chaque 3 lignes de la colonne donc pour chaque client, il faut comparer la valeur de 2015 avec 2016 et 2017, ressortir la valeur la plus bas puis colorer cette valeur uniquement si ca tombe dans l'anné la plus récente (selon la comparaison) ( si par exemple en 2017 on n'a pas de valeur, on compare 2015 et 2016 puis si la valeur en 2016 est inférieur à celle en 2015 on colore la valeur en 2016, sinon on fait rien

pour comprendre de quoi il s'agit, J'ai joint un exemple en Excel avec deux onglets, un onglet de données exemple et un onglet du résultat souhaité...

je chercher donc un macro qui:

  • pour chaque client et chaque contrat, il compare les valeurs de contrat des trois années.
  • pour chaque client et chaque contrat, si la valeur de contrat d'une année est vide, il l'ignore et compare les valeurs entre les deux autres.
  • pour chaque client et chaque contrat, il met en couleur la valeur la plus faible (de la comparaison) UNIQUEMENT lorsque cette valeur se retrouve dans l’année la plus récente.
Merci beaucoup!

Pour ceux qui viennent de voir ce post, merci de lire mes réponses pour ne pas gaspiller vos efforts

Bonjour kasper2004, bienvenue sur le forum,

à tester,

Sub test()
n = Cells(Rows.Count, 1).End(xlUp).Row
For col = 3 To 7
 For i = 2 To n Step 3
  For k = i + 2 To i + 1 Step -1
    If Cells(k, col) <> 0 Then
     m = Application.Min(Range(Cells(i, col).Address, Cells(k, col).Address))
     If Cells(k, col) = m Then Cells(k, col).Interior.Color = 49407: Exit For
    End If
  Next
 Next
Next
End Sub

Bonjour,

Bravo Isabelle qui a relevé le grand défi VBA !

L'une des premières règles du VBA est aussi de savoir ... s'en passer. Voici une solution sans VBA !

sabV...Merci bcp pour le code..je ne sais pas il y a qq chose qui marche pas avec la 3ème ligne (celle de l'anné 2017). il y a d'autres commentaires que j'ai mis sur le fichier ci-joint. Dans ce fichier j'ai rempli les cellules du tableau avec tous les cas possible pour que tu ailles une idée..mais vraiment tu es très proche de la solution...Bravo!!!!...après avoir réussi à écrire le bon code, J'aimerais bien que tu me montreras comment passer de 4 colonnes à des milliers...même chose pour les lignes...Merci Infiniment pour ton aide!

Steelson, Merci pour votre message...mon fichier de travail comme j'ai mentionné comporte des centaines de colonne et des miliers de lignes et je pense pas que ta method marcheras pour un fichier volumineux. l'exemple joint au premier message c juste un tout tout petit tableau pour tester le macro.

Merci infiniment à tous ceux et celles qui vont participer à la resolution de ce cas un peu complexe pour moi.

Bonjour,

Une piste un peu similaire à celle de sabV avec une boucle en moins mais une batterie de tests :

Sub Test()

    Dim C As Range
    Dim Col As Long
    Dim Lig As Long
    Dim DerLig As Long
    Dim I As Integer

    DerLig = Cells(Rows.Count, 1).End(xlUp).Row

    For Col = 4 To 8: For Lig = DerLig To 2 Step -3

            Set C = Cells(Lig, Col) 'pour raccourcir un peu les lignes !

            If C.Value <> "" Then

                If C.Offset(-1).Value <> "" Then

                    If C.Value < C.Offset(-1).Value Then C.Interior.Color = 49407

                Else

                    If C.Value < C.Offset(-2).Value Then C.Interior.Color = 49407

                End If

            Else

                If C.Offset(-1).Value <> "" Then If C.Offset(-1).Value < C.Offset(-2).Value Then C.Offset(-1).Interior.Color = 49407

            End If

    Next Lig, Col

End Sub

Steelson, Merci pour votre message...mon fichier de travail comme j'ai mentionné comporte des centaines de colonne et des miliers de lignes et je pense pas que ta method marcheras pour un fichier volumineux. l'exemple joint au premier message c juste un tout tout petit tableau pour tester le macro.

Non c'est un a priori erroné. mais <isabelle a parfaitement répondu ... en VBA.

Bonjour Theze,

Merci pour votre effort.malheureusement votre code ne donne pas le résultat souhaité. peut être que j'ai mal expliqué ma demande

En fait le macro doit travailler en deux étapes: comparaison et mise en forme.

le macro doit comparer les trois cellules corespondant aux années 2015,2016 et 2017 pour chaque client et chaque contrat.Par exemple (pour le client 2 et le contrat 3, il doit comparer les cellules F5,F6 et F7. Dans ce cas, il y a trois possibilités:

1-1- si l'une des trois cellules est vide , il va l'ignorer et comparer les deux autres. Dans ce cas il y a deux possibilities:

1-1-a si la valeur la plus petite de la comparaison est celle de l'année la plus récente, il met cette valeur en couleur.

1-1-b sinon, il ne met pas de couleur

1-2- si il y a juste une seule cellule parmi les trois qui contient une valeur, il fait rien.

1-3 si les trois cellules contiennet des valeurs, il va ignorer l'année 2015 et comparer les valeurs de 2016 et 2017. deux cas qui se présentent:

1-3-a si la valeur la plus petite de la comparaison est celle de l'année la plus récente, il met cette valeur en couleur.

1-3-b sinon, il ne met pas de couleur.

le macro doit alors contenir des conditions imbriquées et des boucles pour parcourir les colones par un step de 1 à partir de la colonne D et les lignes par un step de 3 à partir de la ligne 2 comme il a fait SabV.

je rejoint le fichier. il y a deux onglets: Onglet Données et Onglet résultat souhaité. Dans ce fichier, J'ai mis tous les possibilities de comparaison et le résultats que le Macro doit normalement faire sortir.

A vos clavier!

Merci à tous le monde

Kasper ... c'est ce qui s'appelle faire compliqué quand on peut faire simple via la MFC (qui plus est n'a pas besoin d'être activée car elle tient compte des modifications naturellement, comme tout format du reste).

Mais c'est toi le "client", c'est toi qui choisis.

Salut Kasper,

salut l'équipe,

tiens donc, la structure du fichier a déjà changé depuis le premier post!

Heureusement que j'ai attendu un peu!

Pas le temps de peaufiner pour l'instant : premier jet!

Un double-clic en 'Données' démarre la macro.

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'
Dim tData
Cancel = True
Application.ScreenUpdating = False
'
tData = Range("A1").Resize(UsedRange.Rows.Count, UsedRange.Columns.Count).Value
For x = 2 To UBound(tData, 1) - 2 Step 3
    For y = 4 To UBound(tData, 2)
        iIdx = 0
        If tData(x + 2, y) <> "" Then
            If tData(x + 1, y) <> "" Then
                iIdx = IIf(tData(x + 2, y) < tData(x + 1, y), 2, 0)
            Else
                iIdx = IIf(tData(x + 2, y) < tData(x, y), 2, 0)
            End If
        Else
            If tData(x + 1, y) <> "" Then iIdx = IIf(tData(x + 1, y) < tData(x, y), 1, 0)
        End If
        Cells(x + iIdx, y).Interior.Color = IIf(iIdx > 0, RGB(215, 215, 215), xlNone)
    Next
Next
'
Application.ScreenUpdating = True
'
End Sub

A+

Je suis tenace je sais, ne serait-ce que pour soigner mes neurones....

j'ai refait la MFC pour tenir compte de toutes tes règles

salut curulis57,

Ton macro marche super bien! Merci!!

j'ai trois questions :

1- est ce possible d'associer un bouton au code au lieu de faire un double clique..comme ça si une valeur change, on refait la mise en forme?

2- si jamais au lieu d'avoir 3 ans de données j'ai par exemple 5 ou 10, je pense que je dois changer step dans le code..c ça?

3- y a-t-il une possibilté d'améliorer le code de telle sorte qu'à l'exécution de macro, il me sort une fenêtre de dialogue pour que je choisisse mes x et y au lieu de les fixer à 2 et 4 respectivement ou de les changer dans le code à chaque fois. genre demander à l'utilisateur des i, j et changer le code :

For x = i To UBound(tData, 1) - 2 Step 3

For y = j To UBound(tData, 2)

voilà...Merci à tous les personnes qui ont participé. vous êtes tous géniaux...bravo! ..grâce à vous tous j'ai adoré ce forum et attendez d'autres défis

Merci Steelson,

tu es un génie de MFC

moi, j'ai trouvé la lampe d'Aladdin, mais en la frottant, j'ai pas eu d'chance : y'a aucun génie MFC qui est apparu !

c'est sûrement pour ça qu'toutes mes MFC foirent lamentablement !

Merci Steelson,

tu es un génie de MFC

merci pour ton humour ... sarcastique, mais tu y viendras ...

moi, j'ai trouvé la lampe d'Aladdin, mais en la frottant, j'ai pas eu d'chance : y'a aucun génie MFC qui est apparu !

c'est sûrement pour ça qu'toutes mes MFC foirent lamentablement !

ah mais mon cher Dhany, tu dis cela mais je suis sûr de ton humilité dans ce domaine

bonjour à tous

vous me connaissez, je préfère, et de très loin, la solution de Steelson par MFC

les MFC sont plus simples, et pas moins rapides, même sur des milliers de données.

et une fois que tu as compris, pas besoin de faire appel à des spécialistes pour en refaire (contrairement à VBA)

note : d'une manière générale, c'est une mauvaise idée de créer par VBA ce qui existe déjà.

amitiés à tous

Bonjour,

les MFC sont plus simples,

d'accord

et pas moins rapides, même sur des milliers de données.

ça, ça reste à voir...

On ne compte plus sur les forums les fichiers devenus impossibles à utiliser suite aux lenteurs à cause de trop nombreuses MFC, et qui retrouvent toute la réactivité dès leur suppression.

Je me demande d'ailleurs si elles ne sont pas volatiles vu le fort impact qu'elles ont.

eric

Salut tout le monde,

je te remercie, jmd, au nom de tous ceux qui préfèrent (aiment) VBA, de nous considérer comme des spécialistes!

Des amateurs éclairés, au mieux, dirais-je!

Voici une macro (toujours activable par double-clic) qui traitera un nombre d'années indéterminé et variable dans une même BDD automatiquement sans demander aucune info à l'utilisateur.

Condition pour que cette version ci fonctionne : que le nom des clients figure sur chaque ligne comme illustré dans le fichier-exemple.

Là, jmd et Steelson, avec tout mon respect, j'attends la MFC qui en fera autant (même si je l'espère, histoire d'en apprendre un peu plus...)!

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'
Dim tData, iStart%
Cancel = True
Application.ScreenUpdating = False
'
Range("D2").Resize(UsedRange.Rows.Count, UsedRange.Columns.Count).Interior.Color = xlNone
tData = Range("A1").Resize(UsedRange.Rows.Count + 1, UsedRange.Columns.Count).Value
iStart = 2
For x = 3 To UBound(tData, 1)
    If tData(x, 2) <> tData(x - 1, 2) Then
        iStop = x - 1
        For y = 4 To UBound(tData, 2)
            For Z = iStop To iStart + 1 Step -1
                iOK = 0
                If tData(Z, y) <> "" Then
                    iOK = 1
                    For w = Z - 1 To iStart Step -1
                        If tData(w, y) <> "" Then
                            If tData(w, y) > tData(Z, y) Then
                                Cells(Z, y).Interior.Color = RGB(215, 215, 215)
                                iOK = 1
                            End If
                            Exit For
                        End If
                    Next
                End If
                If iOK = 1 Then Exit For
            Next
        Next
        iStart = x
    End If
Next
'
Application.ScreenUpdating = True
'
End Sub

Kasper, avant de m'attaquer à une macro sensible au changement, de quel(s) changement(s) parles-tu :

  • un changement de montant ?
  • une insertion/suppression de ligne (année) ?

A+

Là, jmd et Steelson, avec tout mon respect, j'attends la MFC qui en fera autant (même si je l'espère, histoire d'en apprendre un peu plus...)!

je veux bien essayer, avec mon petit niveau en MFC (je galère parfois)

mais il faut me dire ce que tu veux

note : je fais des MFC utiles mais je refuse tout net de bricoler des tonnes de MFC qui prétendent transformer Excel en sapin de Noël inutilement. Comme on l'a vu dans des fils précédents.

jmd a écrit :

note : je fais des MFC utiles mais je refuse tout net de bricoler des tonnes de MFC qui prétendent transformer Excel en sapin de Noël inutilement. Comme on l'a vu dans des fils précédents.

ça, faut avouer qu'y'en a qui lésinent pas sur les MFC !

et c'est un gros euphémisme vu qu'parfois, c'est à tire-larigot !

en veux-tu ? en voilà ! oui, jmd a raison : un vrai sapin d'Noël !

dhany

curulis57 a écrit :

Kasper, avant de m'attaquer à une macro sensible au changement, de quel(s) changement(s) parles-tu :

  • un changement de montant ?
  • une insertion/suppression de ligne (année) ?

ca se peut arriver les deux Mr Excel VBA

t'es vraiment un génie Est ce que tu peux me répondre à mes questions:

1- est ce possible d'associer un bouton au code au lieu de faire un double clique..comme ça si une valeur change, on refait la mise en forme?

2- y a-t-il une possibilté d'améliorer le code de telle sorte qu'à l'exécution de macro, il me sort une fenêtre de dialogue pour que je choisisse mes x et y au lieu de les fixer à 2 et 4 respectivement ou de les changer dans le code à chaque fois. genre demander à l'utilisateur des i, j et changer le code :

For x = i To UBound(tData, 1) - 2 Step 3

For y = j To UBound(tData, 2)

ou encore mieux demander à l'utilisateur la cellule de départ qui est dans mon cas D2 (x=2 et y=4), car il se peut qu'on insère du texte avant le tableau et dans ce cas les repère change et ca pourrait affecter les résultats après exécution du macro.

3-est ce possible d'avoir une deuxième version du macro où on peut changer les valeurs 0 dans les cellules à comparer par des cellules vides car j'ai l'impression que j'aurai trop de couleur avec l'année 2017 du fait que j'ai pas saisi les montants que j'ai pas encore reçu et puisque j'ai mis un format personnalisé, Excel remplace les cellules vides par des € - .

Merciiiiiiiiiiiiiiiiiiiiii à tout le monde.. ce premier post m'encouragera à poster d'autres sujets. je suis sûr et certain que je me suis entouré des personnes géniales.

Rechercher des sujets similaires à "grand defi vba comparaison formattage conditionnel assez delicat"