Filtrage d'un immense fichier

siocnarf

XLDnaute Occasionnel
Bonjour,

J'ai un bon problème devant moi.

1. J'ai une liste de tous les exe d'un parc de 1400 postes ce qui donne environ 400 000 lignes. Le tableau contient le nom de l'ordinateur, l'identifiant de la personne, le système d'exploitation, le nom du fichier, son emplacement, sa version et sa description. (voir le fichier test.xlsx).
2. Je dois épurer cette liste au maximum pour ne garder que certains exe.

Ma solution:

J'ai créé un dictionnaire dans un autre classeur et je le charge comme array avec un vba. Puis pour chaque entrée dans le dictionnaire, je fais une recherche dans la colonne appropriée et supprime la ligne. Je refais la même recherche tant que le mot existe.

Une fois que le mot n'est plus là, je prend la seconde entrée dans le dictionnaire. Actuellement, le dictionnaire a environ 300 lignes mais un même mot du dictionnaire peut apparaitre 5000 fois dans le tableau.

Mon problème:
Si par exemple, je recherche le mot Prowin.exe, ce mot apparaît à différent endroits dans mon tableau mais toujours dans la même colonne. Or l'action de recherche et de suppression de la ligne unique prend du temps.

Serait-il possible de rechercher toutes les chaines contenant Prowin.exe dans une colonne et de simplement supprimer les lignes?

En pièce jointe, vous retrouverez un échantillon de mon fichier. Je n'y ai laissé que les Office.

Que devrais-je faire pour optimiser la suppression de mes lignes afin de ne conserver que les Outlook et les Wordview. Dans les faits mon dictionnaire a plus de mot. Parfois les mots à supprimer font parti de la chaine de caractère dans les descriptions.



Je remarque que suivant mon exécution, le traitement est lent et accélère puisqu'il y a de moins en moins de ligne. Mais cela demande tout de même du temps.

Voici un échantillon de mon code:

Code:
Sub Supprimevaleurs(S_StrNomduFichier, S_StrChiffrierdestination, S_tablodesretraits, S_VFeuilDataCol4, S_VFeuilDataCol6, S_VFeuilDataCol7)

Dim LDerniereLigne As Long
Dim LDerniereColonne As Long
Dim LPosition As Long
Dim Trouve As Range
Dim PlageDeRecherche As Range
Dim Valeur_Cherchee As String
Dim AdresseTrouvee As String
Dim L_ligne As Long


'http://www.commentcamarche.net/faq/36886-vba-recherche-de-donnees-la-methode-find

Workbooks(S_StrNomduFichier).Activate
Sheets(1).Select

'On détermine les dernières lignes et colonnes du tableau
LDerniereColonne = ActiveSheet.UsedRange.Columns.Count
LDerniereLigne = Sheets(1).Cells(Application.Rows.Count, 1).End(xlUp).Row
'LDerniereLigne = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row


For LPosition = LBound(S_tablodesretraits, 1) To UBound(S_tablodesretraits, 1) 'On va passer toutes les lignes du dictionnaire
    
     Select Case S_tablodesretraits(LPosition, 2) 
        Case S_VFeuilDataCol4(0) 'On fait une recherche avec le nom du fichier
        
                Valeur_Cherchee = S_tablodesretraits(LPosition, 1) 'Valeur recherchée
                Set PlageDeRecherche = ActiveSheet.Columns(4)
                
                Call Cherche(PlageDeRecherche, S_StrNomduFichier, Valeur_Cherchee)
             
        Case S_VFeuilDataCol6(0) 'On fait une recherche avec l'emplacement du fichier
        
               Valeur_Cherchee = S_tablodesretraits(LPosition, 1) 'Valeur recherchée
                Set PlageDeRecherche = ActiveSheet.Columns(6)
                
                Call Cherche(PlageDeRecherche, S_StrNomduFichier, Valeur_Cherchee)
            
        Case S_VFeuilDataCol7(0) ' On fait une recherche avec la description du fichier.
                         
                Valeur_Cherchee = S_tablodesretraits(LPosition, 1) 'Valeur recherchée
                Set PlageDeRecherche = ActiveSheet.Columns(7)
                
                Call Cherche(PlageDeRecherche, S_StrNomduFichier, Valeur_Cherchee)
            
    End Select
 
Next

End Sub
'============================================
'============================================
Sub Cherche(C_PlageDeRecherche, C_StrNomduFichier, C_Valeur_Cherchee)

