Access

  MS Access 2010+  |  Przetwarzanie plików  |   VBA 7.0



• Lista podfolderów w folderze roboczym

Czasami, a może i często potrzebujemy uzyskać listę plików znajdujących się w folderze i jego podfolderach. Dobrze by było, gdybyśmy mogli pobrać pliki z określonymi atrybutami:

atrybutznaczenie
aarchive / archiwalny
hhidden / ukryty
rread-only / tylko do odczytu
ssystem file / plik systemu

Jeszcze lepiej by było gdybyśmy mogli pobrać wielkość pliku i jego typ (rozszerzenie), datę utworzenia, datę ostatniego dostępu oraz datę modyfikacji. A jeszcze lepiej gdybyśmy mogli wybrać pliki pasujące do wzorca wyszukiwania z zastosowaniem wieloznaczników (wildcards) w postaci "?""*". Nie czas i miejsce by rozpisywać się szczegółowo jak stosować wieloznaczniki (wildcards). Małe co nieco znajduje się w Wikipedii: Wieloznacznik, symbol maski, znak globalny, metaznak, symbol wieloznaczny – nazwa symbolu stosowanego w informatyce w procedurach wyszukiwania ciągów znaków w dokumentach tekstowych i w zbiorach informacji o charakterze tekstowym. Wieloznaczniki używane są do konstruowania wzorców wyszukania (tzw. masek), w których symbol wieloznaczny zastępuje jeden lub więcej znaków pisarskich (tj. nie tylko litery i cyfry, ale także inne znaki występujące w tekstach – interpunkcyjne, matematyczne itp.).
Więcej szczegółów można znaleźć w Wikipedii: Wieloznaczniki

Wyszukiwanie podfolderów w folderze roboczym.

W celach testowych utworzyłem przykładowy folder MyFiles, który umieściłem na dysku C:\
Pełna ścieżka dostępu do tego folderu ma postać: "C:\MyFiles\". Folder ten zawiera podfoldery i pliki o przeróżnych (czasami bardzo dziwnych) nazwach i różnych atrybutach. W sumie folder roboczy zawiera 24 pliki znajdujące się w 8 podfolderach.
Pierwszym celem będzie znalezienie tych 8 podfolderów. Jeżeli uda się odczytać wszystkie nazwy 8 podfolderów w folderze roboczym, to następnym etapem będzie znalezienie wszystkich 24 plików.

• Wbudowana funkcja Dir

Najprostszym rozwiązanie jest skorzystanie z wbudowanej funkcji Dir, która zwraca wartość typu String reprezentującą nazwę pliku, katalogu lub folderu, która odpowiada określonemu wzorcowi, atrybutowi pliku albo etykiecie dysku.

Dir[(nazwa_ściezki[, atrybuty])]

Lista podfolderów zwracanych przez funkcję Dir ()

Najprostsza postać procedury zwracającej nazwy podfolderów w folderze roboczym ma postać:

Public Function ListSubFolders()
Dim sDirName As String
Const conFolderName As String = "C:\MyFiles\"

' On Error Resume Next
  sDirName = Dir(conFolderName, vbDirectory)

  ' przeszukuj folder roboczy w poszukiwaniu podfolderów
  Do Until sDirName = ""
    ' jeżeli zwracana ścieżka jest folderem
    If (GetAttr(conFolderName & sDirName) And vbDirectory) = vbDirectory Then

      ' pomiń katalog bieżący "." i nadrzędny ".."
      If StrComp(sDirName, ".", vbBinaryCompare) <> 0 And _
        StrComp(sDirName, "..", vbBinaryCompare) <> 0 Then
        ' pokaż w oknie "Immediate"
        Debug.Print conFolderName & sDirName
      End If
    End If
    ' pobierz następny element (plik lub folder)
    sDirName = Dir()
  Loop
End Function

Niestety. Po wywołaniu funkcji ListSubFolders () Access zgłasza błąd i pokazuje tylko 3 znalezione foldery:

Run-time error 52 Dir. Lista podfolderów

Jeżeli odremujemy instrukcję On Error Resume Next, to uzyskamy nieco bogatszą, ale nieprawidłową listę podfolderów o niewiele mówiących nazwach zawierających znaki ???

