recherche de fichiers contenant macro

wwwhttp

XLDnaute Nouveau
Bonjour,
je suis à la recherche d'une bonne âme afin de m'aider à trouver les fichiers contenant des macros.
le but est d'identifier dans un répertoire et ses sous-répertoires tous les fichiers xls qui contiennent du vba et de les restituer sous une forme de liste quelconque (xls, txt, html, ...).
les fichiers à analyser sont tous sous Excel 2003 et sous environnement windows xp
merci d'avance pour votre aide
 

job75

XLDnaute Barbatruc
Re : recherche de fichiers contenant macro

Bonjour wwwhttp,

Créez un fichier pilote et enregistrez-le en .xls ou .xlsm.

Sur Excel 2003 cochez l'option Faire confiance au projet Visual Basic (menu Outils-Macro-Sécurité-Editeurs approuvés).

Sur les versions ultérieures cochez l'option Accès approuvé au modèle d'objet du projet VBA (onglet Fichier-Options-Centre de gestion de la confidentialité-Paramètres...-Paramètres des macros)

Placez ce code dans un module standard et exécutez la procédure Sub :

Code:
Function ContientMacros(Wb As Workbook) As Boolean
Dim o As Object
For Each o In Wb.VBProject.VBComponents
  With o.CodeModule
    ContientMacros = .CountOfDeclarationLines + 1 < .CountOfLines
  End With
  If ContientMacros Then Exit For
Next
End Function

