XL 2010 Lister un dossier comportant des sous-dossiers

Magic_Doctor

XLDnaute Barbatruc
Bonjour,

Je voudrais, comme le titre l'indique, lister un dossier comportant des sous-dossiers.
Supposons que le dossier, dans le disque "G", s'intitule "Musique".
Ses sous-dossiers : "Blues" | "Classic" | "Folk" | "Jazz" | "Tangos Mortels" ...
Mais, par exemple, dans "Jazz" il y a d'autres sous-dossiers : "Guitare" | "Piano" | "Saxophone" ...
Et dans "Guitare" : "Emily Remler" | "Grant Green" | "Joe Pass" | "Wes Montgomery" ...

Pour récupérer tous les noms de fichiers d'un dossier unique, j'ai trouvé :
VB:
Sub Listage()

    Dim Dossier$, Fichier$, i%
  
    Dossier = "G:\iPod\"  'il n'y a ici qu'un seul dossier
    Fichier = Dir(Dossier)
    i = 0
    Do While Fichier <> ""
        i = i + 1
        Worksheets(1).Range("A" & i) = Fichier
        Fichier = Dir
    Loop
End Sub
Comment faire pour récupérer aussi la totalité des contenus de tous les sous-dossiers ?
 

Dudu2

XLDnaute Barbatruc
Bonsoir @Magic_Doctor,
Peut-être au travers d'une boucle qui passerait en revue tous les éventuels sous-dossiers.
Je comprends pas bien tes questionnements. A moins qu'ils ne soient rétrospectifs.

Si tu veux le faire en VBA, c'est fait dans le fichier que je t'ai mis en Post #7.
Sinon, en ligne de commande, @Staple1600 a aussi donné une solution et fait référence à un autre sujet qui couvre cette question.
 

Magic_Doctor

XLDnaute Barbatruc
As tu au moins lu le sommaire du site??
la 15eme ligne plus particulièrement
Re,

Merci pour l'info. Je viens de lire cette 15ème ligne et ça fait parfaitement l'affaire :
VB:
Sub TestListeFichiers()
    Dim Dossier As String
 
    'Définit le répertoire pour débuter la recherche de fichiers.
    '(Attention à ne pas indiquer un répertoire qu contient trop de sous-dossiers ou de
    'fichiers, sinon le temps de traitement va être très long).
    Dossier = "G:\Films\Español"
 
    'Appelle la procédure de recherche des fichiers
    ListeFichiers Dossier
 
    'Ajuste la largeur des colonnes A:E en fonction du contenu des cellules.
    Columns("A:E").AutoFit
    MsgBox "Terminé"
End Sub

Sub ListeFichiers(Repertoire As String)
    '
    'Nécessite d'activer la référence "Microsoft Scripting RunTime"
        'Dans l'éditeur de macros (Alt+F11):
        'Menu Outils
        'Références
        'Cochez la ligne "Microsoft Scripting RunTime".
        'Cliquez sur le bouton OK pour valider.
 
    Dim Fso As Scripting.FileSystemObject
    Dim SourceFolder As Scripting.Folder
    Dim SubFolder As Scripting.Folder
    Dim FileItem As Scripting.File
    Dim i As Long
 
    Set Fso = CreateObject("Scripting.FileSystemObject")
    Set SourceFolder = Fso.GetFolder(Repertoire)
 
    'Récupère le numéro de la dernière ligne vide dans la colonne A.
    i = Range("A65536").End(xlUp).Row + 1
 
    'Boucle sur tous les fichiers du répertoire
    For Each FileItem In SourceFolder.Files
        'Inscrit le nom du fichier dans la cellule
        Cells(i, 1) = FileItem.Name
'        'Ajoute un lien hypertexte vers le fichier
'        ActiveSheet.Hyperlinks.Add Anchor:=Cells(i, 1), _
'            Address:=FileItem.ParentFolder & "\" & FileItem.Name
'        'Indique la date de création
'        Cells(i, 2) = FileItem.DateCreated
'        'Indique la date de dernier acces
'        Cells(i, 3) = FileItem.DateLastAccessed
'        'Indique la date de dernière modification
'        Cells(i, 4) = FileItem.DateLastModified
'        'Nom du répertoire
'        Cells(i, 5) = FileItem.ParentFolder
        i = i + 1
    Next
 
    '--- Appel récursif pour lister les fichier dans les sous-répertoires ---.
    For Each SubFolder In SourceFolder.subfolders
        ListeFichiers SubFolder.Path
    Next
End Sub
C'est court, succinct et rapide. Je n'ai eu qu'à virer ce dont je n'avais pas besoin.

Mais une petite question. Il faut activer la référence "Microsoft Scripting RunTime". Pourquoi diable ne l'est-elle pas par défaut ?
 

