web-dev-qa-db-fra.com

Obtenir la liste des fichiers Excel dans un dossier en utilisant VBA

Je dois obtenir les noms de tous les fichiers Excel dans un dossier, puis apporter des modifications à chaque fichier. J'ai obtenu la partie "faire des changements" triée. Est-il possible d’obtenir une liste des .xlsx fichiers dans un dossier, par exemple D:\Personal et le stocker dans un tableau de chaînes.

Je dois ensuite parcourir la liste des fichiers et exécuter une macro sur chacun des fichiers que je pensais pouvoir utiliser à l'aide de:

Filepath = "D:\Personal\"
For Each i in FileArray
    Workbooks.Open(Filepath+i)
Next

J'ai jeté un œil à this , cependant, je n’ai pas pu ouvrir les fichiers car il stockait les noms au format Variant.

En bref, comment utiliser VBA pour obtenir une liste de noms de fichiers Excel dans un dossier spécifique?

18
Buzz Lightyear

Ok, cela pourrait fonctionner pour vous, une fonction qui prend un chemin et renvoie un tableau de noms de fichiers dans le dossier. Vous pouvez utiliser une instruction if pour obtenir uniquement les fichiers Excel lors de la lecture en boucle du tableau.

Function listfiles(ByVal sPath As String)

    Dim vaArray     As Variant
    Dim i           As Integer
    Dim oFile       As Object
    Dim oFSO        As Object
    Dim oFolder     As Object
    Dim oFiles      As Object

    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFolder = oFSO.GetFolder(sPath)
    Set oFiles = oFolder.Files

    If oFiles.Count = 0 Then Exit Function

    ReDim vaArray(1 To oFiles.Count)
    i = 1
    For Each oFile In oFiles
        vaArray(i) = oFile.Name
        i = i + 1
    Next

    listfiles = vaArray

End Function

Ce serait bien si nous pouvions simplement accéder aux fichiers de l'objet files par numéro d'index, mais cela semble rompu dans VBA pour une raison quelconque (bug?).

35
Coder375

Vous pouvez utiliser la fonction Dir intégrée ou le FileSystemObject.

Ils ont chacun leurs forces et leurs faiblesses.

Fonction Dir

La fonction Dir est une méthode intégrée et légère permettant d’obtenir une liste de fichiers. Les avantages de l’utiliser sont:

  • Facile à utiliser
  • Bonne performance (c'est rapide)
  • Support de joker

L'astuce consiste à comprendre la différence entre l'appel avec ou sans paramètre. Voici un exemple très simple à démontrer:

Public Sub ListFilesDir(ByVal sPath As String, Optional ByVal sFilter As String)

    Dim sFile As String

    If Right(sPath, 1) <> "\" Then
        sPath = sPath & "\"
    End If

    If sFilter = "" Then
        sFilter = "*.*"
    End If

    'call with path "initializes" the dir function and returns the first file name
    sFile = Dir(sPath & sFilter)

   'call it again until there are no more files
    Do Until sFile = ""

        Debug.Print sFile

        'subsequent calls without param return next file name
        sFile = Dir

    Loop

End Sub

Si vous modifiez l'un des fichiers de la boucle, vous obtiendrez des résultats imprévisibles. Il est préférable de lire tous les noms dans un tableau de chaînes avant d’effectuer des opérations sur les fichiers. Voici un exemple qui s'appuie sur le précédent. C'est une fonction qui retourne un tableau de chaînes:

Public Function GetFilesDir(ByVal sPath As String, _
    Optional ByVal sFilter As String) As String()

    'dynamic array for names
    Dim aFileNames() As String
    ReDim aFileNames(0)

    Dim sFile As String
    Dim nCounter As Long

    If Right(sPath, 1) <> "\" Then
        sPath = sPath & "\"
    End If

    If sFilter = "" Then
        sFilter = "*.*"
    End If

    'call with path "initializes" the dir function and returns the first file
    sFile = Dir(sPath & sFilter)

    'call it until there is no filename returned
    Do While sFile <> ""

        'store the file name in the array
        aFileNames(nCounter) = sFile

        'subsequent calls without param return next file
        sFile = Dir

        'make sure your array is large enough for another
        nCounter = nCounter + 1
        If nCounter > UBound(aFileNames) Then
            'preserve the values and grow by reasonable amount for performance
            ReDim Preserve aFileNames(UBound(aFileNames) + 255)
        End If

    Loop

    'truncate the array to correct size
    If nCounter < UBound(aFileNames) Then
        ReDim Preserve aFileNames(0 To nCounter - 1)
    End If

    'return the array of file names
    GetFilesDir = aFileNames()

End Function

Objet du système de fichiers

Le File System Object est une bibliothèque pour les opérations IO) qui prend en charge un modèle objet pour la manipulation de fichiers. Avantages de cette approche:

  • Intellisense
  • Modèle d'objet robuste

