Se connecter avec
S'enregistrer | Connectez-vous

suppression de plusieurs lignes d'un fichier lourd

Dernière réponse : dans Programmation

Bonjour tout le monde,
J'ai un petit code qui me permet de faire une comparaison entre 2 fichiers. S'il y a une concordance entre ces 2 fichiers, alors garder ces lignes et supprimer les autres.
Mon fichier 1 contient 32 000 lignes et mon fichier 2 en contient 190.
Si la cellule D1 du fichier 2 correspond pas à la cellule D1 du fichier 1, alors supprimer la ligne du fichier 1
etc...
Mon code a l'air de bien marcher, le problème c'est qu'il prend beaucoup beaucoup de temps.
Quelqu'un aurait il une astuce pour réduire le temps que cela prend?
voici mon code

  1. Option Explicit
  2. Sub CmistesDMO()
  3. Dim Class1 As Workbook
  4. Dim Class2 As Workbook
  5. Dim PlageClass2 As Range
  6. Dim CellClass2 As Range
  7. Dim PlageClass1 As Range
  8. Dim CellClass1 As Range
  9.  
  10. Set Class2 = Workbooks.Open("C:\Documents\Fichier2.xls", ReadOnly:=False)
  11. Set Class1 = Workbooks.Open("C:\Documents\Fichier1.xls", ReadOnly:=False) ' ReadOnly:=False -> lire et écrire
  12.  
  13. 'Supprimer les colonnes inutiles
  14. With Class1.Worksheets(1)
  15. Range("W:W").Delete
  16. Range("U:U").Delete
  17. Range("L:L").Delete
  18. Range("G:G").Delete
  19. Range("E:B").Delete
  20. End With
  21. ' Identifier la plage de données
  22. Set PlageClass1 = Class1.Worksheets(1).Range("A1").CurrentRegion.Offset(1, 0)
  23. Set PlageClass2 = Class2.Worksheets(1).Range("A1").CurrentRegion.Offset(1, 0)
  24. 'Comparaison
  25. For Each CellClass2 In PlageClass2
  26. For Each CellClass1 In PlageClass1
  27. If CellClass2.Offset(, 1).Text <> CellClass1.Offset(, 1).Text Then
  28. CellClass1.EntireRow.Delete
  29. End If
  30. Next
  31. Next
  32. End Sub
fopy12 a édité ce message
Lassé par la pub ? Créez un compte
Expert Programmation

Salut fopy,

Eh, ce code n'est pas correctement indenté. C'est mal :fou: 

Ce n'est pas la peine de mettre le ReadOnly à faux. C'est sa valeur par défaut.
Sauf que justement, ton classeur 2 peut être ouvert en lecture seule, lui ;) 


Le With de la ligne 14 ne sert à rien : il n'y a pas de point devant tes Range aux lignes 15 à 19.
Range("W:W") ça passe très bien. Mais Columns("W") ou Columns(23) sont plus jolis.

Si tu dois supprimer des lignes, il faut partir du bas et remonter. Tu le fais très bien pour les colonnes que tu supprimes de droite à gauche.
J'explique ça ici : http://www.presence-pc.com/forum/ppc/Programmation/tuto...

Voici de quoi bien le comprendre :
  1. Range("A1").Value = "A"
  2. Range("A2").Value = "Z"
  3. Range("A3").Value = "E"
  4. Range("A4").Value = "R"
  5. Range("A5").Value = "T"
  6. Range("A6").Value = "Y"
  7.  
  8. For Each cell In Range("A1:A6")
  9. If cell.Value <> "" Then cell.EntireRow.Delete
  10. Next


Je ne comprends pas pourquoi tu utilises des offset() à la ligne 27. :heink: 

Et on n'a pas encore parlé de performance ! :/ 
zeb a édité ce message

