Indice VBA excel

Bonjour,

Je travaille actuellement sur Excel et je souhaiterais développer un code VBA me permettant de comparer deux colonnes A situées sur des onglets différents (N et N-1) dans un même classeur afin de déterminer ce qui à été ajouté ou supprimer.

Les entêtes de colonnes A sont identiques ainsi que les chaînes de caractères à comparer.

l'idée serait de créer une nouvelle colonne en y incluant "1" si la cellule existe dans les deux onglets, "2" si la cellule existe uniquement pour N-1 et "3" si la cellule existe uniquement dans N.

Je sais que le topic à été beaucoup traité, cependant, je n'arrive pas à trouver des ressources suffisantes.

l'Objectif pour moi ensuite étant de pouvoir faire le tri avec cette macro :

Sub tri_doublon()

Dim Rw As Range
Dim Ligne As Long
Dim derli As Variant
Dim r As Variant

' Sélection des données
Sheets("N").Select
ActiveCell.SpecialCells(xlLastCell).Select
Range(Selection, Cells(1)).Select

' Boucle qui copie dans une deuxième feuille de calcul

For Each Rw In Selection.Rows

Ligne = Rw.Row

If Rw.Cells(1, 1).Value = "1" Then
Rw.Copy Destination:=Worksheets("Feuil1").Cells(Ligne, 1)
End If

Next Rw

For Each Rw In Selection.Rows

Ligne = Rw.Row

If Rw.Cells(1, 1).Value = "2" Then
Rw.Copy Destination:=Worksheets("Feuil2").Cells(Ligne, 1)
End If

Next Rw


Serait-il possible d'obtenir un soutien technique de votre part ?

Très cordialement

