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
en fait le dir donne false pour les dossiers interdits aussi bien sur
peut être aussi les noms de dossiers
mais on s'en fout on gère l'erreur quoi qu'il arrive c'est ça le but avec ce dir
et non seulement on gere les erreurs mais ça permet de zapper le moulinage subfolder dans les gestions d'erreur et leur return de gosub
si ce dir te dit non c'est que
  • soit y a pas de fichier avec l' extension demandée
  • soit il y a un fichier interdit dedans ( tant pis pour les autre fichier de cette racine)
  • soit c'est un dossier interdit
et de toute façon si tu met pas le dir, tes erreurs tu les a dans le message après

a' la seule différence sans ce dir c'est que tu a mouliné pour avoir ce msgbox alors qu'avec le dir tu n'a plus de msgbox ,donc tout les dossiers en défauts sont zappés voila ou il est le temps gagné ;)
de 123 S je passe à 39/40
et je maintient le fait que sans utiliser de variable pour dir a partir du 2d appel le dir est perdu (dans une fonction pas dans une sub) hein ;)

d'ailleurs ça fonctionne avec variable non?;)
demain je ferais un exemple représentatif dans les mêmes conditions dans une fonction récursive (dir/fso) et j'essaierais de mettre des debug pour lire les erreurs si c'est possible

là j'essai de voir autre chose car on a un problème plus sournois (la mémoire et le dimensionnement de tableau )

d'ailleurs je crois me souvenir que j'ai un code de demo dir en récursif démontrant ce problème que j'avais fait pour un membre sur DVP ET il est incontestable
 

Dudu2

XLDnaute Barbatruc
Tu as eu la très bonne idée / intuition d'encadrer le Dir() par un On Error, chose à laquelle je n'aurais jamais pensé puisque le Dir() ne générait jamais de plantage VBA ce qui, comme je l'ai dit avant, me semble tout à fait anormal à partir du moment où on récupère ses erreurs sous un On Error.

mais on s'en fout on gère l'erreur quoi qu'il arrive c'est ça le but avec ce dir
et non seulement on gere les erreurs mais ça permet de zapper le moulinage subfolder
Lorsque le Dir() est en erreur, il faut scanner le dossier car le Dir() n'a pas donné la réponse à la question qu'on lui posait à savoir: y a-t-il des fichiers de telle extension dans ce répertoire ? Et s'il n'a pas donné la réponse, il faut y aller voir.

Je pense que tu vas perdre ton temps avec cette histoire de récursivité qui n'a rien à voir avec le problème. Le Dir() se plante à cause des noms de répertoire en Unicode, comme le GetAttr() se plante sur les noms de fichiers (ou répertoires d'ailleurs) Unicode retournés par le Dir() dans la solution VBA DIR. Au moins pour les erreurs #53. Tu as juste à essayer de reproduire l'erreur, de dumper le nom du répertoire concerné et constater. Pour les erreurs #52, je n'ai pas approfondi la recherche.
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
bonjour dudu2
non je n'ai pas le soucis (si dir erreur ) et justement ca liste quand même les sous dossiers
non je perds pas de temps au contraire je met au propre des chose que j'utilise depuis longtemps
Donc
  1. pour FSO je garde ta version post #194 modifié avec le dir
  2. mais j'ai fait une 2d version de la tienne avec partname
  3. pour le dir vba je garde ma version perso 2016 a la quelle j'ai fait les mises a jour et corrections concernant les problèmes que l'on a soulevé
  4. pour la version bath celle là elle est simple
et pour la démo du dir non fermé j'ai retrouvé mon exemplaire
ne m'en veux pas j' étais pas aussi aguerri à l’époque elle date de 2009
c'est pour te dire 🤣 elle a rien a voir avec ma fonction dire vba de 2016
voila le code de cette vieillerie

teste le sur un dossier pas trop lourd
c'est juste un test je ne suis plus ce model de toute façon ma version 2016 étant imparable et encore plus plus maintenant

donc testons ce truc sorti de la bad cave
  1. met la fenetre debug ;lance la sub dans VBE et et regarde
  2. appuie sur esc pour arrêter
  3. débloque la ligne entre les deux lignes d’étoile
  4. et relance
cette fonction si il n'y avait pas d'erreur de fichier ou dossier a gérer fonctionnerait parfaitement bien
VB:
Option Explicit  'déclaration obligatoire des variables

Public Type TypeFichier
    nom As String
    repertoire As String
    taille As Long
End Type

Public ListeFichiers() As TypeFichier
'

Public Sub liste_fichiers()

    Dim Dossier As String
    Dim NbreFicTot As Long

    Debug.Print String(100, "*")

    ReDim ListeFichiers(0 To 0) As TypeFichier

    Dossier = "h:"

    Call Dir_Fichiers(Dossier)

    NbreFicTot = UBound(ListeFichiers)
    MsgBox NbreFicTot & " fichiers", vbInformation, "Fin Liste Fichiers"
End Sub

Public Sub Dir_Fichiers(ByVal Dossier As String)

'utilise la Variable globale : 'ListeFichiers() as TypeFichier

    Dim Chemin As String
    Dim FichierLu As String
    Dim NbreFichiersLus As Long, NbreFichiers As Long
    Dim i As Long
    Dim crit
    NbreFichiersLus = 0
    Chemin = Dossier & "\"
    'liste les fichiers et les dossiers avec l'option vbDirectory
    crit = vbDirectory Or vbHidden Or vbNormal Or vbArchive Or vbReadOnly Or vbSystem Or vbVolume

    FichierLu = Dir(Chemin, vbDirectory)
    Do
        NbreFichiersLus = NbreFichiersLus + 1
        If FichierLu <> "." And FichierLu <> ".." Then
            On Error Resume Next
            If (GetAttr(Chemin & FichierLu) And vbDirectory) = vbDirectory Then
                'c'est un répertoire, on l'examine de facon récursive
                If Error.Number = 0 Then
                    Debug.Print "Dossier: " & Chemin & FichierLu
                    Debug.Print "debut de  Dossier: " & Chemin & FichierLu & "  " & String(70, "-")
                    Call Dir_Fichiers(Chemin & FichierLu)
                    Debug.Print "Fin Dossier: " & Chemin & FichierLu & "  " & String(70, "-")
                    'après avoir examiné le sous-dossier, il faut repositionner Dir sur l'entrée suivante
                    'car la fonction dir n'est pas récursive et a donc perdue la dernière position
                    'on réinitialise donc Dir et repositionne le flag à la bonne place avec NbreFichiersLus
                    FichierLu = Dir(Chemin, vbDirectory)
                    '------------------------------------------------------------
                    'il faut fermer les dir sinon le dir sur le quel on revient est perdu
                    For i = 1 To NbreFichiersLus - 1
                        '********************************************************
                        'If FichierLu <> "" Then FichierLu = Dir ' ici le dir récursif des instance passées
                        '*******************************************************
                    Next i
                    '---------------------------------------------------------------
                Else
                    MsgBox FichierLu
                    'traiter les fichierLu en erreurs ici
                End If
            Else
                'c'est un fichier, on le met dans la liste globale
                'augmente de 1 la taille de la liste en préservant le contenu du tableau de la liste

                If Error.Number = 0 Then
                    On Error GoTo 0
                    Debug.Print FichierLu
                    NbreFichiers = UBound(ListeFichiers) + 1
                    ReDim Preserve ListeFichiers(0 To NbreFichiers) As TypeFichier
                    'ajoute le fichier à la liste
                    ListeFichiers(NbreFichiers).nom = FichierLu
                    ListeFichiers(NbreFichiers).repertoire = Chemin
                    ListeFichiers(NbreFichiers).taille = FileLen(Chemin & FichierLu)
                End If
            End If
        End If
        'passe à l'entrée suivante de la fonction Dir
        FichierLu = Dir ' ici le dir recursif de l'instance
    Loop While FichierLu <> ""