Vous pouvez ajouter une référence à "Modèle d'objet hôte de script Windows" (ou "Windows Scripting Runtime") et déclarer vos objets comme suit:

Public Sub ListFilesFSO(ByVal sPath As String)

    Dim oFSO As FileSystemObject
    Dim oFolder As Folder
    Dim oFile As File

    Set oFSO = New FileSystemObject
    Set oFolder = oFSO.GetFolder(sPath)
    For Each oFile In oFolder.Files
        Debug.Print oFile.Name
    Next 'oFile

    Set oFile = Nothing
    Set oFolder = Nothing
    Set oFSO = Nothing

End Sub

Si vous ne voulez pas d’intellisense, vous pouvez le faire sans définir de référence:

Public Sub ListFilesFSO(ByVal sPath As String)

    Dim oFSO As Object
    Dim oFolder As Object
    Dim oFile As Object

    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFolder = oFSO.GetFolder(sPath)
    For Each oFile In oFolder.Files
        Debug.Print oFile.Name
    Next 'oFile

    Set oFile = Nothing
    Set oFolder = Nothing
    Set oFSO = Nothing

End Sub
25
Don Jewett
Dim iIndex as Integer
Dim ws As Excel.Worksheet
Dim wb      As Workbook
Dim strPath As String
Dim strFile As String

strPath = "D:\Personal\"
strFile = Dir(strPath & "*.xlsx")

Do While strFile <> ""
    Set wb = Workbooks.Open(Filename:=strPath & strFile)

    For iIndex = 1 To wb.Worksheets.count
        Set ws = wb.Worksheets(iIndex)

        'Do something here.

    Next iIndex

 strFile = Dir 'This moves the value of strFile to the next file.
Loop
5
MatthewD

Si tout ce que vous voulez est le nom du fichier sans extension de fichier

Dim fileNamesCol As New Collection
Dim MyFile As Variant  'Strings and primitive data types aren't allowed with collection

filePath = "c:\file directory" + "\"
MyFile = Dir$(filePath & "*.xlsx")
Do While MyFile <> ""
    fileNamesCol.Add (Replace(MyFile, ".xlsx", ""))
    MyFile = Dir$
Loop

Pour générer une feuille de calcul Excel

Dim myWs As Worksheet: Set myWs = Sheets("SheetNameToDisplayTo")
Dim ic As Integer: ic = 1

For Each MyFile In fileNamesCol
    myWs.Range("A" & ic).Value = fileNamesCol(ic)
    ic = ic + 1
Next MyFile

Principalement basé sur la technique détaillée ici: https://wordmvp.com/FAQs/MacrosVBA/ReadFilesIntoArray.htm

1
gimmegimme

En ce qui concerne la réponse upvoted, cela m'a plu, sauf que si le tableau "listfiles" résultant est utilisé dans une formule matricielle {CSE}, les valeurs de la liste apparaissent toutes dans une ligne horizontale. Pour les faire apparaître dans une colonne verticale, j'ai simplement fait le tableau en deux dimensions comme suit:

ReDim vaArray(1 To oFiles.Count, 0)
i = 1
For Each oFile In oFiles
    vaArray(i, 0) = oFile.Name
    i = i + 1
Next
0
aVIPtoYou