Sault Zeb,
Voici mon nouveau code modifié suivant tes indications
  1. Option Explicit
  2. Sub CmistesDMO()
  3. Dim Class1 As Workbook
  4. Dim Class2 As Workbook
  5. Dim PlageClass2 As Range
  6. Dim CellClass2 As Range
  7. Dim PlageClass1 As Range
  8. Dim CellClass1 As Range
  9. Dim LastLineC1 As Long
  10. Dim LastLineC2 As Long
  11. '
  12. Set Class2 = Workbooks.Open("C:\Documents\Fichier2.xls", ReadOnly:=True)
  13. Set Class1 = Workbooks.Open("C:\Documents\Fichier1.xls")
  14. 'Supprimer les colonnes inutiles
  15. Columns("W").Delete
  16. Columns("U").Delete
  17. Columns("L").Delete
  18. Columns("G").Delete
  19. Columns("E:B").Delete
  20. '
  21. Set PlageClass1 = Class1.Worksheets(1).Range("A1").CurrentRegion.Offset(1, 0)
  22. LastLineC1 = PlageClass1.Rows(PlageClass1.Rows.Count).Row
  23. Set PlageClass2 = Class2.Worksheets(1).Range("A1").CurrentRegion.Offset(1, 0)
  24. LastLineC2 = PlageClass2.Rows(PlageClass2.Rows.Count).Row
  25. 'Comparaison
  26. Dim i ' fichier 1
  27. Dim j ' fichier 2
  28. '
  29. For j = LastLineC2 To 1 Step -1
  30. For i = LastLineC1 To 1 Step -1
  31. If Cells(i, 4).Text <> Cells(j, 3).Text Then Rows(i).Delete
  32. End If
  33. Next
  34. Next
  35. End Sub
Expert Programmation

Ah, c'est mieux.

Manque toujours l'indentation qui m'est si chère (jamais content le vieux.)
Et ce qui est bien plus grave, ni tes colonnes (lignes 15 à 19), ni tes cellules et ta ligne (ligne 31) ne sont préfixées par la feuille concernée. Dans le cas de la ligne 31, c'est même un gros bug !

C'est pourquoi je préfère faire des For Each comme dans ton premier exemple.

Autre chose, supprimer au fur et à mesure tes lignes est très consommateur de ressource.
On peut le faire en une seule fois.

Dans ton dernier code, on ne compare que les valeurs de la colonne 4 à celles de la colonne 3. Est-ce fait exprès ?

  1. ' // J'aime !
  2. Option Explicit
  3.  
  4. Sub CmistesDMO()
  5.  
  6. Dim Class1 As Workbook
  7. Dim Class2 As Workbook
  8.  
  9. Dim FeuilleClass1 As Worksheet
  10. Dim FeuilleClass2 As Worksheet
  11.  
  12. Dim PlageClass2 As Range
  13. Dim PlageClass1 As Range
  14.  
  15. Dim CellClass1 As Range
  16. Dim CellClass2 As Range
  17.  
  18. Dim a_supprimer As Range
  19.  
  20. Set Class1 = Workbooks.Open("C:\Documents\Fichier1.xls")
  21. Set Class2 = Workbooks.Open("C:\Documents\Fichier2.xls", ReadOnly:=True)
  22.  
  23. Set FeuilleClass1 = Class1.Worksheets(1)
  24. Set FeuilleClass2 = Class2.Worksheets(1)
  25.  
  26. ' // Supprimer l'ensemble des colonnes inutiles
  27. ' // C'est juste pour te montrer ;-)
  28. ' // Regarde quand-même comment ça marche !
  29. Union( _
  30. FeuilleClass1.Columns("W"), _
  31. FeuilleClass1.Columns("U"), _
  32. FeuilleClass1.Columns("L"), _
  33. FeuilleClass1.Columns("G"), _
  34. FeuilleClass1.Columns("E:B")).Delete
  35.  
  36. Set PlageClass1 = FeuilleClass1.Range("A1").CurrentRegion.Offset(1, 0).Columns(4)
  37. Set PlageClass2 = FeuilleClass2.Range("A1").CurrentRegion.Offset(1, 0).Columns(3)
  38.  
  39. 'Comparaison
  40. For Each CellClass1 In PlageClass1
  41. For Each CellClass2 In PlageClass2
  42. If CellClass2.Cells(i, 4).Value <> CellClass2.Value Then
  43. ' // On accumule les lignes à supprimer
  44. Set a_supprimer = Union(a_supprimer, CellClass1.EntireRow)
  45. End If
  46. Next
  47. ' // Pour savoir où on en est
  48. Application.StatusBar = "Progression : " & (CellClass1.Row * 100 / PlageClass1.Count) & "%"
  49. Next
  50.  
  51. Application.StatusBar = False
  52. ' / Et on supprime pour de bon
  53. a_supprimer.Delete
  54.  
  55. Class2.Close
  56. End Sub


Bon, à la ligne 44, il y a un problème, VBA ne sait pas faire l'union avec un truc vide.
Il faut donc distinguer ce cas.
  1. ' // On accumule les lignes à supprimer
  2. If a_supprimer Is Nothing Then
  3. Set a_supprimer = CellClass1.EntireRow
  4. Else
  5. Set a_supprimer = Union(a_supprimer, CellClass1.EntireRow)
  6. End If


Le gain ne sera pas forcément énorme, mais c'est déjà ça.
zeb a édité ce message
Lassé par la pub ? Créez un compte