OSFiles
Cross-platform file and folder selection helper. Wraps Windows FileDialog and macOS AppleScript pickers behind a unified API. Supports single and multi-selection for both files and folders, persists the last-used folder across sessions, and provides iterator-style enumeration over multi-selections. 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 #
Factory returning an initialised interface
Signature:
Public Function Create() As IOSFiles
Returns: IOSFiles. Ready to use.
Elements
file #
Current loaded file path
Signature:
Private Property Get File() As String
Returns: String. The first selected file path.
files #
All loaded file paths from a multi-selection
Signature:
Private Property Get Files() As Variant
Returns: Variant. Zero-based string array of file paths.
folder #
Current loaded folder path
Signature:
Private Property Get Folder() As String
Returns: String. The first selected folder path.
folders #
All loaded folder paths from a multi-selection
Signature:
Private Property Get Folders() As Variant
Returns: Variant. Zero-based string array of folder paths.
Selecting
load-folder #
Show a single-folder picker dialog
Signature:
Private Sub LoadFolder()
load-file #
Show a single-file picker dialog
Signature:
Private 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.
load-files #
Show a multi-file picker dialog
Signature:
Private 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.
load-folders #
Show a multi-folder picker dialog
Signature:
Private Sub LoadFolders()
Iteration
reset-files-iterator #
Reset the file iteration cursor to the beginning
Signature:
Private Sub ResetFilesCursor()
reset-folders-iterator #
Reset the folder iteration cursor to the beginning
Signature:
Private Sub ResetFoldersCursor()
has-next-file #
Check if another file is available in the iterator
Signature:
Private Function HasNextFileValue() As Boolean
has-next-folder #
Check if another folder is available in the iterator
Signature:
Private Function HasNextFolderValue() As Boolean
next-file #
Return the next file path and advance the cursor
Signature:
Private Function NextFileValue() As String
next-folder #
Return the next folder path and advance the cursor
Signature:
Private Function NextFolderValue() As String
Validation
has-valid-file #
Whether the loaded file path is valid
Signature:
Private Function HasValidFile() As Boolean
Returns: Boolean. True when a non-empty file path exists.
has-valid-files #
Whether the loaded files array contains entries
Signature:
Private Function HasValidFiles() As Boolean
Returns: Boolean. True when at least one file was selected.
has-valid-folder #
Whether the loaded folder path is valid
Signature:
Private Function HasValidFolder() As Boolean
Returns: Boolean. True when a non-empty folder path exists.
has-valid-folders #
Whether the loaded folders array contains entries
Signature:
Private Function HasValidFolders() As Boolean
Returns: Boolean. True when at least one folder was selected.
Internal members (not exported)
Initialization
class-initialize #
Set default values for file and folder state
Signature:
Private Sub Class_Initialize()
reset-file-state #
Clear file-related state and reset the iteration cursor
Signature:
Private Sub ResetFileState()
reset-folder-state #
Clear folder-related state and reset the iteration cursor
Signature:
Private Sub ResetFolderState()
empty-string-array #
Return an empty variant array
Signature:
Private Function EmptyStringArray() As Variant
Returns: Variant. Empty array.
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.
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
count-array-items #
Count the number of items in a variant array
Signature:
Private Function CountArrayItems(ByVal candidate As Variant) As Long
to-string-array #
Coerce a variant into a zero-based string array
Signature:
Private Function ToStringArray(ByVal value As Variant) As Variant
clone-string-array #
Create a safe copy of a string array
Signature:
Private Function CloneStringArray(ByVal source As Variant) As Variant
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
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
set-files-selection #
Persist file selections and prime the iterator
Signature:
Private Sub SetFilesSelection(ByVal selectedItems As Variant)
set-folders-selection #
Persist folder selections and prime the iterator
Signature:
Private Sub SetFoldersSelection(ByVal selectedItems As Variant)
first-string-or-empty #
Return the first array entry or an empty string
Signature:
Private Function FirstStringOrEmpty(ByVal source As Variant) As String
normalize-folder-path #
Trim trailing separators and clean the folder path
Signature:
Private Function NormalizeFolderPath(ByVal folderPath As String) As String
extract-folder-from-path #
Identify the parent directory from a file path
Signature:
Private Function ExtractFolderFromPath(ByVal filePath As String) As String
remember-folder #
Cache the folder locally and in the workbook
Signature:
Private Sub RememberFolder(ByVal folderPath As String)
remember-folder-from-files #
Persist the parent directory of the first selected file
Signature:
Private Sub RememberFolderFromFiles(ByVal filesSelection As Variant)
remember-folder-from-folders #
Persist the first folder from a folder selection
Signature:
Private Sub RememberFolderFromFolders(ByVal folderSelection As Variant)
resolve-last-known-folder #
Resolve the last-used folder from cache or workbook storage
Signature:
Private Function ResolveLastKnownFolder() As String
has-workbook-context #
Check whether ThisWorkbook is accessible
Signature:
Private Function HasWorkbookContext() As Boolean
read-last-folder-from-workbook #
Read the last-used folder from a workbook-level Name
Signature:
Private Function ReadLastFolderFromWorkbook() As String
write-last-folder-to-workbook #
Persist the folder path in a hidden workbook Name
Signature:
Private Sub WriteLastFolderToWorkbook(ByVal folderPath As String)
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
decode-workbook-storage-value #
Undo Name serialization to recover the original folder path
Signature:
Private Function DecodeWorkbookStorageValue(ByVal storedValue As String) As String
wrap-apple-script-string #
Escape a string for safe insertion into AppleScript
Signature:
Private Function WrapAppleScriptString(ByVal value As String) As String
wrap-apple-script-alias #
Build an AppleScript alias literal from a colon path
Signature:
Private Function WrapAppleScriptAlias(ByVal aliasPath As String) As String
build-apple-script-list #
Translate a VBA array into an AppleScript list literal
Signature:
Private Function BuildAppleScriptList(ByVal entries As Variant) As String
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
parse-mac-selection-result #
Split newline-delimited POSIX paths from AppleScript output
Signature:
Private Function ParseMacSelectionResult(ByVal response As String) As Variant
normalize-folder-selections #
Normalize picker results into clean folder paths
Signature:
Private Function NormalizeFolderSelections(ByVal folderSelection As Variant) As Variant
convert-posix-to-colon-path #
Translate a POSIX path to AppleScript colon-delimited format
Signature:
Private Function ConvertPosixToColonPath(ByVal posixPath As String) As String
get-mac-default-folder-alias #
Resolve the default folder alias for macOS pickers
Signature:
Private Function GetMacDefaultFolderAlias() As String
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
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
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
run-mac-folder-picker #
Execute the AppleScript folder picker and return POSIX paths
Signature:
Private Function RunMacFolderPicker(ByVal allowMultiple As Boolean) As Variant
Elements
self #
Self-reference as IOSFiles
Signature:
Public Property Get Self() As IOSFiles
Returns: IOSFiles. Self-reference.
os #
Current operating system flag
Signature:
Public Property Get OS() As String
Returns: String. "Mac" or "Windows".
os-set #
Override the detected OS flag
Signature:
Public Property Let OS(ByVal currentOS As String)
Parameters:
currentOS: String. "Mac" or "Windows".
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-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.
select-folder-on-mac #
Show the macOS single-folder picker
Signature:
Private Function SelectFolderOnMac() As String
select-folders-on-mac #
Show the macOS multi-folder picker
Signature:
Private Function SelectFoldersOnMac() As Variant
select-folder-on-windows #
Show the Windows single-folder picker
Signature:
Private Function SelectFolderOnWindows() As String
select-files-on-windows #
Show the Windows multi-file picker
Signature:
Private Function SelectFilesOnWindows(ByVal filters As String) As Variant
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
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
select-file-on-windows #
Show the Windows single-file picker
Signature:
Private Function SelectFileOnWindows(ByVal filters As String) As String
Test Support
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
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 (17 file(s))
- ExportButton.cls
- DesignerPreparation.cls
- IOSFiles.cls
- OSFiles.cls
- Linelist.cls
- SetupImportService.cls
- DesignerMain.bas
- EventsDesignerAdvanced.bas
- EventsDesignerCore.bas
- EventsDesignerMulti.bas
- RibbonDev.bas
- FormLogicAdvanced.bas
- FormLogicExportMig.bas
- SetupHelpers.bas
- Exports.bas
- TestManualOSFiles.bas
- TestOSFiles.bas