Rem On Error Resume Next

Na liście znajduje się pozycja C:\MyFiles\Ola??ma?kota.txt (czwarta od góry). Powodowała ona błąd po uruchomieniu funkcji ListSubFolders () bez instrukcji On Error Resume Next. Faktycznie nie jest folder, ale plik tekstowy o Unicodowej nazwie Ola作手ma册kota.txt, z nazwą którego funkcja Dir nie daje sobie rady. Ostatnia pozycja C:\MyFiles\??????, odnosząca się do folderu niewiele mówi. Folderów o takich zwracanych nazwach, może być wiele w folderze roboczym.

Wniosek jest prosty. Wbudowana funkcja Dir nie daje sobie rady z odczytaniem nazw podfolderów w „moim wydumanym” folderze roboczym.

Komenda (polecenie) DIR uruchamiana za pomocą funkcji Shell(...)

Podstawowe informacje o komendzie Dir możemy uzyskać po uruchomieniu w oknie „Immediate” poniższej instrukcji:

?Shell(Environ$("COMSPEC") & " /k Dir/?", vbMaximizedFocus)
' lub bardziej skrótowo:
?Shell("cmd.exe /k Dir/?", vbMaximizedFocus)

Aby otworzyć okno „Immediate”, należy wcisnąć klawisze Ctrl+G. Można też w edytorze kodu VBA wybrać polecenie „View/Immediate Window”.

Okno Immediate

Liczba 4880 jest identyfikatorem zadania PID zwracanym przez funkcję Shell. Identyfikator ten jednoznacznie określa wykonujący się program.
Po uruchomieniu komendy Dir za pomocą funkcji Shell zostaje otwarte okno z podstawowymi informacjami dotyczącymi komendy Dir.

Okno konsoli

Lista podfolderów zwracanych przez komendę Dir ()

Poznaliśmy „najsubtelniejsze” tajniki komendy Dir, wię możemy spróbować uzyskać listę podfolderów znajdujących się w folderze roboczym. Wystarczy w oknie „Immediate” wpisać poniższą instrukcję i podziwiać wynik:

?Shell(Environ$("COMSPEC") & " /k Dir C:\MyFiles\* /A:D /B /S",vbMaximizedFocus)
Shell
wywołanie funkcji Shell
Environ$
funkcja zwracająca zmienne środowiskowe
"COMSPEC"
zmienna środowiskowa ComSpec (ściżka do interpretera poleceń cmd.exe systemu Windows)
/k
przełącznik polecena cmd. Po wykonaniu polecenia okno interpretera poleceń cmd.exe pozostaje otwarte
Dir
wywołanie funkcji Dir
C:\MyFiles\*
ścieżka do folderu roboczego, wraz z wieloznacznikiem "*"
/A:D
(A:) atrybut D nakazuje wyszukiwanie tylko folderów
/B
nakazuje użycia prostego formatu (bez informacji nagłówka lub podsumowania)
/S
nakazuje wyświetlanie wszystkich plików i folderów w określonym katalogu i wszystkich podkatalogach
vbMaximizedFocus
otwarte okno ma mieć fokus i być zmaksymalizowane

Po uruchomieniu instrukcji wyszukiwania podfolderów w oknie „Immediate” otrzymujemy poniższą listę podfolderów:

Lista podfolderów
Lista znalezionych podfolderów

Na liście tej znajdują się wszystkie podfoldery z folderu roboczego. Niestety, w niektórych przypadkach zwrócone nazwy nie odzwierciedlają faktycznych nazw podfolderów. Także próba przekierowania zwracanego strumienia przez wywołaną instrukcję do pliku tekstowego ~Dir2File.txt nic nie daje.

?Shell(Environ$("COMSPEC") & " /c Dir C:\MyFiles\* /A:D /B /S > C:\MyFiles\~Dir2File.txt")

Otrzymujemy plik z tekstem o stronie kodowej IBM-852,

Lista podfolderów  w pliku
Lista znalezionych podfolderów

którego treść po przekonwertowaniu na stronę kodową 1250 jest identyczna z tekstem zwróconym w oknie poleceń.