Autres Faire une recherche de sous-dossiers Windows (pas de fichiers) dans un dossier précis à partir de son nom contenu dans une cellule

  • Initiateur de la discussion Initiateur de la discussion Michou9
  • Date de début Date de début

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

Michou9

XLDnaute Occasionnel
Bonjour à tous
J'ai un fichier Excel (environ 500 lignes actuellement)
Dans la colonne A sont contenus des noms de sous dossiers
Je souhaiterais pouvoir faire une recherche de ces sous-dossiers Windows dans un dossier précis à partir de ces noms contenus dans les cellules de cette colonne
Les noms de ces sous-dossiers sont assez long
Je suis sous Excel 2007
Je ne sais pas si c'est réalisable ?
Je viens chercher de l'aide
Merci par avance
 
Solution
Bonsoir @Michou9

Avec votre fichier en Poste #5
VBA sans Module de classe.

VB:
Option Explicit
Option Compare Text

Sub Main()
' Procédure VBA :
' A1 = le chemin complet du dossier générale
' B2 = le chemin complet du (nom du dossier exact en A20) qui noyer dans l arborescence du dossier générale
' B2 = le Nom du dossier exact en A20 s'ouvrent automatiquement
' Recherche :
' A20 = Le Nom du dossier Exact (qui noyer dans l'arborescence du dossier générale)
    Application.ScreenUpdating = False
  
    Dim F1 As Worksheet
    Dim DossierRacine As String
    Dim DossierCherche As String
    Dim CheminTrouve As String
  
    Set F1 = Worksheets(ActiveSheet.Name)
  
    ' Récupération des paramètres
    DossierRacine = F1.Cells(1...
Autre code, autre demande :

Cela m’ouvre une autre utilisation possible de ce code, mais pour un résultat différent
Je vois que le code liste tous les dossiers en doublon avec leurs chemins
Pour lister tous mes fichiers, j’utilise un programme annexe qui fait très bien le travail
Mais dont je ne peux pas directement intégrer le résultat dans Excel
Si je pouvais lister les dossiers (Doublons ou Pas) dans une colonne, Comme vous le faite pour les doublons avec ce code
Je n’aurai pas besoin de ce programme annexe
A priori, ce code devrait être même plus simple, j'ai essayer de le faire ces derniers jours, mais sans résultat

Important tous les nom des dossiers doivent comporter au moins le signe « € »
 
Bonsoir à tous,

Je n'ai pas le temps d'étudier les solutions proposées mais je les trouve bien compliquées.

Celle-ci est simple, le code de la feuille du fichier .xlsm :
VB:
Option Compare Text 'la casse est ignorée
Dim fso As Object, chemin$ 'mémorise les variables

Private Sub Worksheet_Change(ByVal Target As Range)
Set Target = Intersect(Target, Range("A12:A" & Rows.Count), Me.UsedRange)
If Target Is Nothing Then Exit Sub
Set fso = CreateObject("Scripting.FileSystemObject")
chemin = ThisWorkbook.Path & "\"
Application.ScreenUpdating = False
Application.EnableEvents = False 'désactive les évènements
For Each Target In Target 'si entrées multiples (copier-coller)
    Target(1, 2).Resize(, Columns.Count - 1).ClearContents 'RAZ
    RechercheRecursive chemin & "Dossier général", Target
Next Target
Me.UsedRange.Offset(, 1).Columns.AutoFit 'ajustement largeurs
Application.EnableEvents = True 'réactive les évènements
Set fso = Nothing
End Sub

Sub RechercheRecursive(NomComplet$, Target As Range)
Dim sf As Object, lig&, col%
For Each sf In fso.GetFolder(NomComplet).SubFolders
    If Mid(sf.Path, InStrRev(sf.Path, "\") + 1) = Target Then
        lig = Target.Row
        col = Cells(lig, Columns.Count).End(xlToLeft).Column + 1
        Cells(lig, col) = Mid(sf.Path, Len(chemin) + 1)
    End If
    RechercheRecursive sf.Path, Target
Next sf
End Sub

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Intersect(Target, [B12].Resize(Rows.Count - 11, Columns.Count - 1), Me.UsedRange) Is Nothing Then Exit Sub
Cancel = True
Shell "explorer.exe """ & ThisWorkbook.Path & "\" & Target & """", vbNormalFocus 'ouvre le dossier
End Sub
Téléchargez le fichier Excel et le dossier "Dossier général" zippés sur le bureau.

Nota : le dossier zippé n'accepte pas les "€" je les ai remplacés par "E" mais vous pourrez restituer les "€" après extraction.

A+
 

Pièces jointes

Bonsoir @patricktoulon

c'est comme cela l'idée ?
@laurent950
  1. passe en statique
  2. met un indice de démarrage
  3. le return opéré qu'a la fin
tu ira encore plus vite
VB:
Option Explicit
Option Compare Text

Sub MainStatic()
    Application.ScreenUpdating = False
    
    Dim F1 As Worksheet
    Dim DossierRacine As String
    Dim DossierCherche As String
    Dim i As Long
    ' Changement
    Dim Resultats As Collection
    
    Set F1 = Worksheets(ActiveSheet.Name)
    
    ' Changement
    ' Maintenant en static dans une fonction (Function) et plus une procédure (Sub)
    ' Création de l'objet UNE SEULE FOIS pour tout le programme (Gain de vitesse)
    ' (Ceci est maintenant géré automatiquement par la fonction statique)
    
    DossierRacine = F1.Cells(1, 1).Value
    DossierCherche = F1.Cells(20, 1).Value
    
    ' Nettoyage de la zone
    F1.Range(F1.Cells(1, 2), F1.Cells(100, 2)).Clear
    
    ' Ancienne version
    ' Lancement de la recherche en passant l'objet Fso
    ' Resultats, Fso inclus dans la procédure.
    ' Call TrouverTousLesDossiers(DossierRacine, DossierCherche, Resultats, Fso)
    
    ' Changement
    ' ---------------------------------------------------------
    ' APPEL DE LA FONCTION OPTIMISÉE (STATIC)
    ' Le 3ème argument "True" est l'indice de démarrage (Initialisation)
    ' ---------------------------------------------------------
    Set Resultats = TrouverTousLesDossiers(DossierRacine, DossierCherche, True)
    
    
    ' Inchangé
    ' --- RESTITUTION (Identique) ---
    ' --- GESTION DES RÉSULTATS AVEC LIENS ---
    
    If Resultats.Count = 0 Then
        F1.Cells(1, 2).Value = "Non trouvé"
        F1.Cells(1, 2).Interior.Color = vbRed
        
    ElseIf Resultats.Count = 1 Then
        F1.Hyperlinks.Add Anchor:=F1.Cells(1, 2), Address:=Resultats(1), TextToDisplay:=Resultats(1)
        F1.Cells(1, 2).Interior.Color = vbGreen
        Shell "explorer.exe " & Chr(34) & Resultats(1) & Chr(34), vbNormalFocus
        
    Else
        F1.Cells(1, 2).Value = "Il y a " & Resultats.Count & " dossiers identiques :"
        F1.Cells(1, 2).Interior.Color = vbYellow
        F1.Cells(1, 2).Font.Bold = True
        
        For i = 1 To Resultats.Count
            F1.Hyperlinks.Add Anchor:=F1.Cells(i + 1, 2), Address:=Resultats(i), TextToDisplay:=Resultats(i)
            F1.Cells(i + 1, 2).Interior.Color = RGB(220, 240, 220)
            
            If i = 1 Then Shell "explorer.exe " & Chr(34) & Resultats(1) & Chr(34), vbNormalFocus
        Next i
    End If
    
    F1.Columns("B").AutoFit
    Application.ScreenUpdating = True
End Sub

' ---------------------------------------------------------
' FONCTION RECURSIVE STATIQUE (ULTRA RAPIDE)
' ---------------------------------------------------------
Function TrouverTousLesDossiers(DossierPath As String, NomRecherche As String, _
                            Optional IsStart As Boolean = False) As Collection
    
    Dim Dossier As Object
    Dim SousDossier As Object
    
    ' 1 - passe en statique (Astuce @Patricktoulon)
    ' 1. VARIABLES STATIQUES : Change pas entre les appels
    Static Fso As Object                ' Créé une seule fois
    Static ListeResultats As Collection ' Remplie petit à petit sans passage de paramètre
    
    ' 2 - met un indice de démarrage (Astuce @Patricktoulon)
    ' 2. INDICE DE DÉMARRAGE : Initialisation seulement au 1er appel
    If IsStart Then
        Set ListeResultats = New Collection
        If Fso Is Nothing Then Set Fso = CreateObject("Scripting.FileSystemObject")
    End If
    
    ' Traitement en cours.
    On Error Resume Next
    Set Dossier = Fso.GetFolder(DossierPath)
    If Err.Number <> 0 Then Exit Function
    On Error GoTo 0
    
    For Each SousDossier In Dossier.SubFolders
        ' Si on trouve, on ajoute à la collection (Rapide, pas de Redim)
        If SousDossier.Name = NomRecherche Then
            ListeResultats.Add SousDossier.Path
        End If
        
        ' On continue l'exploration (Récursivité)
        ' CORRECTION ICI : On rappelle la fonction par son bon nom
        TrouverTousLesDossiers SousDossier.Path, NomRecherche, False
    Next SousDossier
    
    ' 3 - le return opéré qu'a la fin : Passage de la Sub en Fonction (Astuce @Patricktoulon)
    ' 4. RETURN OPÉRÉ QU'À LA FIN (Quand la première call se termine)
    If IsStart Then
        Set TrouverTousLesDossiers = ListeResultats
    End If

End Function
 
ouio c'est a peu pres ça mais ton istart n'est pas tout a fait la bonne astuce
la bonne astuce c'est de se fier a dossierpath (soit c'est un string de dossier soit c'est un object folder )
VB:
Option Explicit
Sub test()
    Dim mesfolder As Collection
    Set mesfolder = TrouverCheminDossier("C:\Users\patricktoulon\Desktop\creatorRibbonX\creatorRibbonX  2025 V 6.0-6.2", "images")
    MsgBox mesfolder.Count
    'faire ce que l'on veut ici avec la collection de path
End Sub

' Fonction fso récursive herzat de ma fonction [DirPileListFso de patricktoulon]
Function TrouverCheminDossier(Dossier, NomRecherche As String) As Collection
    Dim first As Boolean, Lparent As Object, SubFolder As Object, SousDossier As Object
    Static FSO As Object 'Fso est statique
    Static Collect As Collection 'Collect est statique
   
    'lors du premier appel  on injecte un string
    If TypeOf Dossier Is Object  Then
        Set Lparent = Dossier
        first = False
    Else
        'string au premier appel donc on crée les object
        Set FSO = CreateObject("scripting.filesystemobject")
        Debug.Print Dossier
        Set Lparent = FSO.GetFolder(Dossier)
        first = True
        Set Collect = New Collection
    End If
   
    On Error Resume Next 'je laisse tomber les erreurs je ne les traites pas (erreur(70,53,75,etc...)
    Set Dossier = FSO.GetFolder(Lparent.Path)
    If Err.Number <> 0 Then
        Err.Clear
    Else
       
        For Each SousDossier In Dossier.SubFolders
            If SousDossier.Name = NomRecherche Then
                Collect.Add SousDossier.Path
            End If
            TrouverCheminDossier SousDossier, NomRecherche 'recall de la fonction
           
        Next SousDossier
    End If
    On Error GoTo 0
   
    'quand la fonction a fait le tours des instance de la fonction first est donc  true car lui est redimer a chaque tours  et conserver dans le stack memoire des instances de fonction
    'Alors on charge le return
    'Debug.Print Abs(first)juste pour montrer qu au  dernier tour on est revenu a la premiere instance la fonction appelée par  un string
    If first Then Set TrouverCheminDossier = Collect
   
End Function

avec cette methode tu est libérer de toute variable que tu transporte ou variable globale
set macollection=fonction( dossier maitre,nom recherché)
Terminé
Patrick
 
@patricktoulon
Par contre, dans la solution DirPileFolderListDIR, tu pourrais substituer le "redim preserve" du tableau par une collection ou un dictionnaire. Si c'est un dictionnaire, passe directement l'item en une fois dans le tableau à la fin, car "redim preserve" dans une boucle est aussi gourmand en ressources système.
 
non ca c'est que le IA te disent mais en VBA c'est faux
le redim preserve en vba donc progressif et la solution la moins lourde
contrairement au push en JS par exemple
le chatGpt je lui est défoncé cette logique archi fausse il y a quelques temps
c'est au même niveau que la collection en treme de poid (du contenu) un poil plus lent a cause de l'action elle meme de redimer par rapport à la collection
la collection native de vba elle est un poil plus lourde au depart(object oblige)
 
@laurent950
imagine nous jouons a s'envoyer la balle
la balle fait 10 kilos
combien de temps allons nous durer

imagine maintenant que la balle fait 100Grammes
et quelle se remplis de 10G a chaque fois qu on se la lance
combien de temps allons nous durer

c'est exactement le même principe entre FSO et dir et une collection ou dico et un tableau re dimensionné avec préservation
 
Je complète le code de mon post #49 avec celui-ci qui permet de lister (sans doublons) les dossiers en colonne A :
VB:
Option Compare Text 'la casse est ignorée
Dim fso As Object, chemin$, a$(), n& 'mémorise les variables

Sub RemplirColonneA()
If fso Is Nothing Then
    Set fso = CreateObject("Scripting.FileSystemObject")
    chemin = ThisWorkbook.Path & "\"
End If
RemplirRecursive chemin & "Dossier général"
Application.ScreenUpdating = False
With [A12] '1ère cellule de destination
    If n Then
        Application.EnableEvents = False 'désactive les évènements
        .Resize(n) = Application.Transpose(a)
        .Resize(n).RemoveDuplicates 1, Header:=xlNo 'supprime les doublons
        Application.EnableEvents = True 'réactive les évènements
        .Resize(n) = .Resize(n).Value 'lance la macro Worksheet_Change
    End If
    .Offset(n).Resize(Rows.Count - n - .Row + 1).ClearContents 'RAZ en dessous
End With
Set fso = Nothing
Erase a: n = 0
End Sub

Sub RemplirRecursive(NomComplet$)
Dim sf As Object
For Each sf In fso.GetFolder(NomComplet).SubFolders
    ReDim Preserve a(n)
    a(n) = Mid(sf.Path, InStrRev(sf.Path, "\") + 1)
    n = n + 1
    RemplirRecursive sf.Path
Next sf
End Sub
La macro RemplirColonneA est affectée au bouton, le remplissage de la colonne A lance la macro Worksheet_Change.

Je rappelle que les "€" ont été remplacés par des "E", remettez-les dans les noms des dossiers après extraction.

Bonne nuit.
 

Pièces jointes

- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Réponses
3
Affichages
868
Retour