Indice VBA excel

oliv'' -  
 oliv'' -
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

A voir également:

5 réponses

madeliocustom Messages postés 42 Statut Membre 13
 
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
oliv''
 
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
oliv''
 
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
eriiic Messages postés 25847 Date d'inscription   Statut Contributeur Dernière intervention   7 282
 
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
oliv''
 
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
michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   3 318
 
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
eriiic Messages postés 25847 Date d'inscription   Statut Contributeur Dernière intervention   7 282
 
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
oliv''
 
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
eriiic Messages postés 25847 Date d'inscription   Statut Contributeur Dernière intervention   7 282
 
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

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
oliv''
 
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
eriiic Messages postés 25847 Date d'inscription   Statut Contributeur Dernière intervention   7 282
 
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
michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   3 318
 
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
eriiic Messages postés 25847 Date d'inscription   Statut Contributeur Dernière intervention   7 282
 
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
oliv2''
 
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
eriiic Messages postés 25847 Date d'inscription   Statut Contributeur Dernière intervention   7 282
 
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