End Sub
méthode dans l'ordre de rapidité
dir bath
dir vba (ma version 2016)
dir fso 194
dir fso partname
les deux dernières ayant le même temps
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Pour ne rien laisser au hasard, je viens de refaire un test en listant les répertoires en erreur avec le n° d'erreur et je connais maintenant avec certitude la cause des 2 erreurs que le Dir() rencontre:
- Erreur #53: la longueur du chemin est > ??? caractères (je pense 247 à confirmer)
- Erreur #52: un ou plusieurs caractères du nom du répertorie sont codés en Unicode
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
avec ma dir vba 2016
1612957049474.png
 

patricktoulon

XLDnaute Barbatruc
re c'est celle ci
et je pense que je peux encore l'améliorer
VB:
'**********************************************************
'                fonction récursive pour dir vba
'utilisation de Dir VBA
'auteur: patricktoulon Sur DVP et Exceldownloads
'date:09/11/2016
'
'mises a jour
'date:03/15/2018: utilisation d'une collection pour le stockage provisoire des dossiers
'date 07/02/2021:désormais la fonction compile l'array a la fin de l'appel #1 de la fonction (recall=false)
'date 07/02/2021: ajout de l'argument "PartName"
'date 08/02/2021: ajout d'une fonction de transposition simple pour eviter la limite de la fonction transpose de vba pour 2007 et ceux qui n'on pas installé le KB complement de correction du LAA pour 2013 2010 version disque
'date 09/02/2021: ajout de la gestion d'erreur et correction sur les fichiers portant un nom avec des caracteres spéciaux
'                ainsi que les dossiers ou fichiers interdits
'*************************************************************
Option Explicit

Function TransposeArray(arr)
    Dim T(), I&
    ReDim T(LBound(arr) To UBound(arr), 1 To 1)
    For I = LBound(arr) To UBound(arr): T(I, 1) = arr(I): Next
    TransposeArray = T
End Function
Sub testDIR_1()
    Dim tim#, T, extension$
    [A1].CurrentRegion.Clear
    extension = "*.txt"
    tim = Timer
    T = DirList("h:\", PartName:=extension)

    If IsArray(T) Then
        MsgBox Timer - tim & " secondes pour " & UBound(T) & " fichier(s)"
        [A1].Resize(UBound(T)) = TransposeArray(T)
    Else
        MsgBox "pas de fichier"
    End If

End Sub
Function DirList(dossier As String, Optional recall As Boolean = False, Optional PartName As String = "") As Variant
    Dim ItemVu As String, SubFolderCollection As New Collection, I As Long, a As Long, q As Long, criteres, arr1, arr2, subdossier, x
    Static tbl$()    'tbl est statique
    arr1 = Array("a~", "a`", "a^", "a¨", "e`", "e^", "e¨", "i`", "i^", "i¨", "o~", "o`", "o^", "o¨", "u`", "u^", "u¨")    'array caracteres séparés
    arr2 = Array("ã", "à", "â", "ä", "è", "ê", "ë", "ì", "î", "ï", "õ", "ò", "ô", "ö", "ù", "û", "ü")    'array caracteres regroupés
    If recall = False Then ReDim tbl(0)    ' si recall  on redim un tableau  de zero item (pour la creation du tableau)
    criteres = vbDirectory Or vbSystem Or vbHidden Or vbArchive Or vbReadOnly Or vbNormal
    On Error Resume Next    'gestion des fichiers dossiers system et interdit ou generant une erreur(PerLog,recycle,etc..)
    ItemVu = Dir(dossier, criteres)
    If Error.Number = 0 Then    ' si pas d'erreur on examine le contenu
        'examen  du dossier courrant
        Do While ItemVu <> vbNullString    'boucle tant que DIR renvoie une chaine
            If ItemVu <> "." And ItemVu <> ".." And Not ItemVu Like "*RECYCLE*" Then
                On Error Resume Next
                If (GetAttr(dossier & ItemVu) And vbDirectory) = vbDirectory Then    'test Dossier
                    If Err.Number > 0 Then    'si erreur c'est un fichier(particulier ou caracteres particulier)
                        If Err.Number = 53 Then    'si c'est des caracteres bizarres
                            For q = 0 To UBound(arr1): ItemVu = Replace(Replace(ItemVu, arr1(q), arr2(q)), UCase(arr1(q)), UCase(arr2(q))): Next  'replace caracteres
                            If PartName <> "" Then
                            If ItemVu Like PartName Then ReDim Preserve tbl(UBound(tbl) + 1): tbl(UBound(tbl) - 1) = "erreur !!" & Err.Number & "-->" & dossier & ItemVu
                            Else
                                ReDim Preserve tbl(UBound(tbl) + 1): tbl(UBound(tbl) - 1) = "erreur !!" & Err.Number & "-->" & dossier & ItemVu
                            End If
                        Else
                            'si autre erreur
                            If PartName <> "" Then
                            If ItemVu Like PartName Then ReDim Preserve tbl(UBound(tbl) + 1): tbl(UBound(tbl) - 1) = "erreur !!" & Err.Number & "-->" & dossier & ItemVu
                            Else
                                ReDim Preserve tbl(UBound(tbl) + 1): tbl(UBound(tbl) - 1) = "erreur !!" & Err.Number & "-->" & dossier & ItemVu
                            End If
                        End If
                        'si dossier
                    Else
                        SubFolderCollection.Add dossier & ItemVu    'sinon ajout dans la collection de dossier
                    End If
                    Err.Clear
                Else    'sinon c'est un fichier et pas un concombre:)

                    'If ItemVu Like PartName Then
                    If PartName <> "" Then
                    If ItemVu Like PartName Then ReDim Preserve tbl(UBound(tbl) + 1): tbl(UBound(tbl) - 1) = dossier & ItemVu
                    Else
                        ReDim Preserve tbl(UBound(tbl) + 1): tbl(UBound(tbl) - 1) = dossier & ItemVu
                    End If
                End If
            End If
            ItemVu = Dir()
        Loop
    Else
        Err.Clear    'si erreur a la racine du dir actuel
    End If
    'examen des sub dossier appel récursif
    For Each subdossier In SubFolderCollection
    DirList subdossier & "\", True, PartName
     Next subdossier
    DirList = False
    If Not recall Then DirList = tbl  ' return du tableau (apres le dernier appel récursif )'economie de 0.3000 secondes
