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?
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?).
Vous pouvez utiliser la fonction Dir intégrée ou le FileSystemObject.
Fonction Dir: VBA: Fonction Dir
FileSystemObject: VBA: FileSystemObject - Collection de fichiers
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:
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:
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
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
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
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