5 réponses

  1. euh désolé d'avoir valider le topic! En fait je me suis aperçu d'un petite modif qui serait utile dans ta macro éric!
    en fait quand je selectionne les données de mes colonnes, il ne va pas m'implémenter la valeur qui est écrite dans la cellule mais la formule!
    mes données du champs A sont enn fait une concaténation de plusieurs autres colonnes!

    Alors oui ta macro marche parfaitement, je l'ai utilisée au préalable sur la liste qu'avait envoyé michel mais je ne m'attendais pas à cela sur mon fichier!

    je vais tenter de rectifier cela et si jamais tu as une idée je suis toujours preenur!

    merci.
    0
    1. Contributeur
      Rapidement car je pars...
      Essaie en ajoutant ces 2 lignes devant 'calcul présence :

      sh3.Columns("A:A").Copy
      sh3.[A1].PasteSpecial Paste:=xlPasteValues
      ' calcul présence
      0
    2. Contributeur
      Hé oui, Eric, pendant que tu restaurais grassement, j'en ai profité sournoisement pour bosser !
      quant à la ballade c'était des courses à l'hyper du coin car vu le temps ici (orages, pluies, froid) pas question d'aller se ballader, pardon se tremper... merci quand m^me
      le temps sur 5000 lignes version Eric :15 secondes... et toc! :-D

      petit truc curieux: je n'ai pas vu d'index 2 en testant ta procédure, regarde (mais j'ai testé en vitesse)

      mais je n'ai pas utilisé l'idée 1,2,3 : je renvoie directement les valeurs dans 3 colonnes, donc...

      quant à oliv, ma proposition ne semble pas l'inspirer ('a t il essayé?), pourtant il voulait aller + rapidement... je" n'insiste donc pas sur ma recherche d'une solution encore + rapide (mise des valeurs sheets1 et sheets2 dans variables tableaux (élimination des test sur cellules)

      amicalement
      michel

      ps: si ca t'intéresse dans mon fichier module 2 tu as les procédures de chronometrage récupérées sur le site de Frédéric Sigonneau
      0
    3. Contributeur
      le temps sur 5000 lignes version Eric :15 secondes... et toc! :-D
      50% en plus ça commence à faire mais je m'attendais à pire... :-)
      dans mon fichier module 2 tu as les procédures de chronometrage
      Tu as bien fait de le dire car j'avais juste lu ton code.
      Hummm, je préfère encore mon t=timer et msgbox(timer-t) plus facilement mis en place ;-)

      @+
      eric
      0
    4. J'ai bien regardé ton script michel et tu m'as convaincu de son efficacité! C'est vrai que de passer d'un traitement de 3 heures à un autre de 11 secondes eh bien ca fais plaisir. Je revois ca des vendredi pour recomparer ces macros!
      Car, j'ai tenté les deux lignes que tu m'as envoyé eric sans succès. J'ai refait un test sur un autre fichier et j'ai obtenu :
      "Nom" en A1 ," Feuille" en B1 et "3" en B2.
      Même enenregistrant une macro le resultat est le même!
      0
    5. Contributeur
      Effectivement il faut copier les valeurs dès le début.
      La modif pour copier les valeurs :
      Sub controle()   
          t = Timer   
          Dim sh1 As Worksheet, sh2 As Worksheet, sh3 As Worksheet   
          Dim derlig1 As Long, derlig2 As Long, derlig3 As Long   
          Dim c As Range, r1, r2   
          Set sh1 = Worksheets("Feuil1")   
          Set sh2 = Worksheets("Feuil2")   
          Set sh3 = Worksheets("Feuil3")   
          derlig1 = sh1.[A65536].End(xlUp).Row   
          derlig2 = sh2.[A65536].End(xlUp).Row   
          Application.ScreenUpdating = False   
          ' vider sh3   
          sh3.Range("A:B").Delete   
          sh3.[A1] = "Nom"   
          ' copier datas feuil1   
          sh1.Range("A2:A" & sh1.[A65536].End(xlUp).Row).Copy   
          sh3.[A2].PasteSpecial Paste:=xlPasteValues   
          ' copier datas feuil2   
          sh2.Range("A2:A" & sh2.[A65536].End(xlUp).Row).Copy '   
          sh3.[A65536].End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValues   
          ' éliminer doublons   
          sh3.Range("A1:A" & sh3.[A65536].End(xlUp).Row).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=sh3.Range("B1"), Unique:=True   
          sh3.Range("A:A").Delete   
          sh3.[B1] = "Feuille"   
          derlig3 = sh3.[A65536].End(xlUp).Row   
          ' calcul présence   
          For Each c In sh3.Range("A2:A" & derlig3)   
              c.Offset(0, 1) = IIf(Application.WorksheetFunction.CountIf(sh1.Range("A2:A" & derlig1), c.Value) > 0, 1, 0) + IIf(Application.WorksheetFunction.CountIf(sh2.Range("A2:A" & derlig2), c.Value) > 0, 2, 0)   
          Next c   
          Application.ScreenUpdating = True   
          MsgBox (Timer - t)   
      End Sub


      Et pour répondre à michel sur une question zappée :
      <ital>petit truc curieux: je n'ai pas vu d'index 2 en testant ta procédure

      Normal, y'en n'a pas ;-)
      Je compile les 2 listes dont j'élimine les doublons, et je recherche les éléments dans les 2 feuilles.

      eric
      0
  2. Contributeur
    Si tu dois l'utiliser souvent ça vaut peut-être le coup d'adapter celle de michel, il travaille en mémoire et il doit y avoir un gain significatif.
    A voir...

    Edit: et si tu travailles sur 2007 il y aura des petites modif à faire pour augmenter le nombre de lignes utilisables
    0
    1. Je viens de tester vos deux macros et les deux me conviennent parfaitement , même si j'ai une petite préférence pour celle d'eric qui donne les numéros! Enfin bon Michel à été plus rapide! ;)

      En tout cas je tiens vraiment à vous remercier pour le temps que vous aurez pris pour m'aider (le duel en face du PC à été tres long ce matin!)

      Bonne continuation à vous et peut être à bientôt!

      olivier
      0
      1. Contributeur
        Rhooo, on ne peut même plus s'absenter un peu... ;-)
        Voici quand même ma version :
        Je préfère utiliser une 3ème feuille, et mettre 1 pour feuil1, 2 pour feuil2 et 3 pour feuil1+feuil2, ça heurte moins ma logique ;-)

        Sub controle()  
            Dim sh1 As Worksheet, sh2 As Worksheet, sh3 As Worksheet  
            Dim derlig1 As Long, derlig2 As Long, derlig3 As Long  
            Dim c As Range, r1, r2  
            Set sh1 = Worksheets("Feuil1")  
            Set sh2 = Worksheets("Feuil2")  
            Set sh3 = Worksheets("Feuil3")  
            derlig1 = sh1.[A65536].End(xlUp).Row  
            derlig2 = sh2.[A65536].End(xlUp).Row  
            Application.ScreenUpdating = False  
            ' vider sh3  
            sh3.Range("A:B").Delete  
            sh3.[A1] = "Nom"  
            ' copier datas feuil1  
            sh1.Range("A2:A" & sh1.[A65536].End(xlUp).Row).Copy Destination:=sh3.[A2]  
            ' copier datas feuil2  
            sh2.Range("A2:A" & sh2.[A65536].End(xlUp).Row).Copy sh3.[A65536].End(xlUp).Offset(1, 0)  
            ' éliminer doublons  
            sh3.Range("A1:A" & sh3.[A65536].End(xlUp).Row).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=sh3.Range("B1"), Unique:=True  
            sh3.Range("A:A").Delete  
            sh3.[B1] = "Feuille"  
            derlig3 = sh3.[A65536].End(xlUp).Row  
            ' calcul présence  
            For Each c In sh3.Range("A2:A" & derlig3)  
                c.Offset(0, 1) = IIf(Application.WorksheetFunction.CountIf(sh1.Range("A2:A" & derlig1), c.Value) > 0, 1, 0) + IIf(Application.WorksheetFunction.CountIf(sh2.Range("A2:A" & derlig2), c.Value) > 0, 2, 0)  
            Next c  
            Application.ScreenUpdating = True  
        End Sub  
        

        Michel si tu pouvais comparer, je n'ai pas de grande liste...
        Je pense mettre moins de 3h aussi ;-)
        Bonne balade :-)

        Oliv, regarde aussi la proposition de michel à 13h27

        eric
        0
        1. Bonjour,

          voici du code qui fait ce que tu veux a adapter tout de meme en fonction de la repartition de tes listes de données dans tes feuilles excel, et en fonction des codes "1", "2" et "3" que tu souhaites en sortie, car le code ci-dessous construit une nouvelle liste avec les données qui sont dans la deuxieme liste mais pas dans la premiere.

          ----------------------------------------

          Dim ligneparcourslisteexistante As Integer
          Dim ligneparcourslistenouvelle As Integer
          Dim lignedebut As Integer
          Dim lignefinlisteexistante As Integer
          Dim lignefinlistenouvelle As Integer
          Dim lignefinlisteaajouter As Integer
          Dim ligneajout As Integer
          Dim existedeja As Integer

          Dim colonnelisteexistante As Integer
          Dim colonnelistenouvelle As Integer
          Dim colonnelisteaajouter As Integer

          MsgBox "Demarrage du comparateur de liste"

          'debut init
          lignedebut = 4
          ligneajout = 4
          existedeja = 0

          colonnelisteexistante = 2
          colonnelistenouvelle = 3
          colonnelisteaajouter = 4

          lignefinlistenouvelle = lignedebut
          Do While ActiveWorkbook.Worksheets("listes").Cells(lignefinlistenouvelle, colonnelistenouvelle).Value <> ""
          lignefinlistenouvelle = lignefinlistenouvelle + 1
          Loop
          ligneparcourslistenouvelle = lignefinlistenouvelle

          lignefinlisteexistante = lignedebut
          Do While ActiveWorkbook.Worksheets("listes").Cells(lignefinlisteexistante, colonnelisteexistante).Value <> ""
          lignefinlisteexistante = lignefinlisteexistante + 1
          Loop
          ligneparcourslisteexistante = lignefinlisteexistante

          lignefinlisteajouter = lignedebut
          Do While ActiveWorkbook.Worksheets("listes").Cells(lignefinlisteajouter, colonnelisteaajouter).Value <> ""
          ActiveWorkbook.Worksheets("listes").Cells(lignefinlisteajouter, colonnelisteaajouter).Value = ""
          lignefinlisteajouter = lignefinlisteajouter + 1
          Loop

          'fin init

          'debut parcours
          Do While ligneparcourslistenouvelle >= lignedebut

          lignefinlisteexistante = lignedebut
          Do While ActiveWorkbook.Worksheets("listes").Cells(lignefinlisteexistante, colonnelisteexistante).Value <> ""
          lignefinlisteexistante = lignefinlisteexistante + 1
          Loop
          ligneparcourslisteexistante = lignefinlisteexistante

          existedeja = 0
          Do While ligneparcourslisteexistante >= lignedebut
          If _
          ActiveWorkbook.Worksheets("listes").Cells(ligneparcourslistenouvelle, colonnelistenouvelle).Value _
          = ActiveWorkbook.Worksheets("listes").Cells(ligneparcourslisteexistante, colonnelisteexistante).Value _
          Then
          existedeja = 1
          Exit Do
          End If
          ligneparcourslisteexistante = ligneparcourslisteexistante - 1
          Loop

          If existedeja = 0 Then

          ActiveWorkbook.Worksheets("listes").Cells(ligneajout, colonnelisteaajouter).Value = _
          ActiveWorkbook.Worksheets("listes").Cells(ligneparcourslistenouvelle, colonnelistenouvelle).Value
          ligneajout = ligneajout + 1

          End If

          ligneparcourslistenouvelle = ligneparcourslistenouvelle - 1
          Loop
          'fin parcours

          MsgBox "Liste des entrées à ajouter crée"

          ----------------------------------------

          A+
          Madelio
          0
          1. Merci beaucoup pour la réponse Madelio!
            Je regarde ça aujourd'hui ou demain et je te dit si ca a marché!
            bonne aprem'
            0
          2. rebonjour,

            j'ai regardé ton script hier soir et je m'en suis servi pour ecrire le code suivant. Le problème c'est que mes deux onglets font chacun plus de 30000 lignes. J'ai déclaré toutes mes variables en types string.

            Sub INDICES()

            Sheets("Feuille cont2").Select

            Columns("A:A").Select
            Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
            Range("A1").Select
            ActiveCell.FormulaR1C1 = "Résultat du test"
            Range("A2").Select
            Columns("A:A").EntireColumn.AutoFit
            Range("B2").Select

            compteurf2 = 0
            l1 = 2
            l2 = 2
            Dim nomtest As String
            num = 0

            Cells(l2, 2).Select
            Do
            nomtest = Cells(l2, 2).Value
            num = 0
            l1 = 2

            Sheets("Feuille1").Select
            Cells(l1, 1).Select

            Do

            If Cells(l1, 1) = nomtest Then
            num = 1
            compteurf1 = l1
            End If

            l1 = l1 + 1
            Cells(l1, 1).Select
            Loop Until ActiveCell = ""

            If num = 1 Then
            Sheets("Feuille2").Select
            Cells(l2, 1).FormulaR1C1 = "1"
            Sheets("Feuille1").Select
            Cells(compteurf1, 2).FormulaR1C1 = "1"
            Else
            Sheets("Feuille2").Select
            Cells(l2, 1).FormulaR1C1 = "0"
            End If

            Sheets("Feuille2").Select
            l2 = l2 + 1
            Cells(l2, 2).Select

            Loop Until ActiveCell = ""

            compteurf2 = l2

            l1 = 2

            Sheets("Feuille1").Select

            Cells(l1, 1).Select

            Do

            If Cells(l1, 2) = "" Then
            ActiveCell.Select
            Selection.Copy
            Sheets("Feuille2").Select
            Cells(compteurf2, 2).Select
            ActiveSheet.Paste
            Cells(compteurf2, 1).FormulaR1C1 = "3"
            compteurf2 = compteurf2 + 1
            Sheets("Feuille1").Select
            End If

            l1 = l1 + 1
            Cells(l1, 1).Select
            Loop Until ActiveCell = ""

            Sheets("Feuille1").Select
            Columns("B:B").Select
            Selection.ClearContents

            Sheets("Feuille2").Select

            MsgBox ("macro executée")

            End Sub

            La taille des fichiers ralentit vraiment le traitement et je souhaiterais l'accélerer! si jamais quelqu'un a une supposition je suis preneur!
            merci
            0
          3. Contributeur
            Bonjour,

            Le mieux est de tout reprendre à zéro...
            Tu veux recenser tout dans une 3ème feuille ?
            Parce qu'avec 'l'idée serait de créer une nouvelle colonne' on a l'impression que tu veux enrichir les 2 feuilles...
            0
          4. oui en effet le dernier exemple que j'ai envoyé "enrichi" le deuxième onglet.
            Hier je l'ai faite fonctionner ainsi :

            Sur la feuille 1 :

            Nom 1
            Olivier
            Amélie
            Richard

            Sur la feuille 2 :

            Nom 2
            Olivier
            Sébastien
            Amélie

            Une fois la macro lancée, la mise à jour se fait sur la feuille deux et me donne le résultat :

            Résultat du test Nom 2
            1 Olivier 'sur les deux feuillet
            0 Sébastien ' sur le deuxième feuillet
            1 Amélie ' sur les deux feuillets
            3 Richard 'sur le premier feuillet

            De cette façon je n'ai plus qu'a appliquer un filtre sur la colonne "résultat du test" pour savoir à quels onglets correspond la cellule.
            Cependant avec un volume de donnée important, le traitement est vraiment trop long (pour l'instant j'en suis à trois heures d'attentes!!) j'ai utilisé un application.screenupdating et j'ai aussi modifié une partie de la première boucle <i>Loop Until ActiveCell = "" </i> en
            <b>loop until activecell = "" or num = 1</b>
            sans trop d'amélioration performante.
            0
          5. Contributeur
            Bonjour à tous
            Sur la proposition d'Eric (bonjour, ca va ?):restitution page 3

            Sub comparer()
            
            Dim derlig1 As Long, derlig2 As Long
            Dim tablo1, tablo2, tablo3
            Dim zone1 As Range, zone2 As Range
            
            With Sheets(1)
                derlig1 = .Range("A65536").End(xlUp).Row
                Set zone1 = .Range(.Cells(1, 1), .Cells(derlig1, 1))
                ReDim tablo1(0)
            End With
            
            With Sheets(2)
                derlig2 = .Range("A65536").End(xlUp).Row
                 Set zone2 = .Range(.Cells(1, 1), .Cells(derlig2, 1))
                ReDim tablo2(0)
            End With
            
            
            With Sheets(1)
            For cptr = 1 To derlig1
                If Application.CountIf(zone2, .Cells(cptr, 1)) > 0 Then
                    tablo1(cptr1) = .Cells(cptr, 1)
                    cptr1 = cptr1 + 1
                    ReDim Preserve tablo1(cptr1)
                Else
                    tablo2(cptr2) = .Cells(cptr, 1)
                    cptr2 = cptr2 + 1
                    ReDim Preserve tablo2(cptr2)
                End If
            Next
            End With
            
            With Sheets(2)
            ReDim tablo3(0)
            For cptr = 1 To derlig2
                If Application.CountIf(zone1, .Cells(cptr, 1)) = 0 Then
                    tablo3(cptr3) = .Cells(cptr, 1)
                    cptr3 = cptr3 + 1
                    ReDim Preserve tablo3(cptr3)
                End If
            Next
            End With
            
            Application.ScreenUpdating = False
            With Sheets(3)
                .Range("A2:C65536").Clear
                .Range("A2").Resize(UBound(tablo1) + 1, 1) = Application.Transpose(tablo1)
                .Range("B2").Resize(UBound(tablo2) + 1, 1) = Application.Transpose(tablo2)
                .Range("C2").Resize(UBound(tablo3) + 1, 1) = Application.Transpose(tablo3)
                .Activate
            End With
            End Sub
            


            je regarde pour le temps et t'envoie une demo sur 5000 lignes chaque feuille (j'vas manger)
            0