-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDirectoryManager.cls
225 lines (176 loc) · 8.48 KB
/
DirectoryManager.cls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "DirectoryManager"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Version 1.0.2 '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'MIT License '
' '
'Copyright (c) 2022 M. Scott Lassiter '
' '
'Permission is hereby granted, free of charge, to any person obtaining a copy '
'of this software and associated documentation files (the "Software"), to deal '
'in the Software without restriction, including without limitation the rights '
'to use, copy, modify, merge, publish, distribute, sublicense, and/or sell '
'copies of the Software, and to permit persons to whom the Software is '
'furnished to do so, subject to the following conditions: '
' '
'The above copyright notice and this permission notice shall be included in all '
'copies or substantial portions of the Software. '
' '
'THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR '
'IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, '
'FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE '
'AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER '
'LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, '
'OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE '
'SOFTWARE. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Option Explicit
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Class Variables
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim FolderPath As String
Dim FolderName As String
Dim FoundFoldersList As New Collection
Dim FoundFilesList As New Collection
Dim FoundFolders As New Collection
Dim FoundFiles As New Collection
Dim isFile As Boolean
Dim OmittedPrefixValue As String
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Properties
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Property Get Path() As String
Path = FolderPath
End Property
Public Property Let Path(PathName As String)
'This is the entry point to initialize the class. Trying to use any feature before running this script should abort.
FolderPath = PathName
If Not (Exists) Then Exit Property
FolderPath = FormatFilePath(FolderPath)
'Reinitialize if the same DirectoryManager class is set to a new path
Set FoundFoldersList = New Collection
Set FoundFilesList = New Collection
Set FoundFolders = New Collection
Set FoundFiles = New Collection
FindFilesAndFolders
FindSubFilesAndFolders
End Property
Public Property Get Name() As String
If isFile Then
Name = Split(FolderPath, "\")(UBound(Split(FolderPath, "\")))
Else
Name = Split(FolderPath, "\")(UBound(Split(FolderPath, "\")) - 1)
End If
End Property
Public Property Get Folders() As Collection
Set Folders = FoundFolders
End Property
Public Property Get Files() As Collection
Set Files = FoundFiles
End Property
Public Property Get Exists() As Boolean
'Uninitialized instances of the class and folders that do not exist return false
On Error Resume Next
If Len(Dir(FolderPath, vbDirectory)) = 0 Or FolderPath = "" Or Err <> 0 Then 'Gives error 52 if file name is invalid
Exists = False
Else
Exists = True
End If
On Error GoTo 0
End Property
Public Property Let OmittedPrefix(Omit As String)
'If true, the DirectoryManager ignores all files and folders that begin with the specified characters.
' This allows the end user to setup a file structure with folders or files that he or she does not want
' to be included when the DirectoryManager scans a path.
OmittedPrefixValue = Omit
Path = FolderPath 'Reinitialize the DirectoryManager, this time using the new omit prefix
End Property
Public Property Get OmittedPrefix() As String
OmittedPrefix = OmittedPrefixValue
End Property
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Functions and Methods
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Sub FindFilesAndFolders()
'Loops through all files and folders in this path directory and adds them to their respective collections
Dim RefFolders As Variant
Dim newItem As DirectoryManager
RefFolders = Dir(FolderPath, vbDirectory)
Do While RefFolders <> "" And isFile = False
'Ignore the special folders '.' and '..'
If RefFolders <> "." And RefFolders <> ".." Then
If UCase(Left(RefFolders, Len(OmittedPrefixValue))) <> UCase(OmittedPrefixValue) Or OmittedPrefixValue = "" Then 'Ignore the omitted prefixes, if specified
If (GetAttr(FolderPath & RefFolders) And vbDirectory) = vbDirectory Then
FoundFoldersList.Add RefFolders, RefFolders
Else
FoundFilesList.Add RefFolders, RefFolders
End If
End If
End If
RefFolders = Dir 'Required to move to the next file
Loop
End Sub
Private Sub FindSubFilesAndFolders()
'After the list of folders is identified, this function recursively creates a new Folder class for each folder
' and repeats the process.
Dim item As Variant
Dim newFolder As DirectoryManager
Dim originalStatusBarDisplay As Boolean
originalStatusBarDisplay = Application.DisplayStatusBar
Application.DisplayStatusBar = True
For Each item In FoundFoldersList
'For large file/folder counts, Excel appears to freeze. This gives feedback that it's still working.
Application.StatusBar = "Reading from folder '" & item & "'"
DoEvents
Set newFolder = New DirectoryManager
newFolder.OmittedPrefix = OmittedPrefixValue
newFolder.Path = FolderPath & item
InsertCollectionValueAlphabetically FoundFolders, newFolder, newFolder.Name
Next item
For Each item In FoundFilesList
Set newFolder = New DirectoryManager
newFolder.OmittedPrefix = OmittedPrefixValue
newFolder.Path = FolderPath & item
InsertCollectionValueAlphabetically FoundFiles, newFolder, newFolder.Name
Next item
Application.DisplayStatusBar = originalStatusBarDisplay
End Sub
Private Sub InsertCollectionValueAlphabetically(Col As Collection, item As Variant, Key As String)
'Collections do not have a built in sort feature. This loops through each item in the collection,
' and once the new item (key) comes later than the current loop value (Col(i).Name), then it
' immediately exits the loop and adds the Key into that spot.
Dim i As Long
If Col.Count = 0 Then
Col.Add item, Key 'First value gets added without trying to loop through
Exit Sub
End If
For i = 1 To Col.Count
'Convert to lower case to get predictable behavior during ASCII text comparison
If (LCase(Key) < LCase(Col(i).Name)) Then Exit For
Next i
If i = 1 Then
'Trying to add after index 0 results in an error
Col.Add item, Key, 1
Else
Col.Add item, Key, , i - 1
End If
End Sub
Private Function FormatFilePath(InputPath As String) As String
'If a folder, normalize the root directory file path to have a backslash at the end of it.
' Otherwise, it is a file and should be left alone.
FormatFilePath = InputPath
If (GetAttr(InputPath) And vbDirectory) = vbDirectory Then
isFile = False
If Right(InputPath, 1) <> "\" Then FormatFilePath = InputPath & "\"
ElseIf Len(Dir(InputPath, vbReadOnly Or vbHidden Or vbSystem Or vbDirectory)) > 0 Then
isFile = True
End If
End Function