Sub FichiersAvecMacros()
Dim chemin$, lig&, dossier, liste$, fichier$, test As Boolean
chemin = ThisWorkbook.Path
lig = 2
Application.ScreenUpdating = False
Application.DisplayAlerts = False 'si un fichier est ouvert
[A:C].ClearContents 'RAZ
[A1] = "MACRO": [B1] = "DOSSIER": [C1] = "FICHIER"
'---liste des sous-dossiers---
dossier = Dir(chemin & "\*", vbDirectory)
While dossier <> ""
  If GetAttr(chemin & "\" & dossier) = vbDirectory _
    Then liste = liste & Chr(1) & dossier
  dossier = Dir
Wend
liste = Mid(liste, 2)
'---fichiers du dossier et des sous-dossiers---
For Each dossier In Split(liste, Chr(1))
  fichier = Dir(chemin & "\" & dossier & "\*xls")
  While fichier <> ""
    If fichier <> ThisWorkbook.Name Then
      Workbooks.Open chemin & "\" & dossier & "\" & fichier
      test = ContientMacros(Workbooks(fichier))
      Workbooks(fichier).Close False
      If test Then Cells(lig, 1) = "OUI"
      Cells(lig, 2) = dossier
      Cells(lig, 3) = fichier
      lig = lig + 1
    End If
    fichier = Dir
  Wend
Next
Columns.AutoFit
End Sub
A+
 

Staple1600

XLDnaute Barbatruc
Re : recherche de fichiers contenant macro

Bonsoir à tous, _____________________(salut job75, 00 ;))


Une autre façon de faire en utilisant la propriété idoine : Ce lien n'existe plus
(disponible à partir d'Excel 2007)

Code:
Sub FindMacros()
'code d'Allen Wyatt
'francisé par votre serviteur
    Dim sPath As String
    Dim sFile As String
    Dim sFoundFiles As String

    'specify directory to use - must end in "\"
    sPath = "C:\Temp\" 'adapter le chemin

    sFile = Dir(sPath)
    Do While sFile <> ""
        If InStr(sFile, ".xls") > 0 Then
            Workbooks.Open (sPath & sFile)
            If Workbooks(sFile).HasVBProject Then
                sFoundFiles = sFoundFiles & sFile & vbCrLf
            End If
            Workbooks(sFile).Close (False)
        End If
        sFile = Dir     ' Get next filename
    Loop
    If Len(sFoundFiles) = 0 Then
        MsgBox "Aucun classeur contenant du code VBA trouvé"
    Else
        sFoundFiles = "Le classeur suivant contient du code VBA:" & _
          vbCrLf & vbCrLf & sFoundFiles
        MsgBox sFoundFiles
    End If
End Sub
 
Dernière édition:

wwwhttp

XLDnaute Nouveau
Re : recherche de fichiers contenant macro

Bonjour wwwhttp,

Placez ce code dans un module standard et exécutez la procédure Sub :

Code:
Function ContientMacros(Wb As Workbook) As Boolean
Dim o As Object
For Each o In Wb.VBProject.VBComponents
  With o.CodeModule
    ContientMacros = .CountOfDeclarationLines + 1 < .CountOfLines
  End With
  If ContientMacros Then Exit For
Next
End Function

Sub FichiersAvecMacros()
Dim chemin$, lig&, dossier, liste$, fichier$, test As Boolean
chemin = ThisWorkbook.Path
lig = 2
Application.ScreenUpdating = False
Application.DisplayAlerts = False 'si un fichier est ouvert
[A:C].ClearContents 'RAZ
[A1] = "MACRO": [B1] = "DOSSIER": [C1] = "FICHIER"
'---liste des sous-dossiers---
dossier = Dir(chemin & "\*", vbDirectory)
While dossier <> ""
  If GetAttr(chemin & "\" & dossier) = vbDirectory _
    Then liste = liste & Chr(1) & dossier
  dossier = Dir
Wend
liste = Mid(liste, 2)
'---fichiers du dossier et des sous-dossiers---
For Each dossier In Split(liste, Chr(1))
  fichier = Dir(chemin & "\" & dossier & "\*xls")
  While fichier <> ""
    If fichier <> ThisWorkbook.Name Then
      Workbooks.Open chemin & "\" & dossier & "\" & fichier
      test = ContientMacros(Workbooks(fichier))
      Workbooks(fichier).Close False
      If test Then Cells(lig, 1) = "OUI"
      Cells(lig, 2) = dossier
      Cells(lig, 3) = fichier
      lig = lig + 1
    End If
    fichier = Dir
  Wend
Next
Columns.AutoFit
End Sub
A+

Bonjour job75 et merci à toi
ça fonctionne presque nickel car l'exploration s'arrête au niveau n-1 des répertoires, alors qu'il faudrait que ça descende au dernier niveau, peu en importe le nombre. Si j'ai bien compris, vbDirectory permet d'explorer le niveau n et n-1 dans lequel figure le fichier de recherche (chemin = ThisWorkbook.Path)
on y est presque mais j'ai encore besoin d'un coup de main :eek:


Bonsoir à tous, _____________________(salut job75, 00 ;))
Une autre façon de faire en utilisant la propriété idoine : Ce lien n'existe plus
(disponible à partir d'Excel 2007)
Bonjour Staple1600,
disponible à partir d'Excel 2007 => le pb est là ! j'ai tout sous 2003 :(
dommage
 

job75

XLDnaute Barbatruc
Re : recherche de fichiers contenant macro

Bonjour wwwhttp, DoubleZero, Jean-Marie,

@ DoubleZero tu es gentille d'apprécier toujours autant mes solutions :)

@ Jean Marie .HasVBProject renvoie True s'il y a un module standard même sans aucune macro...

@ wwwhttp je n'ai pas de solution pour un nombre quelconque de niveaux d'imbrications.

Si l'on se fixe le nombre de niveaux on peut à partir de ma solution faire autant de boucles que de niveaux...

Pour terminer, on pourra remarquer que ma solution liste les fichiers des sous-dossiers, du dossier (.) mais aussi du dossier "père" (..).

Si l'on ne veut pas les fichiers du dossier "père" utiliser :

Code:
Sub FichiersAvecMacros()
Dim chemin$, lig&, dossier, liste$, fichier$, test As Boolean
chemin = ThisWorkbook.Path
lig = 2
Application.ScreenUpdating = False
Application.DisplayAlerts = False 'si un fichier est ouvert
[A:C].ClearContents 'RAZ
[A1] = "MACRO": [B1] = "DOSSIER": [C1] = "FICHIER"
'---liste des sous-dossiers---
dossier = Dir(chemin & "\*", vbDirectory)
While dossier <> ""
  If GetAttr(chemin & "\" & dossier) = vbDirectory _
    Then liste = liste & Chr(1) & dossier
  dossier = Dir
Wend
liste = Mid(liste, 2)
'---fichiers du dossier et des sous-dossiers---
For Each dossier In Split(liste, Chr(1))
  If dossier <> ".." Then 'élimine le dossier "père"
    fichier = Dir(chemin & "\" & dossier & "\*xls")
    While fichier <> ""
      If fichier <> ThisWorkbook.Name Then
        Workbooks.Open chemin & "\" & dossier & "\" & fichier
        test = ContientMacros(Workbooks(fichier))
        Workbooks(fichier).Close False
        If test Then Cells(lig, 1) = "OUI"
        Cells(lig, 2) = dossier
        Cells(lig, 3) = fichier
        lig = lig + 1
      End If
      fichier = Dir
    Wend
  End If
Next
Columns.AutoFit
End Sub
A+
 

Staple1600

XLDnaute Barbatruc
Re : recherche de fichiers contenant macro

Bonsoir à tous

[aparté]
@ Jean Marie .HasVBProject renvoie True s'il y a un module standard même sans aucune macro...
Tout utilisateur sensé (ou respectueux) d'Excel ne laisse jamais de modules vides dans un classeur. ;)

Par contre, à la réflexion, je pense (mais pas testé encore) que HasVBProject ne détecte peut-être pas les procédures évènementielles.

Avec les versions supérieures à Excel 2003 (et sous certaines conditions), un simple dir /s *.xlsm et ou *.xlsb *.xlam
pourrait suffire ;)

Et pour les PC récents (et sous Windows), on peut aussi explorer les puissantes fonctionnalités offertes par PowserShell
(en une seule ligne! ;))
Code:
Get-ChildItem "C:\Temp" -Filter *.xls -recurse | Select-String -pattern "End Sub" | group path | select name
test OK sur PC avec W7 64 bits.
(On peut s'amuser à créer une macro qui crée le script Powershell puis l’exécuter par un Shell ou un objet FSO, mais ceci est autre histoire ;) )
[/aparté]
 

job75

XLDnaute Barbatruc
Re : recherche de fichiers contenant macro

Re,

JM je ne connais pas du tout PowserShell...

Une solution semi-automatique pour étudier toute l'arborescence des dossiers :

Code:
Function ContientMacros(Wb As Workbook) As Boolean
Dim o As Object
For Each o In Wb.VBProject.VBComponents
  With o.CodeModule
    ContientMacros = .CountOfDeclarationLines + 1 < .CountOfLines
  End With
  If ContientMacros Then Exit For
Next
End Function

Sub FichiersAvecMacros()
Dim chemin$, lig&, dossier, fichier$, test As Boolean, x
'---initialisation---
chemin = ThisWorkbook.Path 'chemin du 1er niveau
lig = 2
[A:C].ClearContents 'RAZ
[A1] = "MACRO": [B1] = "DOSSIER": [C1] = "FICHIER"
Application.DisplayAlerts = False 'si un fichier est ouvert
'---boucles sur les dossiers---
1 Application.ScreenUpdating = False
dossier = Mid(chemin, InStrRev(chemin, "\") + 1)
fichier = Dir(chemin & "\*xls")
While fichier <> ""
  If fichier <> ThisWorkbook.Name Then
    Workbooks.Open chemin & "\" & fichier
    test = ContientMacros(Workbooks(fichier))
    Workbooks(fichier).Close False
    If test Then Cells(lig, 1) = "OUI"
    Cells(lig, 2) = dossier
    Cells(lig, 3) = fichier
    lig = lig + 1
  End If
  fichier = Dir
Wend
Columns.AutoFit
Application.ScreenUpdating = True
Cells(lig - 1, 1).Select 'pour faire défiler la feuille
2 ChDir chemin
x = Application.GetOpenFilename(Title:="Ouvrez un fichier quelconque du dossier à traiter")
If x = False Then Exit Sub
x = Left(x, InStrRev(x, "\") - 1)
If x = chemin Then GoTo 2
chemin = x
GoTo 1
End Sub
Le dossier du fichier sélectionné dans la boîte de dialogue est analysé.

Edit : ajouté Cells(lig - 1, 1).Select 'pour faire défiler la feuille

Séparer alors en 2 volets pour figer la ligne 1.

A+
 
Dernière édition:

Staple1600

XLDnaute Barbatruc
Re : recherche de fichiers contenant macro

Re


Sinon, on peut aussi utiliser cette bonne vieille invite MSDOS
(dans le cas d'un PC de disposant pas de Powershell)
(toujours en un ligne ;))
Code:
findstr /s /m "End Sub" *.xls?

Ou en créant la liste dans un fichier txt
Code:
findstr /s /m "End Sub" *.xls? >ListVBAFic.txt

NB: On peut aussi piloter ce batch avec un script VBS (donc sans passer par Excel)
(En créant un fichier *.vbs avec le bloc-notes)
 

job75

XLDnaute Barbatruc
Re : recherche de fichiers contenant macro

Bonjour wwwhttp, le fil, le forum,

Je disais au post #7 :

Si l'on se fixe le nombre de niveaux on peut à partir de ma solution faire autant de boucles que de niveaux...

Alors accrochez vos ceintures, ce code permet de traiter jusqu'à 5 niveaux d'imbrication des sous-dossiers :

Code:
Option Explicit 'déclaration des variables obligatoire
Dim lig&, dico As Object 'mémorise les variables

Sub FichiersAvecMacros_5_niveaux_d_imbrication()
Dim chemin$, chem1$, chem2$, chem3$, chem4$, chem5$
Dim niveau1$(), niveau2$(), niveau3$(), niveau4$(), niveau5$()
Dim dossier1, dossier2, dossier3, dossier4, dossier5
'---initialisation---
chemin = ThisWorkbook.Path 'chemin du 1er niveau
lig = 2
Application.ScreenUpdating = False
[A:C].ClearContents 'RAZ
[A1] = "MACRO": [B1] = "DOSSIER": [C1] = "FICHIER"
'---listes des sous-dossiers---
SousDossiers chemin, niveau1
For Each dossier1 In niveau1
  chem1 = chemin & "\" & dossier1
  SousDossiers chem1, niveau2
  For Each dossier2 In niveau2
    chem2 = chem1 & "\" & dossier2
    SousDossiers chem2, niveau3
    For Each dossier3 In niveau3
      chem3 = chem2 & "\" & dossier3
      SousDossiers chem3, niveau4
      For Each dossier4 In niveau4
        chem4 = chem3 & "\" & dossier4
        SousDossiers chem4, niveau5
Next dossier4, dossier3, dossier2, dossier1
'---fichiers du dossier et des sous-dossiers---
Set dico = CreateObject("Scripting.Dictionary")
Fichiers chemin
For Each dossier1 In niveau1
  chem1 = chemin & "\" & dossier1
  Fichiers chem1
  For Each dossier2 In niveau2
    chem2 = chem1 & "\" & dossier2
    Fichiers chem2
    For Each dossier3 In niveau3
      chem3 = chem2 & "\" & dossier3
      Fichiers chem3
      For Each dossier4 In niveau4
        chem4 = chem3 & "\" & dossier4
        Fichiers chem4
        For Each dossier5 In niveau5
          chem5 = chem4 & "\" & dossier5
          Fichiers chem5
Next dossier5, dossier4, dossier3, dossier2, dossier1
Columns.AutoFit
End Sub

Sub SousDossiers(chemin$, niveau$())
Dim dossier$, n&
dossier = Dir(chemin & "\*", vbDirectory)
On Error Resume Next
If IsError(niveau(0)) Then ReDim niveau(0) Else n = UBound(niveau) + 1
On Error GoTo 0
While dossier <> ""
  If GetAttr(chemin & "\" & dossier) = vbDirectory And dossier <> "." And dossier <> ".." Then
    ReDim Preserve niveau(n)
    niveau(n) = dossier
    n = n + 1
  End If
  dossier = Dir
Wend
End Sub

Sub Fichiers(chemin$)
Dim dossier$, fichier$, fich$, test As Boolean
dossier = Mid(chemin, InStrRev(chemin, "\") + 1)
If dossier = "" Then Exit Sub
fichier = Dir(chemin & "\*xls")
While fichier <> ""
  fich = LCase(chemin & "\" & fichier)
  If Not dico.exists(fich) Then 'élimine les doublons
    dico(fich) = ""
    If fichier <> ThisWorkbook.Name Then
      On Error Resume Next
      Workbooks(fichier).Close False 'si un fichier du même nom est ouvert
      On Error GoTo 0
      Workbooks.Open fich
      test = ContientMacros(Workbooks(fichier))
      Workbooks(fichier).Close False
      If test Then Cells(lig, 1) = "OUI"
      Cells(lig, 2) = dossier
      Cells(lig, 3) = fichier
      lig = lig + 1
    End If
  End If
  fichier = Dir
Wend
End Sub

Function ContientMacros(Wb As Workbook) As Boolean
Dim o As Object
For Each o In Wb.VBProject.VBComponents
  With o.CodeModule
    ContientMacros = .CountOfDeclarationLines + 1 < .CountOfLines
  End With
  If ContientMacros Then Exit For
Next
End Function
Bonne journée et A+
 
Dernière édition:

wwwhttp

XLDnaute Nouveau
Re : recherche de fichiers contenant macro

Bonjour à tous

Re,
Une solution semi-automatique pour étudier toute l'arborescence des dossiers :
Le dossier du fichier sélectionné dans la boîte de dialogue est analysé.
A+
progrès intéressant mais avec 900 000 fichiers de tous types repartis dans plus de 110 000 dossiers, sous-dossiers, sous-sous-dossiers,... j'ai trouvé jusqu'à 14 imbrications (on ne rigole pas :eek:), ça va être long !


Re
Sinon, on peut aussi utiliser cette bonne vieille invite MSDOS
(dans le cas d'un PC de disposant pas de Powershell)
(toujours en un ligne ;))
Code:
findstr /s /m "End Sub" *.xls?

Ou en créant la liste dans un fichier txt
Code:
findstr /s /m "End Sub" *.xls? >ListVBAFic.txt
ça tourne très bien cette petite commande, juste en mettant xl? au lieu de xls? sinon les xls (2003) ne sont pas pris en compte


Bonjour wwwhttp, le fil, le forum,
Alors accrochez vos ceintures, ce code permet de traiter jusqu'à 5 niveaux d'imbrication des sous-dossiers :
Bonne journée et A+
je vais tester mais si ça ne suffit pas en niveau, y a t'il une contre-indication à descendre plus bas en adaptant le code ?
 

job75

XLDnaute Barbatruc
Re : recherche de fichiers contenant macro

Re,

progrès intéressant mais avec 900 000 fichiers de tous types repartis dans plus de 110 000 dossiers, sous-dossiers, sous-sous-dossiers,... j'ai trouvé jusqu'à 14 imbrications (on ne rigole pas :eek:), ça va être long !

Il n'est pas difficile d'adapter le code du post #11 à 14 niveaux d'imbrications, il suffit de créer 13 boucles imbriquées au lieu de 4 pour les sous-dossiers et 14 au lieu de 5 pour les fichiers.

Par contre chez moi (Excel 2003) pour un fichier la durée du traitement (ouverture et test) est d'environ 0,5 seconde.

Donc si 110000 fichiers à ouvrir => 55000 secondes => 15 heures 17 minutes.

Et si 900000 fichiers à ouvrir => 450000 secondes => 5 jours 5 heures :rolleyes:

A+
 

Staple1600

XLDnaute Barbatruc
Re : recherche de fichiers contenant macro

Bonsoir à tous

Bonjour à tous
progrès intéressant mais avec 900 000 fichiers de tous types repartis dans plus de 110 000 dossiers, sous-dossiers, sous-sous-dossiers,... j'ai trouvé jusqu'à 14 imbrications (on ne rigole pas :eek:), ça va être long !

quote_icon.png
Envoyé par Staple1600
Re
Sinon, on peut aussi utiliser cette bonne vieille invite MSDOS
(dans le cas d'un PC de disposant pas de Powershell)
(toujours en un ligne ;))
findstr /s /m "End Sub" *.xls?
Ou en créant la liste dans un fichier txt
findstr /s /m "End Sub" *.xls? >ListVBAFic.txt


ça tourne très bien cette petite commande, juste en mettant xl? au lieu de xls? sinon les xls (2003) ne sont pas pris en compte
L'avantage avec findstr /s c'est qu'on parcoure tous les répertoires et sous répertoires sans ouvrir les fichiers.
Je suis curieux de savoir en combien de temps ce batch parcoure tes 900 000* fichiers ;)
Si ton lecteur s'appelle C alors testes ceci
findstr /s /m "End Sub" c:\*.xls >ListVBAFic.txt

NB
: Combien de fichiers *.xls sur tes 900 0000 fichiers ?
 
Dernière édition:

Discussions similaires

Réponses
19
Affichages
2 K

Statistiques des forums

Discussions
312 502
Messages
2 089 022
Membres
104 006
dernier inscrit
CABROL