kiki29

XLDnaute Barbatruc
Salut, à lire/assimiler/appliquer : Early Late binding et M$
Bref on développe en Early ( Référence cochée ) pour principalement IntelliSense
et déploie en Late ( Référence décochée ) surtout dans un environnement hétérogène.
VB:
Private Sub ListeFichiers_Late(Repertoire As String, bSousDossier As Boolean)
Dim Fso As Object
Dim SourceFolder As Object
Dim SubFolder As Object
Dim FileItem As Object
Dim i As Long

    Set Fso = CreateObject("Scripting.FileSystemObject")
    Set SourceFolder = Fso.GetFolder(Repertoire)
    
    i = Feuil1.Range("A" & Rows.Count).End(xlUp).Row + 1
    For Each FileItem In SourceFolder.Files
        Feuil1.Cells(i, 1) = FileItem.Name
        i = i + 1
    Next FileItem
    
    If bSousDossier Then
        For Each SubFolder In SourceFolder.subfolders
            ListeFichiers_Late SubFolder.Path
        Next SubFolder
    End If
    
    Set SourceFolder = Nothing
    Set Fso = Nothing
End Sub

VB:
Private Sub ListeFichiers_Early(Repertoire As String)
Dim Fso As Scripting.FileSystemObject
Dim SourceFolder As Scripting.Folder
Dim SubFolder As Scripting.Folder
Dim FileItem As Scripting.File
Dim i As Long

    Set Fso = New Scripting.FileSystemObject
    Set SourceFolder = Fso.GetFolder(Repertoire)

    i = Feuil1.Range("A" & Rows.Count).End(xlUp).Row + 1

    For Each FileItem In SourceFolder.Files
        Feuil1.Cells(i, 1) = FileItem.Name
        i = i + 1
    Next FileItem

    For Each SubFolder In SourceFolder.subfolders
        ListeFichiers_Early SubFolder.Path
    Next SubFolder

    Set SourceFolder = Nothing
    Set Fso = Nothing
End Sub
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
Bonjour à tous
pour des gros dossiers avec beaucoup de fichiers et sous dossier a visiter
on peut accélérer filesystemobject
on peut aussi gérer certaines erreurs (des noms avec caractères particuliers,trop long,fichiers system,etc...)
avec ce qui suit on peut choisir de lister avec une partie du nom ou une extension
VB:
'**************************************************************
'fonction récursive pour lister les fichiers d'un disque ou dossier
'Utilisation de filesystemobject(FSO)
'-------------------------------------
'                          THEME
'recherche D 'amelioration  pour la lenteur de FSO en récursif
'recherche des moyens de controler les erreurs du aux noms trop long  ou fichiers interdit  ou system ou caracteres particuliers
'------------------------------------

'Auteurs Dudu2 et patricktoulon  sur exceldownload
'version 1.5
'Date:08/02/2021
'mise en place du principe (Part name) valable aussi pour (si juste extension demandée:ex;[*.XXX])
'suppression du stockage des erreurs et des msgbox d'erreur
'suppression commentaires
'utilisation d'une fonction de transposition de l'array simplifiée (horizontal(1 dim) To vertical(2 dim))pour palier au limite de la fonction transpose d'excel

'Date:08/02/2021
'accélération du processus
'en ajoutant du test dir non bloquant pour zapper les dossiers
'ne contenant pas de fichier avec l'extension ou la partie du nom demandée
'Date:13/02/2021
'remplacement du bloc  <<if takeit>> par un jumping (etiquette "ScanFolder")
'pour jumper directement sur la boucle des dossiers on  zappe directement la partie du code boucle ofile si pas de fichier
'****************************************************************
Option Explicit
Option Compare Text
Dim Appelcount
Dim countdoss
Function TransposeArray(arr) ' fonction de transposition pour palier au limites de la fonction transpose d'excel
    Dim tbl(), I&: ReDim tbl(LBound(arr) To UBound(arr), 1 To 1)
    For I = LBound(arr) To UBound(arr): tbl(I, 1) = arr(I): Next
    TransposeArray = tbl