Set Trouve = C_PlageDeRecherche.Cells.Find(What:=C_Valeur_Cherchee, LookAt:=xlPart)

  Do
            
     If Not Trouve Is Nothing Then
            
           Workbooks(C_StrNomduFichier).Activate
           Sheets(1).Select
                   
          'http://www.commentcamarche.net/faq/18696-vba-recherche-find-avec-retour-multiple
          'AdresseTrouvee = Trouve.Address
          'AdresseTrouvee = Trouve.Row
          L_ligne = Trouve.Row
          'Rows(L_ligne & ":" & L_ligne).Select
          'Range("A472526:H472526").Select
          'Workbooks(S_StrNomduFichier).Sheets(1).Range("A472526:H472526").Select
           Workbooks(C_StrNomduFichier).Sheets(1).Rows(L_ligne & ":" & L_ligne).Select
           'Rows("1:1").Select
          [B] Selection.Delete Shift:=xlUp[/B]
           Set Trouve = C_PlageDeRecherche.Cells.Find(What:=C_Valeur_Cherchee, LookAt:=xlPart)
                    
       End If
                
   Loop While Not Trouve Is Nothing 'Tant que l'on trouve des valeurs on fait la recherche
           

End Sub

SVP, soyez indulgent pour mon code :) Mais je suis évidemment ouvert aux propositions.
 

Pièces jointes

  • test.xlsx
    559 KB · Affichages: 60
  • Épuration des exe.xls
    103 KB · Affichages: 66
  • test.xlsx
    559 KB · Affichages: 65
  • test.xlsx
    559 KB · Affichages: 62
Dernière édition:

siocnarf

XLDnaute Occasionnel
Re : Filtrage d'un immense fichier

Bonjour,

J'ai refait mon code pour tenir compte d'une troisième colonne.

On arrive à 47s parce que j'ai ajouté la colonne des emplacements des exe.

Code:
Sub Supprimevaleurs(S_StrNomduFichier, S_SDictionnaireCol1, S_SDictionnaireCol2)

Dim s_Formulepartie1 As String
Dim s_Formulepartie2 As String
Dim s_Formulepartie3 As String
Dim f As String

t = Timer 'Moment du départ
'http://www.commentcamarche.net/faq/36886-vba-recherche-de-donnees-la-methode-find

Suppression = False

Workbooks(S_StrNomduFichier).Activate
Sheets(1).Select

s_Formulepartie1 = "ISNUMBER(SEARCH(" & S_SDictionnaireCol1 & ",RC4))*(R1C4=" & S_SDictionnaireCol2 & ")"
s_Formulepartie2 = "ISNUMBER(SEARCH(" & S_SDictionnaireCol1 & ",RC6))*(R1C6=" & S_SDictionnaireCol2 & ")"
s_Formulepartie3 = "ISNUMBER(SEARCH(" & S_SDictionnaireCol1 & ",RC7))*(R1C7=" & S_SDictionnaireCol2 & ")"

f = "=LN(SUMPRODUCT(" & s_Formulepartie1 & "+" & s_Formulepartie2 & "+" & s_Formulepartie3 & "))"

Application.ScreenUpdating = False
With Workbooks(S_StrNomduFichier).Sheets(1).UsedRange
  .Columns(8).FormulaR1C1 = f 'Insère la formule f dans chaque cellule de la colonne H
  .Columns(8) = .Columns(8).Value 'ne garde que les valeurs
  .Resize(, 8).Sort .Columns(8), xlDescending, Header:=xlYes  'le tri place les nombres en bas du tableau (pour accélérer)
  On Error Resume Next 's'il n'y a rien à supprimer
  .Columns(8).SpecialCells(xlCellTypeConstants, 1).EntireRow.Delete 'On supprime les lignes en fonction de la colonne 8 lorsque celle-ci est égale à 1
  .Columns(8).Delete xlToLeft 'On supprime la colonne 8 qui devient inutile
  Application.Goto .Cells(1), True
End With
Application.ScreenUpdating = True
MsgBox "Durée " & Format(Timer - t, "0.0 \s") 'facultatif...


End Sub
 

job75

XLDnaute Barbatruc
Re : Filtrage d'un immense fichier

Re,

Erreur 1004 sur "For Each c In Feuil2.Range("A2", Range("A" & Rows.Count).End(xlUp))"

