XL 2010 Copier un fichiers txt qui ont le même nom de plusieurs sous-dossiers vers un dossier

hamzaelhathout

XLDnaute Nouveau
Bonjour,

J'ai un dossier qui contiens plusieurs sous-dossier pour chaque journée qui ont pour nom "aaaa-mm-jj".
Dans ces sous-dossier, il y a un rapport au format txt qui a toujours le même nom "XXXXX.txt"

Je voudrais créer une macro qui aille chercher ce fichier txt dans chaque sous dossier et me le copie avec comme nom, celui du sous dossier dans lequel il se trouve (donc aaaa-mm-jj.txt) vers un dossier "destination".

J'ai cherché dans le forum mais je n'ai pas trouvé exactement ça.

Merci d'avance.
 
Solution
Super merci.

J'ai adapté pour le nom du fichier exact.

VB:
Option Explicit

Sub Test()
    Call FichiersSousRépertoires("C:\Users\Youssef\Documents\fansub\testmacro\")
End Sub

'---------------------------------------------
'Fichiers des sous-répertoires d'un répertoire
'---------------------------------------------
Sub FichiersSousRépertoires(NomRépertoire As String)
    Dim oFSO As Object
    Dim oDir As Object
    Dim oSubDir As Object
    Dim oFile As Object

    'File System Object
    Set oFSO = CreateObject("Scripting.FileSystemObject")

    'Directory Object
    Set oDir = oFSO.GetFolder(NomRépertoire)

    'Parcours des sous-répertoires du répertoire
    For Each oSubDir In oDir.SubFolders
        'Parcours des fichiers du...

patricktoulon

XLDnaute Barbatruc
re
attend j'ai fait plaisir a @Dudu2
j'ai aussi refait la sienne avec if else
j'ai ajouté aussi avec dossier ou pas
je crois que pour une liste ca va le faire FSO on clôture
perso elle me conviennent toutes les deux

allez pour @Dudu2

VERSION IF ELSE avec variable static
VB:
'**********************************
'Auteur:Dudu2 et patricktoulon
'Version DU-PA _1.2
'Date : 07/02/2021
'Liste Fichier / dossier
'utilisation de FSO (fonction récursif)
'exemple d'utilisation
'tbl = recherche_récursive2(Racine)                      'appel de la fonction tout les fichiers sans les dossiers
'tbl = recherche_récursive2(Racine, WithFolder:=True)    'appel de la fonction tout fichiers  avec les dossiers
'tbl = recherche_récursive2(Racine, ext)                 'appel de la fonction tout les fichiers ayant une partie du nom correspondante a la variable ext sans les dossiers
'tbl = recherche_récursive2(Racine, ext, True)           'appel de la fonction tout les fichiers ayant une partie du nom correspondante a la variable ext avec les dossiers
'***********************************
Option Explicit
Option Compare Text
Sub testFSOX()
    Dim Racine$, tim, ext$, tbl    'on dimentionne un array de 1 item pour commencer
    Racine = "e:"    ' disque à lister
    tim = Timer
    ext = "*.txt"    ' une partie du nom  et l'extension
    tbl = recherche_récursive2(Racine, WithFolder:=True)    'appel de la fonction tout fichiers  avec les dossiers
    MsgBox (Timer - tim) & " secondes ; " & UBound(tbl) & " fichiers avec FSO"
    Cells(1, 1).Resize(UBound(tbl), 1) = tbl
End Sub

Private Function recherche_récursive2(dparent, Optional E As String = "*.*", Optional WithFolder As Boolean = False)    ' As Variant
    Static FSO As Object
    Static t$()
    Static foldercount&
    Dim Lparent As Object, SubFolder As Object, Fichier, i&

    If TypeOf dparent Is Object  Then
        'Appel récursif'
        Set Lparent = dparent
    Else
        'Appel initial'
        foldercount = 0
        ReDim t(0)
        Set FSO = CreateObject("scripting.filesystemobject")    ' on declare l'object
    End If

    Set Lparent = FSO.GetFolder(dparent)
    foldercount = foldercount + Lparent.subfolders.Count    ' et on rajoute le subfolders.count

    If Dir(Lparent.Path & "\" & E) <> "" Then
        If WithFolder Then ReDim Preserve t(UBound(t) + 1): t(UBound(t) - 1) = Lparent.Path   'SI ON LISTE AUSSI LES DOSSIERS , on redim preserve le tableau(t) avec un item de plus et on instruit l'item avec le chemin de dossier trouvé
        For Each Fichier In Lparent.Files    'on boucle sur les fichiers qui sont dans ce dossier
            If Mid(Fichier, InStrRev(Fichier, "\")) Like E Then ReDim Preserve t(UBound(t) + 1): t(UBound(t) - 1) = Fichier:    ' on redim preserve le tableau(t) avec un item de plus et on instruit l'item avec le chemin de fichier trouvé
        Next
    End If
    'If Lparent.subfolders.Count Then
    For Each SubFolder In Lparent.subfolders    'on boucle sur les dossiers qui sont dans ce dossier
        On Error Resume Next    '  pour gérer les dossiers interdits
        'si il y a des fichiers correspondant a la recherche ou si il y a encore un/des sousdossiers dans ce subfolder on relance
        If Dir(SubFolder.Path & "\" & E) <> "" And Not SubFolder.Path Like "*RECYCLE*" Or SubFolder.subfolders.Count > 0 Then recherche_récursive2 SubFolder, E, WithFolder                ' on rappelle la fonction avec pour argument le chemin du sous dossier ainsi que le tableau(t) pour continuer a l'instruire et le part of (nom/ext)
        foldercount = foldercount - 1    'à chaque appel recursif on enleve 1
        Err.Clear
    Next SubFolder
    'End If
    ' transposition 2dim
    If foldercount = 0 Then
        ReDim tbl(UBound(t), 1 To 1)
        For i = LBound(t) To UBound(t): tbl(i, 1) = t(i): Next
        recherche_récursive2 = tbl
    End If
End Function

AVEC VARIABLE RECALL
VB:
'**********************************
'Auteur:patricktoulon
'Version PA _1.2
'Date : 07/02/2021
'Liste Fichier / dossier
'utilisation de FSO (fonction récursif)
'exemple d'utilisation
'tbl = recherche_récursive2(Racine)                      'appel de la fonction tout les fichiers sans les dossiers
'tbl = recherche_récursive2(Racine, WithFolder:=True)    'appel de la fonction tout fichiers  avec les dossiers
'tbl = recherche_récursive2(Racine, ext)                 'appel de la fonction tout les fichiers ayant une partie du nom correspondante a la variable ext sans les dossiers
'tbl = recherche_récursive2(Racine, ext, True)           'appel de la fonction tout les fichiers ayant une partie du nom correspondante a la variable ext avec les dossiers
'***********************************
Option Compare Text
Option Explicit
'patricktoulon liste fichier FSO (fonction récursif)
Sub testFSO0()
    Dim Racine$, tim, ext$, tbl    'on dimentionne un array de 1 item pour commencer
    Racine = "h:"    ' disque à lister
    tim = Timer
    ext = "*.txt"    ' une partie du nom  et l'extension
    tbl = recherche_récursive(Racine, ext, WithFolder:=True)               'appel de la fonction tout lles fichier  avec leur dossier
    MsgBox (Timer - tim) & " secondes ; " & UBound(tbl) & " fichiers avec FSO"
    Cells(1, 1).Resize(UBound(tbl), 1) = tbl
End Sub
'
'
Private Function recherche_récursive(dparent, Optional E As String = "*.*", Optional recall As Boolean = False, Optional WithFolder As Boolean = False)    ' As Variant
    Static FSO As Object
    Static t()
    Static foldercount As Long
    Dim Lparent As Object, SubFolder As Object, Ficher, I&

    If Not recall Then ReDim t(0): Set FSO = CreateObject("scripting.filesystemobject")          ' on declare l'object

    Set Lparent = FSO.GetFolder(dparent)  ' regard sur les fichiers  'on attribue a l'object.getfolder le dossier demandé 'Scripting.Folder

    foldercount = foldercount + Lparent.subfolders.Count    ' et on rajoute le subfolders.count

    If Dir(Lparent.Path & "\" & E) <> "" Then
        If WithFolder Then ReDim Preserve t(UBound(t) + 1): t(UBound(t) - 1) = Lparent.Path   'SI ON LISTE AUSSI LES DOSSIERS , on redim preserve le tableau(t) avec un item de plus et on instruit l'item avec le chemin de dossier trouvé
        For Each Ficher In Lparent.Files    'on boucle sur les fichiers qui sont dans ce dossier
            If Mid(Ficher, InStrRev(Ficher, "\")) Like E Then ReDim Preserve t(UBound(t) + 1): t(UBound(t) - 1) = Ficher:    ' on redim preserve le tableau(t) avec un item de plus et on instruit l'item avec le chemin de fichier trouvé
        Next
    End If
    If Lparent.subfolders.Count Then
        For Each SubFolder In Lparent.subfolders    'on boucle sur les dossiers qui sont dans ce dossiers
            'a = UBound(t) + 1: ReDim Preserve t(1 To a): t(a) = SubFolder.Path 'SI ON LISTE AUSSI LES DOSSIERS , on redim preserve le tableau(t) avec un item de plus et on instruit l'item avec le chemin de dossier trouvé

            On Error Resume Next    '  pour gérer les dossier interdits
            'si il y a des fichiers correspondant a la recherche ou si il y a encore un/des sousdossiers dans ce subfolder on relance
            If Dir(SubFolder.Path & "\" & E) <> "" And Not SubFolder.Path Like "*RECYCLE.BIN*" Or SubFolder.subfolders.Count > 0 Then recherche_récursive SubFolder.Path, E, True, WithFolder  ' on rappelle la fonction avec pour argument le chemin du sous dossier ainsi que le tableau(t) pour continuer a l'instruire et le part of (nom/ext)
            foldercount = foldercount - 1    'a chaque appel recursif on enleve 1
            Err.Clear
        Next SubFolder
    End If
    If foldercount = 0 Then
        ReDim tbl(UBound(t), 1 To 1)
        For I = LBound(t) To UBound(t): tbl(I, 1) = t(I): Next
        recherche_récursive = tbl
    End If
End Function
alors @ChTi160 et toi tu es content? 🤣 ;)
 

Dudu2

XLDnaute Barbatruc
@patricktoulon,
Tu t'embêtes bien avec ce foldercount.
VB:
    ' transposition 2dim
    'If foldercount = 0 Then
    If Not TypeOf dparent Is Object  Then

Ou dans la version avec le paramètres Recall (inutile de mon point de vue puisqu'on peut s'en passer comme dans ta version TypeOf)
Code:
    ' transposition 2dim
    'If foldercount = 0 Then
    If Not recall Then

Je te l'ai dit, avec les appels récursifs, le 1er appel est aussi le dernier Exit de la fonction.
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
??????
ok ça fonctionne mais je pige pas

edit:
Debug.Print foldercount & "-" & Lparent & TypeOf dparent Is Object

d'accords j'ai compris ca se produit apres tout les apel récursifs donc a la fin de l'appel(1)

c'est de la compet' ces fonctions
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Lorsque tu entres pour la 1ère fois dans la fonction, tu appelles cette même fonction récursivement (ça pourrait être une autre fonction d'ailleurs) mais tu ne sors pas de la fonction tant que les autres appels ne sont pas terminés.
1612728280822.png

Chaque Appel de la fonction créé son environnement propre (arguments, variables, SAUF variables Static communes à tous les Appels). Chaque cadre bleu est une exécution / instance de la fonction qui a son propre environnement.

En Retour #1 tu retrouves ton environnement d'Appel #1. Et donc tu sais que tu as terminé le boulot et tu peux traiter la phase finale.
En l'occurrence, dans l'environnement d'Appel #1 on a bien Not TypeOf dparent Is Object ou Recall = False. Ce qui n'est pas le cas des autres instances de la fonction.

Concernant les arguments passés, si le même argument est passé ByRef, c'est son adresse qui est passée à chaque appel et donc toutes les instances de la fonction travailleront sur la même zone mémoire. Un peu comme les variables Static.
S'ils sont passés ByVal, ils seront propres à chaque instance de la fonction car Excel donne à la fonction une copie de l'argument original de l'appelant qu'on peut d'ailleurs modifier sans impacter la variable de l'appelant.
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
merci pour le shéma j'ai pigé
bien qu'il ne soit pas tout a fait exact sauf si dossier1 contient qu'un seul sous dossier
en même tant moi qui les utilise souvent j'aurais du comprendre
ça fait 2 jours que l'on est dessus j'ai la tète en vrac entre fso dir,dir dos 🤯 🤯 🤯

perso c'est pas pour me venter mais des fonctions abouties comme ça et aussi rapides avec FSO tu trouve nul part
on a fait du bon boulot ;)
 

patricktoulon

XLDnaute Barbatruc
re:
VB:
'**********************************
'Auteur:Dudu2 et patricktoulon
'Version DU-PA _1.2
'Date : 07/02/2021
'Liste Fichier / dossier
'utilisation de FSO (fonction récursif)
'exemple d'utilisation
'tbl = recherche_récursive2(Racine)                      'appel de la fonction tout les fichiers sans les dossiers
'tbl = recherche_récursive2(Racine, WithFolder:=True)    'appel de la fonction tout fichiers  avec les dossiers
'tbl = recherche_récursive2(Racine, ext)                 'appel de la fonction tout les fichiers ayant une partie du nom correspondante a la variable ext sans les dossiers
'tbl = recherche_récursive2(Racine, ext, True)           'appel de la fonction tout les fichiers ayant une partie du nom correspondante a la variable ext avec les dossiers
'***********************************
Option Explicit
Option Compare Text
Sub testFSOX()
    Dim Racine$, tim, ext$, tbl    'on dimentionne un array de 1 item pour commencer
    Racine = "h:"    ' disque à lister
    tim = Timer
    ext = "*.txt"    ' une partie du nom  et l'extension
    tbl = recherche_récursive2(Racine, WithFolder:=True)    'appel de la fonction tout fichiers  avec les dossiers
    MsgBox (Timer - tim) & " secondes ; " & UBound(tbl) & " fichiers avec FSO"
    Cells(1, 1).Resize(UBound(tbl), 1) = tbl
End Sub

Private Function recherche_récursive2(dparent, Optional E As String = "*.*", Optional WithFolder As Boolean = False)    ' As Variant
    Static FSO As Object
    Static t$()
      Dim Lparent As Object, SubFolder As Object, Fichier, I&

    If TypeOf dparent Is Object  Then
        'Appel récursif'
        Set Lparent = dparent
    Else
        'Appel initial'
        ReDim t(0)
        Set FSO = CreateObject("scripting.filesystemobject")    ' on declare l'object
    End If

    Set Lparent = FSO.GetFolder(dparent)
    
    If Dir(Lparent.Path & "\" & E) <> "" Then
        If WithFolder Then ReDim Preserve t(UBound(t) + 1): t(UBound(t) - 1) = Lparent.Path   'SI ON LISTE AUSSI LES DOSSIERS , on redim preserve le tableau(t) avec un item de plus et on instruit l'item avec le chemin de dossier trouvé
        For Each Fichier In Lparent.Files    'on boucle sur les fichiers qui sont dans ce dossier
            If Mid(Fichier, InStrRev(Fichier, "\")) Like E Then ReDim Preserve t(UBound(t) + 1): t(UBound(t) - 1) = Fichier:    ' on redim preserve le tableau(t) avec un item de plus et on instruit l'item avec le chemin de fichier trouvé
        Next
    End If
    If Lparent.subfolders.Count Then
    For Each SubFolder In Lparent.subfolders    'on boucle sur les dossiers qui sont dans ce dossier
        On Error Resume Next    '  pour gérer les dossiers interdits
        'si il y a des fichiers correspondant a la recherche ou si il y a encore un/des sousdossiers dans ce subfolder on relance
        If Dir(SubFolder.Path & "\" & E) <> "" And Not SubFolder.Path Like "*RECYCLE*" Or SubFolder.subfolders.Count > 0 Then recherche_récursive2 SubFolder, E, WithFolder                ' on rappelle la fonction avec pour argument le chemin du sous dossier ainsi que le tableau(t) pour continuer a l'instruire et le part of (nom/ext)
         Err.Clear
    Next SubFolder
    End If
    ' transposition 2dim a la fin de l'execussion de l'appel(1) de la fonction déclenché apres la fin des sub apel récursifs
           If Not TypeOf dparent Is Object  Then
     ReDim tbl(UBound(t), 1 To 1)
        For I = LBound(t) To UBound(t): tbl(I, 1) = t(I): Next
        recherche_récursive2 = tbl
    End If
End Function
 

patricktoulon

XLDnaute Barbatruc
bonjour @Dudu2
un fonction passe partout multi option c'est bien mais elle a des inconvénients

je récapitule
nous avions tout deux une fonction FSO de base(chacun sa méthode et sa façon de coder)
listant un disque complet de 1.1 Secondes à 1.3 Secondes

donc réellement 1.6 à 1.9(en effet le transpose n’était n'est pas compté dans la sub d'appel )

je suis parti après sur de l'optional histoire de réduire le temps d’exécution pour une recherche de fichier ayant une partie du nom et / ou une extension précise

je suis parti dans l'idée de transposer en interne avec un tableau 2 dim dans le quel on transfère l 'array à la fin de l'appel#1

au final on se retrouve avec une fonction somme toute assez rapide pour du FSO

MAIS!!!!
ce matin les idées claires j'ai constaté que le listage du disque complet (5000 fichier avec dossier ou pas)
prenais entre 2.3 et 2.9 secondes(c'est encore acceptable) mais on a doublé le temps 🤔
mince alors que c'est il passé

en démontant ligne par ligne je me suis rendu compte que selon le besoin les conditions était plus handicapantes que bénéfiques

j'ai donc repris ma fonction de base 0 et ajouté tout ce qui avais été ajouté mais dans des conditions
on retrouve ainsi la rapidité que ce soit en listage complet ou liste ciblée

on retombe donc bien à 1.6(transpose compris) pour le disque complet et on a toujours la rapidité pour une liste ciblée

la fonction base 0 + option+ aménagement des actions selon le mode appelé
VB:
'**********************************
'Auteur:patricktoulon
'Version PA _1.0
'Date : 06/02/2021
'Liste Fichier / dossier
'utilisation de FSO (fonction récursif)
'exemple d'utilisation
'tbl = recherche_récursive2(Racine)                      'appel de la fonction tout les fichiers sans les dossiers
'tbl = recherche_récursive2(Racine, WithFolder:=True)    'appel de la fonction tout fichiers  avec les dossiers
'tbl = recherche_récursive2(Racine, ext)                 'appel de la fonction tout les fichiers ayant une partie du nom correspondante a la variable ext sans les dossiers
'tbl = recherche_récursive2(Racine, ext, True)           'appel de la fonction tout les fichiers ayant une partie du nom correspondante a la variable ext avec les dossiers
'***********************************
Sub testFSO()
    Dim Racine$, tim, ext$, T
    Racine = "h:"    ' disque à lister
    tim = Timer
    ext = "*.txt"    ' une partie du nom  et l'extension
    T = recherche_récursive1(Racine)    ', ext   'appel de la fonction t est injecté comme tel
    MsgBox (Timer - tim) & " secondes ; " & UBound(T) & " fichiers avec FSO"
    If UBound(T) > 0 Then Cells(1, 1).Resize(UBound(T), 1) = T
End Sub
'
'
Private Function recherche_récursive1(dparent, Optional E As String = "*.*", Optional recall As Boolean = False, Optional WithFolder As Boolean = False)     ' As Variant
    Static FSO As Object
    Static T$()
    Dim Lparent As Object, SubFolder As Object, Ficher

    If Not recall Then ReDim T(0): Set FSO = CreateObject("scripting.filesystemobject")    ' on declare l'object
    Set Lparent = FSO.GetFolder(dparent)  ' regard sur les fichiers  'on attribue a l'object.getfolder le dossier demandé 'Scripting.Folder

    '-------------------------------------------------------------
    'condition garde fou pour fichier ou dossiers non autorisé
    If Not Lparent Like "*RECYCLE*" And Not Lparent Like "BIN\" And Not Lparent Like "*System Volume Information*" And Not Lparent Like "*Perflog*" Then
        '----------------------------------------------------------------
        If WithFolder Then ReDim Preserve T(UBound(T) + 1): T(UBound(T) - 1) = Lparent.Path   'SI ON LISTE AUSSI LES DOSSIERS , on redim preserve le tableau(t) avec un item de plus et on instruit l'item avec le chemin de dossier trouvé
        If Dir(Lparent.Path & "\" & E) <> "" Then
        For Each Ficher In Lparent.Files    'on boucle sur les fichiers qui sont dans ce dossier
           
            If E = "*.*" Then    'si on ne cherche pas avec partie de nom ou extention particuliereon zappe le teste likeE du fichier
            'il ajoute 1.3 sur un listage complet du disque contenant environ 5000 fichiers
                ReDim Preserve T(UBound(T) + 1): T(UBound(T) - 1) = Ficher:    ' on redim preserve le tableau(t) avec un item de plus et on instruit l'item avec le chemin de fichier trouvé
            Else 'le test dir ajoute plus d'une seconde  sur le temps pour une recherche sans extention
                If Mid(Ficher, InStrRev(Ficher, "\")) Like E Then ReDim Preserve T(UBound(T) + 1): T(UBound(T) - 1) = Ficher:    ' on redim preserve le tableau(t) avec un item de plus et on instruit l'item avec le chemin de fichier trouvé
            End If
       
        Next
        End If
        For Each SubFolder In Lparent.subfolders    'on boucle sur les dossiers qui sont dans ce dossiers
           
            If E = "*.*" Then    'si on ne cherche pas de part name ou extention particuliere
                recherche_récursive1 SubFolder.Path, E, True, WithFolder
            Else
                On Error Resume Next
                If Dir(SubFolder.Path & "\" & E) <> "" Or SubFolder.subfolders.Count > 0 Then recherche_récursive1 SubFolder.Path, E, True, WithFolder               ' on rappelle la fonction avec pour argument le chemin du sous dossier ainsi que le tableau(t) pour continuer a l'instruire
                Err.Clear
            End If
       
        Next SubFolder
    End If
   
    If Not TypeOf dparent Is Object  Then
       
        If UBound(T) < 5000 Then
            recherche_récursive1 = Application.Transpose(T) ' transpose ajoute 0.4 sur le temps pour le disque complet 5000 fichiers
        Else
            ReDim tbl(UBound(T), 1 To 1)
            For I = LBound(T) To UBound(T): tbl(I, 1) = T(I): Next
            recherche_récursive1 = tbl
        End If
   
    End If
End Function
 

Dudu2

XLDnaute Barbatruc
Bonjour @patricktoulon,
Y a un truc que je ne comprends pas dans cette version. Tu utilises ton système avec Recall et donc tu passes toujours un String (SubFolder.Path) dans les appels de la fonctions. Donc le test If Not TypeOf dparent Is Object Then sera toujours vrai et ne distingue pas le 1er appel des autres. Si tu veux le faire c'est plutôt If Not Recall.
 

patricktoulon

XLDnaute Barbatruc
oui c'est vrai la condition pour transpose devrait être avec recall
j'ai pas tout corrigé oupss!!

cela dit c'est du simple au double pour tout ce que j'ai expliquer plus haut
après de multiples tests en dessous de 500 lignes le transfert tableau 1 dim dans tableau 2 dim est plus rapide que transpose donc je laisserais que celui la et j'abandonne la fonction transpose
j'ai tenter de faire ces modifs conditionnelles avec ta version ou ma 2d avec les shunte error mais c'est pas possible puisque tout est géré justement par cette gestion d'erreur globale
je met ca au propre
 

patricktoulon

XLDnaute Barbatruc
@Dudu2
j'ai dis 500 heu.. 5000 pardon
voila les deux versions (recall/[object/string])
dans l'ensemble la mienne est plus avantageuse dans le sens ou
  • la recherche ciblée dur plus longtemps avec la version dudupat
  • la liste complète pas de différence (ou insignifiante)
dans la tienne j'ai quand même été obligé de mettre la gestion recycle et autres
 

Pièces jointes

  • 2 model FSO avec condition .xlsm
    24.9 KB · Affichages: 6

patricktoulon

XLDnaute Barbatruc
re
la deuxième non c'est la notre (la mienne avec tes idées d'amélioration)

ben si tu a le temps et l'envie d'ajouter la recherche ciblée aux moins les extensions dans ta version
parce que c'est ça qui est important finalement
sinon dir vba le fait très bien et plus vite moyennant quelque ajustements sauf quelques fichiers qui ma fois finalement ont été nommés au tuturkistan :)

je suis curieux de savoir comment tu ferais avec ta version ?
 

patricktoulon

XLDnaute Barbatruc
bon j'ai re re re regardé ta version #72
tu a encore laissé la coquille (table/tablefichiers) dans la sub --> j'ai corrigé pour tester
j'ai ajouté le partname et/ou extension
mais le soucis c'est que complet ou juste ce qui est recherché le temps c'est pareil
tu mouline tout les dossiers quand même

pour le complet tu met 0.96XXXXXX et le ciblé tu met 0.932XXXXXX

j'ai bien essayé plein de chose mais avec ton code difficile de gérer ça


ton code du #72 avec extension ou partname

VB:
'Option Explicit

Sub TestFichiersRépertoireFSO()
    Dim Table As Variant, tim#
    Const Répertoire = "H:" ' "H:\Téléchargements"
    tim = Timer
    Table = FichiersRépertoireFSO(Répertoire, , "*.txt")
   Table = TransposeExcel(Table)
    
    'If not VarType(Table) = vbBoolean Then
    If IsArray(Table) Then
        MsgBox UBound(Table) & " fichier(s) trouvé(s) dans le répertoire <" & Répertoire & "> en " & Timer - tim & " s/"
        ActiveSheet.Range("A1:A" & Rows.Count).ClearContents
        ActiveSheet.Range("A1").Resize(UBound(Table)).Value = Table
    Else
        MsgBox "Aucun fichier dans le répertoire <" & Répertoire & ">"
    End If
End Sub

'---------------------------------------------------------------
'Liste des fichiers de l'arborescence complète d'un répertoire
'par la "méthode FileSystemObject"
'
'- NomRépertoire: chaine du nom du répertoire concerné
'                 (avec ou sans '\' final)
'- NoRecycle: True (valeur par défaut) pour ne pas avoir les
'             fichiers de la poubelle dans la liste résultat
'             si NomRépertoire est une lettre de lecteur (drive)
'- Return: table à 1 dimension des noms complets des fichiers
'          ou False si aucun fichier dans le répertoire
'---------------------------------------------------------------
Function FichiersRépertoireFSO(ByVal NomRépertoire As Variant, Optional NoRecycle As Boolean = True, Optional Ext As String = "*.*") As Variant
    'Tableau résultat static pour être indépendant des appels récursifs
    Static TabNomsFichiers() As String
    Static NbFichiers As Long
    
    'Variable du FileSystemObject commune à toutes les instances de la fonction
    Static oFSO As Object
    
    'Variable spécifiques à une instance de la fonction
    Dim oDir As Object
    Dim oSubDir As Object
    Dim oFile As Object
    Dim InitialCall As Boolean
    
    'Appel recursif de cette fonction (par elle-même ci-dessous)
    If TypeOf NomRépertoire Is Object  Then
        InitialCall = False
        
        'Valorise l'objet Folder
        Set oDir = NomRépertoire
    
    'Appel initial
    Else
         InitialCall = True
        
        'Table résultat
        Erase TabNomsFichiers
          NbFichiers = 0
        
        'File System Object
        Set oFSO = CreateObject("Scripting.FileSystemObject")
        
        'Complémente éventuellement le nom du répertoire avec '\'
        If Right(NomRépertoire, 1) <> "\" Then NomRépertoire = NomRépertoire & "\"
        
        'Valorise l'objet Folder
        Set oDir = oFSO.GetFolder(NomRépertoire)
    End If
    
    'On ne traite pas ces répertoires
    If oDir.Name = "System Volume Information" _
    Or (NoRecycle And oDir.Name = "$RECYCLE.BIN") Then Exit Function
    
    'Parcours des fichiers du répertoire en cours
    On Error Resume Next
    
    For Each oFile In oDir.Files
        If Err.Number = 0 Then
            'Stocke le nom complet du fichier en table
            If oFile.Name Like Ext Then
            NbFichiers = NbFichiers + 1
            ReDim Preserve TabNomsFichiers(1 To NbFichiers)
            TabNomsFichiers(NbFichiers) = oFile.Path
        End If
        Else
            'Error #70 Authorisation refusée, Error #76 Path not found
            If Not (Err.Number = 70 Or Err.Number = 76) Then MsgBox "FichiersRépertoireFSO erreur #" & Err.Number
            Err.Clear
        End If
    Next oFile
    On Error GoTo 0
    
    'Parcours des sous-répertoires du répertoire en cours
    For Each oSubDir In oDir.SubFolders
        'Appels recursifs identifiés par "|" en début du nom de répertoire
         Call FichiersRépertoireFSO(oSubDir, NoRecycle, Ext)
        Next oSubDir
    
    'Return value
    If InitialCall Then
        FichiersRépertoireFSO = False
        If NbFichiers > 0 Then FichiersRépertoireFSO = TabNomsFichiers
    End If
End Function
'--------------------------------------------------------------------
'Fonction de Tranpose selon la logique de WorksheetFunction.Transpose
'sauf que WorksheetFunction.Transpose se limite à 65536 éléments
'alors que cette fonction lève cette limite.
'--------------------------------------------------------------------
Function TransposeExcel(t As Variant) As Variant
    Dim tt() As Variant
    Dim NbDimensions As Integer
    Dim i As Long
    Dim j As Long
    
    If Not IsArray(t) Then
        MsgBox "Function TransposeExcel: error argument is not an array !"
        Exit Function
    End If
    
    '1 ou 2 dimensions pour t ?
    On Error Resume Next
    i = UBound(t, 2)
    If Err.Number Then NbDimensions = 1 Else NbDimensions = 2
    On Error GoTo 0

    '------------------------------------------------------
    'Tableau origine 1 dimension
    '=> Tableau destination 2 dimensions dont la 2ème est 1
    '------------------------------------------------------
    If NbDimensions = 1 Then
        ReDim tt(LBound(t) To UBound(t), 1 To 1)
        
        For i = LBound(t) To UBound(t)
            tt(i, 1) = t(i)
        Next i
    End If
    
    '----------------------------
    'Tableau origine 2 dimensions
    '----------------------------
    If NbDimensions = 2 Then
        '-----------------------------------------------
        'Tableau origine 2 dimensions dont la 2ème est 1
        '=> Tableau destination 1 dimension
        '-----------------------------------------------
        If UBound(t, 2) = 1 Then
            ReDim tt(LBound(t, 1) To UBound(t, 1))
            
            For i = LBound(t, 1) To UBound(t, 1)
                tt(i) = t(i, 1)
            Next i
            
        '-------------------------------------------------
        'Tableau origine 2 dimensions dont la 2ème est > 1
        '=> Tableau destination 2 dimensions inversées
        '-------------------------------------------------
        Else
            ReDim tt(LBound(t, 2) To UBound(t, 2), LBound(t, 1) To UBound(t, 1))
            
            For i = LBound(t, 2) To UBound(t, 2)
                For j = LBound(t, 1) To UBound(t, 1)
                    tt(i, j) = t(j, i)
                Next j
            Next i
        End If
    End If
    
    TransposeExcel = tt
End Function


et en plus j'ai remarqué une erreur que je faisais j'utilisais dir(mid(ficher,instrrev(.....))& E) au lieu de dir(ficher.name & E)
je viens de tomber en dessous 0.2pour la recherche ciblée

incroyable l'erreur (object/string) je gagne 0.25XXX sur l'analyse complète du disque en recherche ciblé
je suis donc à 0.1XXXXXXX
 

Dudu2

XLDnaute Barbatruc
Bon j'ai adapté pour l'option Extension que tu veux ajouter.
Je passe plutôt une "pattern" de la seule extension "txt" ou "xls*" et pas une "pattern" du nom de fichier complet comme tu as choisi de le faire.
Le Transpose, je pense qu'il vaut mieux le sortir, car on ne sait pas à priori à quoi est destinée la Table résultat des noms de fichiers.
Pour reprendre la code que tu as cité avec cette option:
VB:
'Option Explicit

Sub TestFichiersRépertoireFSO()
    Dim Table As Variant, tim#
    Const Répertoire = "H:" ' "H:\Téléchargements"
    tim = Timer
    'Table = FichiersRépertoireFSO(Répertoire, , "txt")
    Table = FichiersRépertoireFSO(Répertoire, , "xls*")

    'If not VarType(Table) = vbBoolean Then
    If IsArray(Table) Then
        Table = TransposeExcel(Table)
        MsgBox UBound(Table) & " fichier(s) trouvé(s) dans le répertoire <" & Répertoire & "> en " & Timer - tim & " s/"
        ActiveSheet.Range("A1:A" & Rows.Count).ClearContents
        ActiveSheet.Range("A1").Resize(UBound(Table)).Value = Table
    Else
        MsgBox "Aucun fichier dans le répertoire <" & Répertoire & ">"
    End If
End Sub

'---------------------------------------------------------------
'Liste des fichiers de l'arborescence complète d'un répertoire
'par la "méthode FileSystemObject"
'
'- NomRépertoire: chaine du nom du répertoire concerné
'                 (avec ou sans '\' final)
'- NoRecycle: True (valeur par défaut) pour ne pas avoir les
'             fichiers de la poubelle dans la liste résultat
'             si NomRépertoire est une lettre de lecteur (drive)
'- Extension: "Pattern" / modèle de l'extension des fichiers à
'             sélectionner ("txt", "xls*" ou "" pour tous)
'- Return: table à 1 dimension des noms complets des fichiers
'          ou False si aucun fichier dans le répertoire
'---------------------------------------------------------------
Function FichiersRépertoireFSO(ByVal NomRépertoire As Variant, _
                               Optional NoRecycle As Boolean = True, _
                               Optional Extension As String = "") As Variant
    'Tableau résultat static pour être indépendant des appels récursifs
    Static TabNomsFichiers() As String
    Static NbFichiers As Long
    
    'Variable du FileSystemObject commune à toutes les instances de la fonction
    Static oFSO As Object
    
    'Variable spécifiques à une instance de la fonction
    Dim oDir As Object
    Dim oSubDir As Object
    Dim oFile As Object
    Dim InitialCall As Boolean
    Dim TakeIt As Boolean
    Dim NomObjetEnErreur As String
    
    'Appel recursif de cette fonction (par elle-même ci-dessous)
    If TypeOf NomRépertoire Is Object  Then
        InitialCall = False
        
        'Valorise l'objet Folder
        Set oDir = NomRépertoire
    
    'Appel initial
    Else
         InitialCall = True
        
        'Table résultat
        Erase TabNomsFichiers
          NbFichiers = 0
        
        'File System Object
        Set oFSO = CreateObject("Scripting.FileSystemObject")
        
        'Complémente éventuellement le nom du répertoire avec '\'
        If Right(NomRépertoire, 1) <> "\" Then NomRépertoire = NomRépertoire & "\"
        
        'Valorise l'objet Folder
        Set oDir = oFSO.GetFolder(NomRépertoire)
    End If
    
    'Si option NoRecycle et répertoire poubelle on ne traite pas
    If NoRecycle And Len(oDir.Name) = 12 Then
        If UCase(oDir.Name) = "$RECYCLE.BIN" Then Exit Function
    End If
    
    'Si le répertoire est "System Volume Information" on ne traite pas
    If oDir.Name = "System Volume Information" Then Exit Function
    
    'Vérifie si le répertoire contient des fichiers avec l'extension
    If Len(Extension) = 0 Then
        TakeIt = True
    Else
         'Il faut couvrir la fonction Dir() par un On Error pour intercepter ses erreurs:
        'Erreur #52:
        '> Accès refusé
        '> Un ou plusieurs caractères du nom du répertoire sont codés en Unicode
        'Erreurs #53:
        '> La longueur du chemin est > longueur maxi
        'Erreurs qui sinon vont se manifester ultérieurement dans la boucle "For Each oSubDir In oDir.subfolders".
        On Error Resume Next
        TakeIt = Len(Dir(oDir.Path & "\*." & Extension)) > 0
        If err.Number <> 0 Then TakeIt = True
        On Error GoTo 0
    End If
    
    'On n'examine les fichiers du répertoire que s'il contient des fichiers avec l'extension
    If TakeIt Then
        err.Clear
        On Error Resume Next
        For Each oFile In oDir.Files
            If err.Number = 0 Then
                'Test si correspondance de l'extension
                If Len(Extension) = 0 Then
                    TakeIt = True
                Else
                    If oFSO.GetExtensionName(oFile.Name) Like Extension Then TakeIt = True Else TakeIt = False
                End If
                
                'Stocke le nom complet du fichier en table
                If TakeIt Then
                    NbFichiers = NbFichiers + 1
                    ReDim Preserve TabNomsFichiers(1 To NbFichiers)
                    TabNomsFichiers(NbFichiers) = oFile.Path
                End If
            
            'Fichier en erreur
            Else
                NomObjetEnErreur = "Fichier <"
                If oFile Is Nothing _
                Then NomObjetEnErreur = NomObjetEnErreur & "Nothing" & ">" _
                Else NomObjetEnErreur = NomObjetEnErreur & oFile.Name & ">"
                GoSub TraiteErreur
            End If
        Next oFile
        On Error GoTo 0
    End If
    
    'Parcours des sous-répertoires du répertoire en cours
    On Error Resume Next
    For Each oSubDir In oDir.subfolders
        If err.Number = 0 Then
            'Appels recursifs identifiés par le type Object de l'argument OsubDir
             Call FichiersRépertoireFSO(oSubDir, NoRecycle, Extension)
        
        'Répertoire en erreur
        Else
            NomObjetEnErreur = "Répertoire <"
            If oSubDir Is Nothing _
            Then NomObjetEnErreur = NomObjetEnErreur & "Nothing" & ">" _
            Else NomObjetEnErreur = NomObjetEnErreur & oSubDir.Path & ">"
            GoSub TraiteErreur
        End If
    Next oSubDir
    On Error GoTo 0
    
    'Return value
    If InitialCall Then
        FichiersRépertoireFSO = False
        If NbFichiers > 0 Then FichiersRépertoireFSO = TabNomsFichiers
    End If
    Exit Function
    
TraiteErreur:
    'Error #70 Authorisation refusée
    'Error #76 Path not found - Cas des noms de répertoires ou fichiers dont le chemin complet > Maximum (247, 259)
    'Autre erreur à identifier ?
    If Not (err.Number = 70 Or err.Number = 76) Then
        MsgBox "FichiersRépertoireFSO erreur #" & err.Number & vbCrLf & "Sur " & NomObjetEnErreur & ""
    End If
    NomObjetEnErreur = ""
    err.Clear
    Return
End Function

'--------------------------------------------------------------------
'Fonction de Tranpose selon la logique de WorksheetFunction.Transpose
'sauf que WorksheetFunction.Transpose se limite à 65536 éléments
'alors que cette fonction lève cette limite.
'--------------------------------------------------------------------
Function TransposeExcel(T As Variant) As Variant
    Dim tt() As Variant
    Dim NbDimensions As Integer
    Dim i As Long
    Dim j As Long

    If Not IsArray(T) Then
        MsgBox "Function TransposeExcel: error argument is not an array !"
        Exit Function
    End If

    '1 ou 2 dimensions pour t ?
    On Error Resume Next
    i = UBound(T, 2)
    If Err.Number Then NbDimensions = 1 Else NbDimensions = 2
    On Error GoTo 0

    '------------------------------------------------------
    'Tableau origine 1 dimension
    '=> Tableau destination 2 dimensions dont la 2ème est 1
    '------------------------------------------------------
    If NbDimensions = 1 Then
        ReDim tt(LBound(T) To UBound(T), 1 To 1)

        For i = LBound(T) To UBound(T)
            tt(i, 1) = T(i)
        Next i
    End If

    '----------------------------
    'Tableau origine 2 dimensions
    '----------------------------
    If NbDimensions = 2 Then
        '-----------------------------------------------
        'Tableau origine 2 dimensions dont la 2ème est 1
        '=> Tableau destination 1 dimension
        '-----------------------------------------------
        If UBound(T, 2) = 1 Then
            ReDim tt(LBound(T, 1) To UBound(T, 1))

            For i = LBound(T, 1) To UBound(T, 1)
                tt(i) = T(i, 1)
            Next i

        '-------------------------------------------------
        'Tableau origine 2 dimensions dont la 2ème est > 1
        '=> Tableau destination 2 dimensions inversées
        '-------------------------------------------------
        Else
            ReDim tt(LBound(T, 2) To UBound(T, 2), LBound(T, 1) To UBound(T, 1))

            For i = LBound(T, 2) To UBound(T, 2)
                For j = LBound(T, 1) To UBound(T, 1)
                    tt(i, j) = T(j, i)
                Next j
            Next i
        End If
    End If

    TransposeExcel = tt
End Function
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re OK
la tienne
demo7.gif


la mienne
demo8.gif


soit la tienne environ 7 fois plus lente sur du ciblé

et la mienne Ext fait office de partname aussi
du genre une recherche ext="*toto*.txt"

le soucis dans la tienne c'est ou placer un test (dir globale+ext )<>"" dans la boucle de récurisivité qui déclanche une erreur forcement avec les dossier sus nommé précédemment dans la fonction
car tu les gère a l'examen
moi je les shunte de l'examen carrément en ne les prenant pas en compte dans le IF globale
je shunte aussi dans la boucle subfolder les dossiers qui ne ressortent pas avec le dir global avec ext
autrement dit

if dir (subfolder.path &"\" & E)<>"" --> je lance sinon passe au suivant
 
Dernière édition:

Discussions similaires