OSFiles
Picks files and folders through the dialog the host offers. On Windows the class opens an Excel FileDialog. On macOS it runs an AppleScript picker. LoadFile, LoadFiles, LoadFolder and LoadFolders each show one dialog and keep what the user chose; File, Files, Folder and Folders answer it back. The four HasValid members say whether the selection points at something that exists on disk.
READING A MULTI SELECTION
HasNextFile and NextFile walk the selected files one at a time, and ResetFilesIterator puts the cursor back to the first one. The folder members work the same way.
THE LAST FOLDER
Each selection stores its folder in the workbook-level name OSFiles_LastFolder, and the next dialog opens on that folder. State bag for OS detection, selections, and cursor positions. Exposed methods Workbook-level Name used to persist the last used folder path.
Version: 1.0 (2026-02-09)
Initialization
Create #
create
Factory returning an initialised interface
Signature:
Public Function Create() As OSFiles
Returns: OSFiles. Ready to use.
Elements
File #
file
Current loaded file path
Signature:
Public Property Get File() As String
Returns: String. The first selected file path.
Files #
files
All loaded file paths from a multi-selection
Signature:
Public Property Get Files() As Variant
Returns: Variant. Zero-based string array of file paths.
Folder #
folder
Current loaded folder path
Signature:
Public Property Get Folder() As String
Returns: String. The first selected folder path.
Folders #
folders
All loaded folder paths from a multi-selection
Signature:
Public Property Get Folders() As Variant
Returns: Variant. Zero-based string array of folder paths.
Selecting
LoadFolder #
load-folder
Show a single-folder picker dialog
Signature:
Public Sub LoadFolder()
LoadFile #
load-file
Show a single-file picker dialog
Signature:
Public Sub LoadFile(ByVal filters As String, _
Optional ByVal customMacFilter As String = vbNullString)
Parameters:
filters: String. File type filters (e.g. "*.xlsx").customMacFilter: String. Optional UTI override for macOS. Defaults to vbNullString.
LoadFiles #
load-files
Show a multi-file picker dialog
Signature:
Public Sub LoadFiles(ByVal filters As String, _
Optional ByVal customMacFilter As String = vbNullString)
Parameters:
filters: String. File type filters.customMacFilter: String. Optional UTI override for macOS. Defaults to vbNullString.
LoadFolders #
load-folders
Show a multi-folder picker dialog
Signature:
Public Sub LoadFolders()
Iteration
ResetFilesIterator #
reset-files-iterator
Reset the file iteration cursor to the beginning
Signature:
Public Sub ResetFilesIterator()
ResetFoldersIterator #
reset-folders-iterator
Reset the folder iteration cursor to the beginning
Signature:
Public Sub ResetFoldersIterator()
HasNextFile #
has-next-file
Check if another file is available in the iterator
Signature:
Public Function HasNextFile() As Boolean
HasNextFolder #
has-next-folder
Check if another folder is available in the iterator
Signature:
Public Function HasNextFolder() As Boolean
NextFile #
next-file
Return the next file path and advance the cursor
Signature:
Public Function NextFile() As String
NextFolder #
next-folder
Return the next folder path and advance the cursor
Signature:
Public Function NextFolder() As String
Validation
HasValidFile #
has-valid-file
Whether the loaded file path is valid
Signature:
Public Function HasValidFile() As Boolean
Returns: Boolean. True when a non-empty file path exists.
HasValidFiles #
has-valid-files
Whether the loaded files array contains entries
Signature:
Public Function HasValidFiles() As Boolean
Returns: Boolean. True when at least one file was selected.
HasValidFolder #
has-valid-folder
Whether the loaded folder path is valid
Signature:
Public Function HasValidFolder() As Boolean
Returns: Boolean. True when a non-empty folder path exists.
HasValidFolders #
has-valid-folders
Whether the loaded folders array contains entries
Signature:
Public Function HasValidFolders() As Boolean
Returns: Boolean. True when at least one folder was selected.
Internal members (not exported)
Initialization
Class_Initialize #
class-initialize
Set default values for file and folder state
Signature:
Private Sub Class_Initialize()
ResetFileState #
reset-file-state
Clear file-related state and reset the iteration cursor
Signature:
Private Sub ResetFileState()
ResetFolderState #
reset-folder-state
Clear folder-related state and reset the iteration cursor
Signature:
Private Sub ResetFolderState()
EmptyStringArray #
empty-string-array
Return an empty variant array
Signature:
Private Function EmptyStringArray() As Variant
Returns: Variant. Empty array.
SelectFoldersOnWindows #
select-folders-on-windows
Show the Windows multi-folder picker
Signature:
Private Function SelectFoldersOnWindows() As Variant
Returns: Variant. Zero-based string array of folder paths.
TryGetArrayBounds #
try-get-array-bounds
Safely probe array bounds
Signature:
Private Function TryGetArrayBounds(ByVal candidate As Variant, _
ByRef lowerBound As Long, _
ByRef upperBound As Long) As Boolean
CountArrayItems #
count-array-items
Count the number of items in a variant array
Signature:
Private Function CountArrayItems(ByVal candidate As Variant) As Long
ToStringArray #
to-string-array
Coerce a variant into a zero-based string array
Signature:
Private Function ToStringArray(ByVal value As Variant) As Variant
CloneStringArray #
clone-string-array
Create a safe copy of a string array
Signature:
Private Function CloneStringArray(ByVal source As Variant) As Variant
HasNextArrayItem #
has-next-array-item
Check whether the cursor is within array bounds
Signature:
Private Function HasNextArrayItem(ByVal items As Variant, ByVal cursor As Long) As Boolean
GetNextArrayItem #
get-next-array-item
Fetch the item at the cursor and advance it
Signature:
Private Function GetNextArrayItem(ByVal items As Variant, _
ByRef cursor As Long) As String
SetFilesSelection #
set-files-selection
Persist file selections and prime the iterator
Signature:
Private Sub SetFilesSelection(ByVal selectedItems As Variant)
SetFoldersSelection #
set-folders-selection
Persist folder selections and prime the iterator
Signature:
Private Sub SetFoldersSelection(ByVal selectedItems As Variant)
FirstStringOrEmpty #
first-string-or-empty
Return the first array entry or an empty string
Signature:
Private Function FirstStringOrEmpty(ByVal source As Variant) As String
NormalizeFolderPath #
normalize-folder-path
Trim trailing separators and clean the folder path
Signature:
Private Function NormalizeFolderPath(ByVal folderPath As String) As String
ExtractFolderFromPath #
extract-folder-from-path
Identify the parent directory from a file path
Signature:
Private Function ExtractFolderFromPath(ByVal filePath As String) As String
RememberFolder #
remember-folder
Cache the folder locally and in the workbook
Signature:
Private Sub RememberFolder(ByVal folderPath As String)
RememberFolderFromFiles #
remember-folder-from-files
Persist the parent directory of the first selected file
Signature:
Private Sub RememberFolderFromFiles(ByVal filesSelection As Variant)
RememberFolderFromFolders #
remember-folder-from-folders
Persist the first folder from a folder selection
Signature:
Private Sub RememberFolderFromFolders(ByVal folderSelection As Variant)
ResolveLastKnownFolder #
resolve-last-known-folder
Resolve the last-used folder from cache or workbook storage
Signature:
Private Function ResolveLastKnownFolder() As String
HasWorkbookContext #
has-workbook-context
Check whether ThisWorkbook is accessible
Signature:
Private Function HasWorkbookContext() As Boolean
ReadLastFolderFromWorkbook #
read-last-folder-from-workbook
Read the last-used folder from a workbook-level Name
Signature:
Private Function ReadLastFolderFromWorkbook() As String
WriteLastFolderToWorkbook #
write-last-folder-to-workbook
Persist the folder path in a hidden workbook Name
Signature:
Private Sub WriteLastFolderToWorkbook(ByVal folderPath As String)
EncodeWorkbookStorageValue #
encode-workbook-storage-value
Convert a folder path into a Name.RefersTo-safe string literal
Signature:
Private Function EncodeWorkbookStorageValue(ByVal folderPath As String) As String
DecodeWorkbookStorageValue #
decode-workbook-storage-value
Undo Name serialization to recover the original folder path
Signature:
Private Function DecodeWorkbookStorageValue(ByVal storedValue As String) As String
WrapAppleScriptString #
wrap-apple-script-string
Escape a string for safe insertion into AppleScript
Signature:
Private Function WrapAppleScriptString(ByVal value As String) As String
WrapAppleScriptAlias #
wrap-apple-script-alias
Build an AppleScript alias literal from a colon path
Signature:
Private Function WrapAppleScriptAlias(ByVal aliasPath As String) As String
BuildAppleScriptList #
build-apple-script-list
Translate a VBA array into an AppleScript list literal
Signature:
Private Function BuildAppleScriptList(ByVal entries As Variant) As String
FilterExtensions #
filter-extensions
Split a filter string into its bare extensions
Signature:
Private Function FilterExtensions(ByVal filters As String) As Variant
Callers write the filter in whichever shape reads well at the call site: ".xlsx", ".xlsb;.xlsx", ".xlsb, .xlsx". They all mean the same thing, so the separator is read as either a semicolon or a comma and the "." is dropped.
This used to be a Select Case over the whole string, which meant a filter had
to be spelled exactly as one of the listed literals or it fell to the Else
branch and answered xlsx alone. clickLoadFileDic asks for ".xlsb;.xlsx"
and the branch it needed was written "*.xlsb, *.xlsx", so loading a setup on
macOS offered xlsx files and hid every .xlsb.
Parameters:
filters: String. The filter string as the caller wrote it.
Returns: Variant. Zero-based array of lower case extensions, without the dot.
UtiForExtension #
uti-for-extension
The macOS uniform type identifier of one Excel extension
Signature:
Private Function UtiForExtension(ByVal extension As String) As String
Parameters:
extension: String. Lower case extension without the dot.
Returns: String. The UTI, or an empty string when it is not one we handle.
BuildWindowsFilter #
build-windows-filter
Rewrite a filter string in the shape Excel's FileDialog documents
Signature:
Private Function BuildWindowsFilter(ByVal filters As String) As String
FileDialogFilters.Add takes its extensions separated by a comma and a space. A caller writing them with a semicolon is saying the same thing, so the string is rebuilt here rather than passed on as typed.
Parameters:
filters: String. The filter string as the caller wrote it.
Returns: String. "*.xlsb, *.xlsx", or the original when nothing could be read.
BuildMacFilterList #
build-mac-filter-list
Construct the UTI list for the AppleScript file picker
Signature:
Private Function BuildMacFilterList(ByVal filters As String, _
ByVal customMacFilter As String) As String
Parameters:
filters: String. The filter string as the caller wrote it.customMacFilter: String. A UTI to use instead, when the caller has one.
Returns: String. An AppleScript list of UTIs.
ParseMacSelectionResult #
parse-mac-selection-result
Split newline-delimited POSIX paths from AppleScript output
Signature:
Private Function ParseMacSelectionResult(ByVal response As String) As Variant
NormalizeFolderSelections #
normalize-folder-selections
Normalize picker results into clean folder paths
Signature:
Private Function NormalizeFolderSelections(ByVal folderSelection As Variant) As Variant
ConvertPosixToColonPath #
convert-posix-to-colon-path
Translate a POSIX path to AppleScript colon-delimited format
Signature:
Private Function ConvertPosixToColonPath(ByVal posixPath As String) As String
GetMacDefaultFolderAlias #
get-mac-default-folder-alias
Resolve the default folder alias for macOS pickers
Signature:
Private Function GetMacDefaultFolderAlias() As String
BuildMacFileSelectionScript #
build-mac-file-selection-script
Compose the AppleScript for file selection on macOS
Signature:
Private Function BuildMacFileSelectionScript(ByVal filters As String, _
ByVal customMacFilter As String, _
ByVal defaultAlias As String, _
ByVal allowMultiple As Boolean) As String
BuildMacFolderSelectionScript #
build-mac-folder-selection-script
Compose the AppleScript for folder selection on macOS
Signature:
Private Function BuildMacFolderSelectionScript(ByVal defaultAlias As String, _
ByVal allowMultiple As Boolean) As String
RunMacFilePicker #
run-mac-file-picker
Execute the AppleScript file picker and return POSIX paths
Signature:
Private Function RunMacFilePicker(ByVal filters As String, _
ByVal customMacFilter As String, _
ByVal allowMultiple As Boolean) As Variant
RunMacFolderPicker #
run-mac-folder-picker
Execute the AppleScript folder picker and return POSIX paths
Signature:
Private Function RunMacFolderPicker(ByVal allowMultiple As Boolean) As Variant
Elements
OS #
os
Current operating system flag
Signature:
Public Property Get OS() As String
Returns: String. "Mac" or "Windows".
OS #
os-set
Override the detected OS flag
Signature:
Public Property Let OS(ByVal currentOS As String)
Parameters:
currentOS: String. "Mac" or "Windows".
File #
file-set
Assign a single file path through the selection pipeline
Signature:
Private Property Let File(ByVal ff As String)
Parameters:
ff: String. The file path.
Folder #
folder-set
Assign a single folder path through the selection pipeline
Signature:
Private Property Let Folder(ByVal ff As String)
Parameters:
ff: String. The folder path.
SelectFolderOnMac #
select-folder-on-mac
Show the macOS single-folder picker
Signature:
Private Function SelectFolderOnMac() As String
SelectFoldersOnMac #
select-folders-on-mac
Show the macOS multi-folder picker
Signature:
Private Function SelectFoldersOnMac() As Variant
SelectFolderOnWindows #
select-folder-on-windows
Show the Windows single-folder picker
Signature:
Private Function SelectFolderOnWindows() As String
SelectFilesOnWindows #
select-files-on-windows
Show the Windows multi-file picker
Signature:
Private Function SelectFilesOnWindows(ByVal filters As String) As Variant
SelectFileOnMac #
select-file-on-mac
Show the macOS single-file picker
Signature:
Private Function SelectFileOnMac(ByVal filters As String, _
Optional ByVal customMacFilter As String = vbNullString) As String
SelectFilesOnMac #
select-files-on-mac
Show the macOS multi-file picker
Signature:
Private Function SelectFilesOnMac(ByVal filters As String, _
Optional ByVal customMacFilter As String = vbNullString) As Variant
SelectFileOnWindows #
select-file-on-windows
Show the Windows single-file picker
Signature:
Private Function SelectFileOnWindows(ByVal filters As String) As String
Test Support
AssignFilesForTesting #
assign-files-for-testing
Inject file selections without showing a dialog
Signature:
Public Sub AssignFilesForTesting(ByVal selections As Variant)
Parameters:
selections: Variant. File paths to assign.TestHook
AssignFoldersForTesting #
assign-folders-for-testing
Inject folder selections without showing a dialog
Signature:
Public Sub AssignFoldersForTesting(ByVal selections As Variant)
Parameters:
selections: Variant. Folder paths to assign.TestHook
Used in (15 file(s))
- ExportButton.cls
- DesignerPreparation.cls
- Linelist.cls
- SetupImport.cls
- EventsDesignerAdvanced.bas
- EventsDesignerCore.bas
- EventsDesignerMulti.bas
- RibbonDev.bas
- FormLogicAdvanced.bas
- FormLogicExportMig.bas
- SetupHelpers.bas
- TestManualOSFiles.bas
- TestOSFiles.bas
- TestHelpersLite.bas
- OBTGrantAccess.bas