En effet, si l'on exécute la macro quand le dictionnaire n'est pas la feuille active.

Donc préciser la feuille devant tous les "Range" :

Code:
For Each c In Feuil2.Range("A2", Feuil2.Range("A" & Feuil2.Rows.Count).End(xlUp))
Edit : j'ai modifié les macros des fichiers (4) et (4 bis) des posts précédents.

A+
 
Dernière édition:

siocnarf

XLDnaute Occasionnel
Re : Filtrage d'un immense fichier

Bonjour,

Je viens de tester votre solution 3 sur mon fichier de 470 000 lignes. Beaucoup trop de lignes sont supprimés.
" .Columns(8).SpecialCells(xlCellTypeConstants, 1).EntireRow.Delete"

Je viens de réaliser que les résultat seront des #nombre ou des décimales allant à jusqu'à 1 et que donc la ligne ne conserve que les #nombre.

Il va falloir que je fouille pourquoi certaines lignes sont supprimés alors qu'elles devraient demeurer.

Je me demandais s'il était possible aisément d'isoler quelle condition retournait une constante. Le fichier ayant 472 000 lignes et le véritable dictionnaire plus de 200 lignes, ce serait bien de pouvoir isoler ce qui retourne la constante par rapport au dictionnaire.

Mon code est maintenant:
Code:
Sub Supprimevaleurs(S_StrNomduFichier, S_SDictionnaireCol1, S_SDictionnaireCol2)

Dim s_Formulepartie1 As String
Dim s_Formulepartie2 As String
Dim s_Formulepartie3 As String
Dim f As String

t = Timer 'Moment du départ
'http://www.commentcamarche.net/faq/36886-vba-recherche-de-donnees-la-methode-find

Suppression = False

Workbooks(S_StrNomduFichier).Activate
Sheets(1).Select

s_Formulepartie1 = "ISNUMBER(SEARCH(" & S_SDictionnaireCol1 & ",RC4))"
s_Formulepartie2 = "ISNUMBER(SEARCH(" & S_SDictionnaireCol1 & ",RC6))"
s_Formulepartie3 = "ISNUMBER(SEARCH(" & S_SDictionnaireCol1 & ",RC7))"

f = "=LN(SUMPRODUCT(" & s_Formulepartie1 & "+" & s_Formulepartie2 & "+" & s_Formulepartie3 & "))"

'Application.ScreenUpdating = False
With Workbooks(S_StrNomduFichier).Sheets(1).UsedRange
  .Columns(8).FormulaR1C1 = f 'Insère la formule f dans chaque cellule de la colonne H
  .Columns(8) = .Columns(8).Value 'ne garde que les valeurs
  .Resize(, 8).Sort .Columns(8), xlDescending, Header:=xlYes  'le tri place les nombres en bas du tableau (pour accélérer)
  On Error Resume Next 's'il n'y a rien à supprimer
  .Columns(8).SpecialCells(xlCellTypeConstants, 1).EntireRow.Delete 'On supprime les lignes en fonction de la colonne 8 lorsque celle-ci est égale à 1
  .Columns(8).Delete xlToLeft 'On supprime la colonne 8 qui devient inutile
  Application.Goto .Cells(1), True
End With
Application.ScreenUpdating = True
MsgBox "Durée " & Format(Timer - t, "0.0 \s") 'facultatif...


End Sub
Merci,

François
 
Dernière édition:

job75

XLDnaute Barbatruc
Re : Filtrage d'un immense fichier

Re,

Ne vous polarisez pas sur la solution (3), qu'en plus vous avez modifiée.

Les solutions (4) et (4 bis) sont nettement plus efficaces et plus rapides.

Mais toutes les solutions suppriment ce que vous demandez de supprimer, rien de plus.

A+
 

siocnarf

XLDnaute Occasionnel
Re : Filtrage d'un immense fichier

Bonjour,

Je vais tester les 4 et 4 bis. Pour la solution 3, j'obtiens 479,4 seconde soit 7,98 minutes. C'est un bond magistral comparativement à la solution de départ.

Merci,

François
 
Dernière édition:

Discussions similaires

Réponses
2
Affichages
320
  • Question
Microsoft 365 Code VBA
Réponses
10
Affichages
744

Statistiques des forums

Discussions
315 080
Messages
2 116 020
Membres
112 637
dernier inscrit
pseudoinconnu