-
Notifications
You must be signed in to change notification settings - Fork 12
/
VBALib_FileUtils.bas
183 lines (153 loc) · 5.83 KB
/
VBALib_FileUtils.bas
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
Attribute VB_Name = "VBALib_FileUtils"
' Common VBA Library - FileUtils
' Provides useful functions for working with filenames and paths.
Option Explicit
Private Declare Function GetTempPathA Lib "kernel32" _
(ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
' Determines whether a file with the given name exists.
' @param findFolders: If true, the function will return true if a folder
' with the given name exists.
Public Function FileExists(ByVal testFilename As String, _
Optional findFolders As Boolean = False) As Boolean
' Include read-only files, hidden files, system files.
Dim attrs As Long
attrs = (vbReadOnly Or vbHidden Or vbSystem)
If findFolders Then
attrs = (attrs Or vbDirectory) ' Include folders as well.
End If
'If Dir() returns something, the file exists.
FileExists = False
On Error Resume Next
FileExists = (Dir(TrimTrailingChars(testFilename, "/\"), attrs) <> "")
End Function
' Determines whether a folder with the given name exists.
Public Function FolderExists(folderName As String) As Boolean
On Error Resume Next
FolderExists = ((GetAttr(folderName) And vbDirectory) = vbDirectory)
End Function
' Creates the given directory, including any missing parent folders.
Public Sub MkDirRecursive(folderName As String)
MkDirRecursiveInternal folderName, folderName
End Sub
Private Sub MkDirRecursiveInternal(folderName As String, _
originalFolderName As String)
If folderName = "" Then
' Too many recursive calls to this function (GetDirectoryName will
' eventually return an empty string)
Err.Raise 32000, _
Description:="Failed to create folder: " & originalFolderName
End If
Dim parentFolderName As String
parentFolderName = GetDirectoryName(folderName)
If Not FolderExists(parentFolderName) Then
MkDirRecursiveInternal parentFolderName, originalFolderName
End If
If Not FolderExists(folderName) Then
MkDir folderName
End If
End Sub
' Merges two path components into a single path.
Public Function CombinePaths(p1 As String, p2 As String) As String
CombinePaths = _
TrimTrailingChars(p1, "/\") & "\" & _
TrimLeadingChars(p2, "/\")
End Function
' Fixes slashes within a path:
' - Converts all forward slashes to backslashes
' - Removes multiple consecutive slashes (except for UNC paths)
' - Removes any trailing slashes
Public Function NormalizePath(ByVal p As String) As String
Dim isUNC As Boolean
isUNC = StartsWith(p, "\\")
p = Replace(p, "/", "\")
While InStr(p, "\\") > 0
p = Replace(p, "\\", "\")
Wend
If isUNC Then p = "\" & p
NormalizePath = TrimTrailingChars(p, "\")
End Function
' Returns the folder name of a path (removes the last component
' of the path).
Public Function GetDirectoryName(ByVal p As String) As String
p = NormalizePath(p)
Dim i As Integer
i = InStrRev(p, "\")
If i = 0 Then
GetDirectoryName = ""
Else
GetDirectoryName = Left(p, i - 1)
End If
End Function
' Returns the filename of a path (the last component of the path).
Public Function GetFilename(ByVal p As String) As String
p = NormalizePath(p)
Dim i As Integer
i = InStrRev(p, "\")
GetFilename = Mid(p, i + 1)
End Function
' Returns the extension of a filename (including the dot).
Public Function GetFileExtension(ByVal p As String) As String
Dim i As Integer
i = InStrRev(p, ".")
If i > 0 Then
GetFileExtension = Mid(p, i)
Else
GetFileExtension = ""
End If
End Function
Private Function ListFiles_Internal(filePattern As String, attrs As Long) _
As Variant()
Dim filesList As New VBALib_List
Dim folderName As String
If FolderExists(filePattern) Then
filePattern = NormalizePath(filePattern) & "\"
folderName = filePattern
Else
folderName = GetDirectoryName(filePattern) & "\"
End If
Dim currFilename As String
currFilename = Dir(filePattern, attrs)
While currFilename <> ""
If (attrs And vbDirectory) = vbDirectory Then
If FolderExists(folderName & currFilename) _
And currFilename <> "." And currFilename <> ".." Then
filesList.Add folderName & currFilename
End If
Else
filesList.Add folderName & currFilename
End If
currFilename = Dir
Wend
ListFiles_Internal = filesList.Items
End Function
' Lists all files matching the given pattern.
' @param filePattern: A directory name, or a path with wildcards:
' - C:\Path\to\Folder
' - C:\Path\to\Folder\ExcelFiles.xl*
Public Function ListFiles(filePattern As String) As Variant()
ListFiles = ListFiles_Internal(filePattern, _
vbReadOnly Or vbHidden Or vbSystem)
End Function
' Lists all folders matching the given pattern.
' @param folderPattern: A directory name, or a path with wildcards:
' - C:\Path\to\Folder
' - C:\Path\to\Folder\OtherFolder_*
Public Function ListFolders(folderPattern As String) As Variant()
ListFolders = ListFiles_Internal(folderPattern, _
vbReadOnly Or vbHidden Or vbSystem Or vbDirectory)
End Function
' Returns the path to a folder that can be used to store temporary
' files.
Public Function GetTempPath() As String
Const MAX_PATH = 256
Dim folderName As String
Dim ret As Long
folderName = String(MAX_PATH, 0)
ret = GetTempPathA(MAX_PATH, folderName)
If ret <> 0 Then
GetTempPath = Left(folderName, InStr(folderName, Chr(0)) - 1)
Else
Err.Raise 32000, Description:= _
"Error getting temporary folder."
End If
End Function