End Function
 

Dudu2

XLDnaute Barbatruc
@ChTi160, je vais essayer ce soir.
Mais je dois apporter une correction suite à l'exécution sur mon C.
Je n'ai pas eu d'erreur #5 (Appel de procédure ou argument non valide)

- Erreur #53: la longueur du chemin est > longueur maxi (je pense 247 à confirmer)
- Erreur #52: 2 possibilités:
> Accès refusé
>un ou plusieurs caractères du nom du répertorie sont codés en Unicode

Je dois aussi apporter une légère modif au code pour tester le UCase(oDir.Name) = "$RECYCLE.BIN" car sur C: j'ai du $Recycle.Bin et ailleurs du $RECYCLE.BIN.
 

ChTi160

XLDnaute Barbatruc
Merci Dudu2 !
juste pour expliquer ma demande !
Hier je suis tombé sur une procédure .
qui contenait ca :
Dim strFileName As String, f As Integer, strExecutable As String, r As Long
If Len(strFileType) = 0 Then Exit Function ' no file type
strFileName = String$(255, " ") 'ici
strExecutable = String$(255, " ")'ici
GetTempFileName CurDir, "", 0&, strFileName ' get a temporary file name
je travaille sur un fichier ou je crée des Fichiers Text dans lesquels ensuite je vais chercher des Données.
voir aussi le Lien ou l'on parle de ce problème : Est-il un moyen pour DIR(chemin) en VBA pour gérer les chaînes de plus de 260?
pas tout Compris Lol
Pas expert du Tout Lol !
jean marie
 
Dernière édition:

ChTi160

XLDnaute Barbatruc
Re
il y a aussi ceci !
le Lien : Naming Files, Paths, and Namespaces

Maximum Path Length Limitation​

In editions of Windows before Windows 10 version 1607, the maximum length for a path is MAX_PATH, which is defined as 260 characters. In later versions of Windows, changing a registry key or using the Group Policy tool is required to remove the limit. See Maximum Path Length Limitation for full details.

jean marie
 
Dernière édition:

Discussions similaires

Statistiques des forums

Discussions
315 095
Messages
2 116 166
Membres
112 675
dernier inscrit
Tazra_IMOU