Wyszukiwanie podfolderów za pomocą wbudowanej funkcji Dir
Wbudowana funkcja Dir nie dawała sobie rady z pobraniem nazw podfolderów Po wywołaniu funkcji ListSubFolders() korzystającej z funkcji Dir MS Access zgłosił błąd i pokazał tylko 3 znalezione foldery:
Błąd wykonania powodował plik, a właściwie jego nazwa w formacie Unicode Ola作手ma册kota.txt, z którą to funkcja Dir nie dawała sobie rady.
Komenda (polecenie) DIR uruchamiana za pomocą funkcji Shell(...)
Ani lista podfolderów zwracana przez komendę Dir, uzyskana po uruchomieniu w oknie „Immediate” poniższej instrukcji:
?Shell(Environ$("COMSPEC") & " /k Dir C:\MyFiles\* /A:D /B /S",vbMaximizedFocus)
ani lista podfolderów uzyskana po przekierowaniu zwracanego strumienia do pliku tekstowego ~Dir2File.txt nie zawiera prawidłowych nazw podfolderów.
Otrzymany plik z tekstowy o stronie kodowej IBM-852, (po przekonwertowaniu na stronę kodową 1250) zawierał identyczny tekst zwrócony w oknie poleceń.
Lista podfolderów zwracanych przez FileSystemObject (FSO)
Skoro ani funkcja Dir ani komenda Dir nie daje sobie rady z pobraniem nazw podfolderów w folderze roboczym, spróbujemy uzyskać listę podfolderów w folderze roboczym wykorzystując usługę Windows Script Host (WSH) i jej obiekt FileSystemObject, który zapewnia dostęp do systemu plików komputera. FileSystemObject zawiera metody i właściwości pozwalającymi zarządzać dyskami, folderami i plikami. Umożliwia ich tworzenie, usuwanie oraz uzyskiwanie informacji o folderach i plikach.
Obiekt FileSystemObject zawiera poniższe obiekty:
- Obiekt Drive
- zapewnia dostęp do właściwości konkretnego dysku twardego lub udziału sieciowego
- Obiekt File
- Zapewnia dostęp do wszystkich właściwości pliku i kolekcji plików
- Obiekt Folder
- Zapewnia dostęp do wszystkich właściwości folderu i kolekcji folderów
- Obiekt TextStream
- Ułatwia sekwencyjny dostęp do pliku tj. odczyt, zapis i dodawanie tekstu do pliku
oraz metody
BuildPath, CopyFile, CopyFolder, CreateFolder, CreateTextFile, DeleteFile, DeleteFolder, DriveExists, FileExists, FolderExists, GetAbsolutePathName, GetBaseName, GetDrive, GetDriveName, GetExtensionName, GetFile, GetFileVersion, GetFileName, GetFolder, GetParentFolderName, GetSpecialFolder, GetStandardStream, GetTempName, MoveFile, MoveFolder, OpenTextFileObiekt Folder
Wykorzystamy taże obiekt Folder który zawiera poniższe metody
Copy, Delete, Move, CreateTextFileoraz właściwości
Attributes, DateCreated, DateLastAccessed, DateLastModified, Drive, Files, IsRootFolder, Name, ParentFolder, Path, ShortName, ShortPath, Size, SubFolders, TypeAby uzyskać listę podfolderów w folderze roboczym wykorzystamy dwie metody obiektu FileSystemObject
- obiekt.FolderExists(ścieżka)
- która zwraca jest wartość logiczna informującą, czy istnieje katalog określony przez podaną ścieżkę
- obiekt.GetFolder(ścieżka)
- która zwraca egzemplarz obiektu Folder reprezentujący katalog określony przez podaną ścieżkę
oraz metodę obiektu Folder
- obiekt.SubFolders
- zwraca kolekcję podfolderów znajdujących się w określonym folderze, także podfoldery z atrybutami ukryty i systemowy.
- obiekt.Path
- która zwraca ścieżkę do wyszczególnionego obiektu
Poniżej przedstawiam rekurencyjną funkcję fileListSubFoldersFSO(...) As Long wykorzystującą usługę Windows Script Host (WSH) i jej obiekt FileSystemObject w celu znalezione wszystkich podfolderów w folderze roboczym oraz sposób jej wywołania wraz z zapisem uzyskanej listy podfolderów do tabeli i pliku tekstowego.
⊗ Funkcja fileListSubFoldersFSO( _ oFolder As String, _ colSubFoldersRet As Collection) As Long
- Rekurencyjna funkcja fileListSubFoldersFSO (...) wykorzystuje usługę Windows Script Host (WSH) i jej obiekt FileSystemObject w celu znalezione wszystkich podfolderów w folderze roboczym.
- argumenty:
- oFolder
- argument typu Obiekt wskazująca folder, który zostanie przeszukany w celu znalezienia podfolderów,
- colSubFoldersRet
- kolekcja, która przekazywana jest ByRef w kolejnych rekurencyjnych wywołaniach funkcji. W każdym wywołaniu uzapełniana jest ścieżkami znalezionych podfolderów w przekazywanym folderze oFolder
- zwraca:
-
Zwraca liczbę znalezionych podfolderów w folderze roboczym oFolder, a w argumencie ByRef colSubFolders kolekcję, której elementy zawierają pełne ścieżki znalezionych podfolderów ze znakiem "/" (backslash) na końcu ścieżki.
- autor: Zbigniew Bratko
- data: 15.11.2017
Public Function fileListSubFoldersFSO(oFolder As Object, _ colSubFoldersRet As Collection) As Long Dim subFolder As Object ' przeszukaj folder roboczy For Each subFolder In oFolder.SubFolders colSubFoldersRet.Add subFolder.Path & "\" Call fileListSubFoldersFSO(subFolder, colSubFoldersRet) Next fileListSubFoldersFSO = colSubFoldersRet.Count End Function
Poniżej przykładowe wywołanie rekurencyjnej funkcji fileListSubFoldersFSO(...) i zapis zwróconych ścieżek podfolderów z folderu głównego do pliku tekstowego "~SubFoldersFSO.txt" oraz do tabeli "tblSubFoldersFSO" w bieżącej bazie MS Access.
Private Sub btnListFoldersFSO_Click() Dim colSubFolders As Collection Dim oFSO As Object Dim oIniFolder As Object Dim sFolderName As String Dim vFolder As Variant Dim ff As Integer Dim lCountSF As Long Const conFolderPath As String = "C:\MyFiles\" Const conFileOut As String = "C:\MyFiles\~SubFoldersFSO.txt" Dim dbs As DAO.Database Dim rst As DAO.Recordset Const conTblName As String = "tblSubFoldersFSO" Const conFldName As String = "SubFolderNameFSO" Set colSubFolders = New Collection Set oFSO = CreateObject("Scripting.FileSystemObject") ' sprawdź, czy istnieje folder roboczy conFolderPath If Not oFSO.FolderExists(conFolderPath) Then MsgBox "Brak folderu " & conFolderPath & " w podanej lokalizacji!" Set oFSO = Nothing Exit Sub End If Set oIniFolder = oFSO.GetFolder(conFolderPath) ' pobierz wszystkie podfoldery lCountSF = fileListSubFoldersFSO(oIniFolder, colSubFolders) Set oIniFolder = Nothing ' folder roboczy conFolderPath nie zawiera podfolderów If lCountSF = 0 Then MsgBox "Brak podfolderów w folderze roboczym:" & vbNewLine & _ conFolderPath, vbInformation Exit Sub End If ' kolekcja zawiera podfoldery, zapisz poszczególne elementy do pliku ff = FreeFile Open conFileOut For Binary Access Write As #ff For Each vFolder In colSubFolders sFolderName = StrConv(vFolder & vbNewLine, vbUnicode) Put #ff, , sFolderName Next Close #ff ' kolekcja zawiera podfoldery, zapisz poszczególne elementy w tabeli Set dbs = CurrentDb Set rst = dbs.OpenRecordset(conTblName, dbOpenDynaset, dbAppendOnly) For Each vFolder In colSubFolders rst.AddNew rst.Fields(conFldName) = vFolder Debug.Print vFolder rst.Update Next rst.Close Set rst = Nothing Set dbs = Nothing Set colSubFolders = Nothing Set oFSO = Nothing End Sub