End Function
'
Sub listeFSOGOSUB()
    Dim Table As Variant, tim
    ActiveSheet.Range("A1:A" & Rows.Count).ClearContents
    Const Répertoire = "h:\": tim = Timer
    Const Ext$ = "*.mp3"
    Appelcount = 0    '
    countdoss = 0
    Table = FSO_List_FICHIERS2(Répertoire, Ext)
    If IsArray(Table) Then
        Table = TransposeArray(Table)
        tim = Format(Timer - tim, "#0.000 S")

        MsgBox UBound(Table) & " fichier(s) <""" & Ext & """> trouvé(s) dans le répertoire <" & Répertoire & "> en " & tim & " s/" & _
               vbCrLf & "pour " & Appelcount & " appels de la fonction dans dossier et sous dossier" & vbCrLf & countdoss & " dossiers utilement explorés"
        
        ActiveSheet.Range("A1").Resize(UBound(Table)).Value = Table

    Else
        MsgBox "Aucun fichier dans le répertoire <" & Répertoire & ">" & vbCrLf & "ayant une partie du nom contenant  " & Ext
    End If
End Sub

Function FSO_List_FICHIERS2(ByVal Folder As Variant, Optional PartName As String = "") As Variant
    Static tbl() As String: Static NbFichiers As Long: Static oFSO As Object
    Appelcount = Appelcount + 1
     countdoss = countdoss + 1
Dim oDir As Object, oSubDir As Object, oFile As Object, First_Call As Boolean, TakeIT As Boolean

    If TypeOf Folder Is Object  Then                            'si ce nest pas le premier appel  Foler est un objet folder membre de FSO
        First_Call = False                                      'si ce nest pas le premier appel  on positionne First_Call a false des les 2d appel
        Set oDir = Folder                                       'si ce nest pas le premier appel  Odir est donc un object Folder membre de FSO
    Else                                                        'si c'est le premier appel Folder est de type string
        First_Call = True                                       'si c'est le premier appel first_call est a true
        Erase tbl                                               'si c'est le premier appel on eraze la variable tableau  <<tbl>>
        NbFichiers = 0                                          'si c'est le premier appel on met la variables NbFichiers à 0
        Set oFSO = CreateObject("Scripting.FileSystemObject")   'si c'est le premier appel on créée l'object FSO
        If Right(Folder, 1) <> "\" Then Folder = Folder & "\"   'si c'est le premier appel si le slach de fin on l'ajoute
        Set oDir = oFSO.getfolder(Folder)                       'si c'est le premier appel on instruit l'object Folder<<Odir>>avec le string du dossier
    End If

    TakeIT = True                                               'on met la variable Takeit à true d'office
    ' on ouvre une gestion d'erreur globale (pour les permissions refusées ou les noms portants des caracteres speciaux)
    'la gestion est valable aussi pour la boucle subFolder elle es fermé a chaque fin d'appels récursifs
    On Error Resume Next
    If Len(PartName) > 0 Then TakeIT = Len(Dir(oDir.Path & "\" & PartName)) > 0    'si partname demandé on test de presence de (fichier avec PartName dans le nom) dans le dossier en une seule fois
    If Err.Number <> 0 Or TakeIT = False Then Err.Clear: countdoss = countdoss - 1: GoSub Scanfolder ' si erreur ou TakeIt =false on zappe l'exploration des fichiers on va directement à l'exploration des sous dossiers avec gosub
 
  
    For Each oFile In oDir.Files            'boucle sur les fichiers
        If Err.Number = 0 Then              'si pas d'erreur
            If Len(PartName) = 0 Then       'si pas de PartName demandé on memorise le fichier directement
                NbFichiers = NbFichiers + 1: ReDim Preserve tbl(1 To NbFichiers): tbl(NbFichiers) = oFile.Path
            Else                            'si PartName demandé on teste si le nom de fichier like PartName
                If oFile.Name Like PartName Then NbFichiers = NbFichiers + 1: ReDim Preserve tbl(1 To NbFichiers): tbl(NbFichiers) = oFile.Path                'Stocke le nom complet du fichier en table
            End If
        End If
        Err.Clear                                       ' on clear l'erreur au cas ou
    Next oFile

Scanfolder:                                             ' etiquette du jumping d'exploration

    For Each oSubDir In oDir.subfolders                 ' boucle sur les dossiers
          
            If Err.Number = 0 Then
            FSO_List_FICHIERS2 oSubDir, PartName        ' on relance la fonction ( appel récursif)
        Else: Err.Clear                                 ' sinon on clear l'erreur si dossier interdit ou special
        End If
    Next oSubDir

    On Error GoTo 0                                     ' ferme la gestion d'erreur globale

' si c'est le premier appel  donc on a lu tout l'arborescence en appels récursifs on peut maintenant instruire le return de la fonction avec le tableau
    If First_Call Then
        FSO_List_FICHIERS2 = False                      ' on met le return de la fonction a false
        If NbFichiers > 0 Then FSO_List_FICHIERS2 = tbl ' si NbFichiers est plus grand que 0 le return de la fonction est la tableau
    End If

End Function
 

Discussions similaires

Statistiques des forums

Discussions
312 215
Messages
2 086 318
Membres
103 176
dernier inscrit
jean.yvesjean.yves