People seem to get befuddled about the proper use of VB's Dir() function. A big part of the reason is that it is actually a stateful object that performs two different operations. Another is probably because it does not descend into subdirectories.
The usual approach to handling recursive descent into subdirectories with Dir() is to write a recursive function. Often this means buffering results and returning them as an array, collection, or other data structure full of the file and subfolder names. This can be fairly heavy when you need to traverse a large and deep folder structure.
Here I have taken another approach, and one you can easily drop into your own Projects. It takes advantage of the fact that Dir() is a lightweight wrapper on FindFirstFile(), etc. API calls. Its performance should be such that you will never need to resort to cumbersome API calling code unless you require proper handling of Unicode file names - which most of the rest of VB's native I/O statements don't handle either.
A wrapper Class providing a global predeclared object for using VB 's Dir() intrinsic function more easily.
DirLister handles subdirectory descent without using recursion and provides a mechanism to retrieve files or files and folders with a one by one call.
It can be easier to use than recursive methods and should be much lighter in terms of resources used. While it uses a tree of Collection objects these are populated gently and trimmed back aggressively.
Seldom used, but returns True when a search has been started and not yet finished. While True you cannot start another search because it will interrupt the internal state of VBA.Dir().
Busy As Boolean (read only)
First call Start() passing the SearchPath, FilePattern, and Attributes desired.
Start(ByVal SearchPath As String, _
Optional ByVal Attributes As VbFileAttribute = vbNormal,
Optional ByVal FilePattern As String = "*.*")
The pattern is applied only to file names and not subdirectory names. If Attributes has the vbDirectory bit set then directory names are returned as well as file names.
After Start() you can call Dir() passing a String variable to receive the file or directory name. Dir() returns True until there are no more names to be returned.
Dir(ByRef Path As String) As Boolean
When Dir() returns False (or whenever you abandon a search) you must call Finish() to release the underlying handles and reset for the next new Start() call.
- The Class provides a GLOBAL PREDECLARED INSTANCE and you do not need (or really want) to create additional instances of it. Since VBA.Dir() is stateful only one could be actively in use at a time anyway.
- This Class is dependent upon the Class DirLNode which it uses internally.
- The FilePattern pattern is much richer than using patterns with Dir() calls. You have the full range of VB6 "Like" operator patterns. The pattern operates on the simple name part of retrieved file names and not the entire full path.
- Files and paths with Unicode symbols or blocked by security will be silently skipped.
- Calling Dir() in your own code while a search has been started will destroy the process because it changes the internal state of Dir(). This is true for any use of Dir() and not specific to this Class.
Just add DirLister.cls and the helper Class DirLNode.cls to your Project.
DirLister is provided here as a demo project showing how to use it.