IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macros et VBA Excel Discussion :

[VBA-E03&07]Amelioration fonction de comptage de fichier de type précis


Sujet :

Macros et VBA Excel

  1. #1
    Membre actif
    Profil pro
    chomeur
    Inscrit en
    Août 2006
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : chomeur

    Informations forums :
    Inscription : Août 2006
    Messages : 343
    Points : 246
    Points
    246
    Par défaut [VBA-E03&07]Amelioration fonction de comptage de fichier de type précis
    Bonjour à tous,

    Je suis amené a devoir compter tous les fichiers Excel present dans un dossier et tous ses sous dossiers.
    J'ai trouvé une méthode mais elle ne me convient pas. Je la trouve très longue. Preuve elle met 3.5 secondes pour dénombrer 200 fichiers dans une dizaine de sous repertoire.

    Voici son code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    Public Const stExcelFile As String = "Microsoft Excel Worksheet"
    Function iCompteLeNombreDeFichierExcel(ByRef fsoLeDossierConserne As Folder) As Integer
     
    'Initialisation
    Dim TousMesFichiers As Files, UnFichier As File, UnFolder As Folder
    iCompteLeNombreDeFichierExcel = 0
    Set TousMesFichiers = fsoLeDossierConserne.Files
     
    'compte ceux presents dans le dossier
    For Each UnFichier In TousMesFichiers
      iCompteLeNombreDeFichierExcel = iCompteLeNombreDeFichierExcel - CInt(UnFichier.Type = stExcelFile)
    Next
     
    ' et ceux presents dans les sous fichiers
    For Each UnFolder In fsoLeDossierConserne.SubFolders
      For Each UnFichier In UnFolder.Files
        iCompteLeNombreDeFichierExcel = iCompteLeNombreDeFichierExcel - CInt(UnFichier.Type = stExcelFile)
      Next
    Next
     
    Set UnFichier = Nothing
    Set UnFolder = Nothing
     
    End Function
    Auriez vous une idée pour améliorer ce code ou meme une autre méthode que celle ci?
    Merci d'avance a tous les participants

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    357
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mars 2008
    Messages : 357
    Points : 417
    Points
    417
    Par défaut
    Bonjour,

    je sais pas si c'est plus rapide, à tester

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    With Application.FileSearch
        .LookIn = "c:\my documents"
        .SearchSubFolders = True
        .FileType = msoFileTypeExcelWorkbooks
        MsgBox .Execute
    End With

  3. #3
    Membre actif
    Profil pro
    chomeur
    Inscrit en
    Août 2006
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : chomeur

    Informations forums :
    Inscription : Août 2006
    Messages : 343
    Points : 246
    Points
    246
    Par défaut
    je viens de faire le test.
    Ta méthode est plus rapide que la mienne. Seulement il y a un souci, les deux ne trouvent pas le meme nombre de fichiers.
    J'avais fait plusieurs tests avec ma macros et donc je suis sûr de son résultat.
    D'où peut venir l'écart ?

  4. #4
    Responsable
    Office & Excel


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 124
    Points : 55 919
    Points
    55 919
    Billets dans le blog
    131
    Par défaut
    Cela peut venir du fait que l'un compte tous les fichiers xl* et l'autre tous les fichiers xls...

  5. #5
    Inactif  

    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    4 555
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 4 555
    Points : 5 537
    Points
    5 537
    Par défaut
    Bonjour,

    Ce n'est un secret pour personne : je n'aime pas FSO.

    Le code qui suit pourra paraître fastidieux, mais (quien sabe ? ) il est peut-être (essaye et dis-nous) plus rapide au bout du compte :

    tout en haut de ta page de code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
    Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
    Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
    Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
     
    Private Type FILETIME
      dwLowDateTime As Long
      dwHighDateTime As Long
    End Type
     
    Private Type WIN32_FIND_DATA
      dwFileAttributes As Long
      ftCreationTime As FILETIME
      ftLastAccessTime As FILETIME
      ftLastWriteTime As FILETIME
      nFileSizeHigh As Long
      nFileSizeLow As Long
      dwReserved0 As Long
      dwReserved1 As Long
      cFileName As String * 260
      cAlternate As String * 14
    End Type
     
     
    Function trouvefics(chem As String, flt As String, nbf As Integer, nbd As Integer)
      Dim nomfic As String, nomdir As String, nds() As String, nDir As Integer, i As Integer, xs As Long
      Dim WFD As WIN32_FIND_DATA, ct As Boolean
      If Right(chem, 1) <> "\" Then chem = chem & "\"
      nDir = 0
      ReDim nds(nDir)
      ct = True
      xs = FindFirstFile(chem & "*", WFD)
      If xs <> -1 Then
        Do While ct
          nomdir = couic0(WFD.cFileName)
          If (nomdir <> ".") And (nomdir <> "..") Then
            If GetFileAttributes(chem & nomdir) And &H10 Then
              nds(nDir) = nomdir: nbd = nbd + 1: nDir = nDir + 1: ReDim Preserve nds(nDir)
            End If
          End If
          ct = FindNextFile(xs, WFD)
        Loop
        ct = FindClose(xs)
      End If
      xs = FindFirstFile(chem & flt, WFD)
      ct = True
      If xs <> -1 Then
        While ct
          nomfic = couic0(WFD.cFileName)
          If (nomfic <> ".") And (nomfic <> "..") Then
            trouvefics = trouvefics + (WFD.nFileSizeHigh * &HFFFF) + WFD.nFileSizeLow
            nbf = nbf + 1
          End If
          ct = FindNextFile(xs, WFD)
        Wend
        ct = FindClose(xs)
      End If
      If nDir > 0 Then
        For i = 0 To nDir - 1
          trouvefics = trouvefics + trouvefics(chem & nds(i) & "\", flt, nbf, nbd)
        Next i
      End If
    End Function
    Function couic0(chaine0 As String) As String
      If (InStr(chaine0, Chr(0)) > 0) Then
        chaine0 = Left(chaine0, InStr(chaine0, Chr(0)) - 1)
      End If
      couic0 = chaine0
    End Function
    puis, d'où tu veux (de l'évènement click d'un bouton de commande, par exemple) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     Dim chemin As String, filtre As String, TF As Long, nbfichiers As Integer, nbdossiers As Integer
      chemin = "d:\monoutil\modeles" 'ooco le chemin de ton répertoire
      filtre = "*.txt" 'ici le filtre que tu veux pour tes fichiers
      TF = trouvefics(chemin, filtre, nbfichiers, nbdossiers)
      MsgBox nbfichiers & " fichiers trouvés dans " & nbdossiers & " dossiers"

  6. #6
    Membre actif
    Profil pro
    chomeur
    Inscrit en
    Août 2006
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : chomeur

    Informations forums :
    Inscription : Août 2006
    Messages : 343
    Points : 246
    Points
    246
    Par défaut
    bonjour,
    euuh je l'aurai bien fait ici... seulement c'est un code pour le Bureau. Je le fais dès que j'arrive lundi (si j'ai le temps).

    Mais une chose est sûre je ferais un retour dans la semaine.

    juste une petite question. Pourquoi es tu opposé au file system object ? Personnellement avant j'étais un peu comme toi, et puis j'ai trouvé l'objet confortable... alors j'y suis passé. Candide que je suis!

  7. #7
    Inactif  

    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    4 555
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 4 555
    Points : 5 537
    Points
    5 537
    Par défaut
    Citation Envoyé par EvaristeGaloisBis Voir le message
    juste une petite question. Pourquoi es tu opposé au file system object ? Personnellement avant j'étais un peu comme toi, et puis j'ai trouvé l'objet confortable... alors j'y suis passé. Candide que je suis!
    confortable, certes ...
    Mais également alourdissant, ralentissant et rendant ton appli inutilement dépendante (de FSO)...
    La qualité d'une appli ne se mesure pas au confort du développeur.

    Edit : pour ton information : mon code (que j'ai testé) met (sur ma machine qui tourne à 1,8 et n'est dotée que de très peu de mémoire vive) moins d'une seconde pour un plus grand nombre de fichiers répartis dans un plus grand nombre de dossiers.

  8. #8
    Membre éprouvé
    Avatar de JackOuYA
    Inscrit en
    Juin 2008
    Messages
    1 040
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 1 040
    Points : 1 191
    Points
    1 191
    Par défaut
    Citation Envoyé par ucfoutu Voir le message
    ... rendant ton appli inutilement dépendante ...
    dépendante de quoi ?


    sont pas plus dépendante que les appels aux API windows..!

  9. #9
    Membre actif
    Profil pro
    chomeur
    Inscrit en
    Août 2006
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : chomeur

    Informations forums :
    Inscription : Août 2006
    Messages : 343
    Points : 246
    Points
    246
    Par défaut
    Bonjour à tous,
    Alors pour mettre fin à toutes controverses j'ai fait le test ce matin entre les deux méthodes.
    Une chose m'a fait assez peur c'est qu'aucune des méthodes ne donne le même chiffres !
    Voici les Résultats pour les méthodes API et fso (j'ai juste fait le test pour 2,5,10 ; après la messe était dite) :
    Pour 10 Iterations
    Temps de comptage par appel fso : 3.701171875 et nb 202
    Temps de comptage par appel API : 0.815234375 et nb 318
    Temps de comptage par appel Find : 10.623046875 et nb 303
    Pour 5 Iterations
    Temps de comptage par appel fso : 3.871875 et nb 202
    Temps de comptage par appel API : 0.99453125 et nb 318
    Temps de comptage par appel Find : 9.47265625 et nb 303
    Pour 2 Iterations
    Temps de comptage par appel fso : 4.005859375 et nb 202
    Temps de comptage par appel API : 0.982421875 et nb 318
    Temps de comptage par appel Find : 9.763671875 et nb 303
    Je crois que je vais prendre la méthode sulfureuse des api...
    Merci pour tous ces codes
    (En cas de litige je peux mettre à disposition les codes du petit test)

    euuh juste une nouvelle remarque.
    ucfoutu, peux tu m'expliquer ta fonction trouvefics ? car en la lisant je ne comprends pas toute la logique.

  10. #10
    Inactif  

    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    4 555
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 4 555
    Points : 5 537
    Points
    5 537
    Par défaut
    Salut,

    Trouvefics travaille en récursivité (se rappelle elle même) : sur chaque dossier trouvé ===>> liste des fichiers contenus et incrémentation du compteur.

    On pourrait faire exactement la même chose en utilisant la fonction Dir de VB, toujours en récursivité. Ce serait moins long qu'avec FSO, mais un peu plus lent qu'avec l'utilisation directe des fonctions de l'Api de Windows.

    J'ai oublié de te préciser un point en ce qui concerne ton filtre : tous les "jokers" (*,?,#) sont acceptés.
    ainsi, par exemple :
    filtre = "*.ab?" recherchera et comptera tous les fichiers dont l'extension commence par ab suivi d'une seule lettre
    filtre = "abcd#.xyz" recherchera tous les fichiers dont le nom commence par abcd suivi d'un seul chiffre et dont l'extension est xyz.
    Toutes les combinaisons sont permises.

    Edit 2 :
    je voudrais également te préciser que, si tu le veux, tu peux également (pour une fraction de seconde de plus, avoir la liste de ces fichiers), ainsi :

    tu ajoutes une listbox nommée List1

    passage de trouvefics à modifier ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    If xs <> -1 Then
        While ct
          nomfic = couic0(WFD.cFileName)
          If (nomfic <> ".") And (nomfic <> "..") Then
            trouvefics = trouvefics + (WFD.nFileSizeHigh * &HFFFF) + WFD.nFileSizeLow
             List1.AddItem chem & "\" & nomfic
          End If
          ct = FindNextFile(xs, WFD)
        Wend
        ct = FindClose(xs)
      End If
    Appel à modifier ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Dim chemin As String, filtre As String, TF As Long, nbfichiers As Integer, nbdossiers As Integer
      chemin = "d:\pour visual basic\a etudier" 'ooco le chemin de ton répertoire
      filtre = "*.fr*" 'ici le filtre que tu veux pour tes fichiers
      List1.Visible = False
      List1.Clear
      TF = trouvefics(chemin, filtre, nbfichiers, nbdossiers)
      List1.Visible = True
      MsgBox List1.ListCount

  11. #11
    Membre actif
    Profil pro
    chomeur
    Inscrit en
    Août 2006
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : chomeur

    Informations forums :
    Inscription : Août 2006
    Messages : 343
    Points : 246
    Points
    246
    Par défaut
    merci pour toutes ses précisions.
    Je relirai tout ça a tete reposée car dans le feu de l'action je ne suis pas toujours capable d'analyser les subtilités.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VBA-E]Probleme avec la fonction Range
    Par pec dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 24/04/2006, 11h36
  2. [VBA-E] problème avec la fonction print#
    Par phoon dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 08/03/2006, 09h51
  3. [VBA-E]création feuille en fonction données d'1 col.
    Par Angel79 dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 23/02/2006, 14h16
  4. [VBA-E] probleme avec la fonction countif
    Par adamm dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 18/02/2006, 09h23
  5. [VBA-E] bouton dynamique avec fonction
    Par ogenki dans le forum Macros et VBA Excel
    Réponses: 38
    Dernier message: 06/02/2006, 12h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo