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 #

create

Factory returning an initialised interface

Signature:

Public Function Create() As IOSFiles

Returns: IOSFiles. Ready to use.


Elements

File #

file

Current loaded file path

Signature:

Private Property Get File() As String

Returns: String. The first selected file path.


Files #

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 #

folder

Current loaded folder path

Signature:

Private Property Get Folder() As String

Returns: String. The first selected folder path.


Folders #

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

LoadFolder #

load-folder

Show a single-folder picker dialog

Signature:

Private Sub LoadFolder()

LoadFile #

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.

LoadFiles #

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.

LoadFolders #

load-folders

Show a multi-folder picker dialog

Signature:

Private Sub LoadFolders()

Iteration

ResetFilesCursor #

reset-files-iterator

Reset the file iteration cursor to the beginning

Signature:

Private Sub ResetFilesCursor()

ResetFoldersCursor #

reset-folders-iterator

Reset the folder iteration cursor to the beginning

Signature:

Private Sub ResetFoldersCursor()

HasNextFileValue #

has-next-file

Check if another file is available in the iterator

Signature:

Private Function HasNextFileValue() As Boolean

HasNextFolderValue #

has-next-folder

Check if another folder is available in the iterator

Signature:

Private Function HasNextFolderValue() As Boolean

NextFileValue #

next-file

Return the next file path and advance the cursor

Signature:

Private Function NextFileValue() As String

NextFolderValue #

next-folder

Return the next folder path and advance the cursor

Signature:

Private Function NextFolderValue() As String

Validation

HasValidFile #

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.


HasValidFiles #

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.


HasValidFolder #

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.


HasValidFolders #

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 #

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

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

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

Self #

self

Self-reference as IOSFiles

Signature:

Public Property Get Self() As IOSFiles

Returns: IOSFiles. Self-reference.


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:


File #

file-set

Assign a single file path through the selection pipeline

Signature:

Private Property Let File(ByVal ff As String)

Parameters:


Folder #

folder-set

Assign a single folder path through the selection pipeline

Signature:

Private Property Let Folder(ByVal ff As String)

Parameters:


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:


AssignFoldersForTesting #

assign-folders-for-testing

Inject folder selections without showing a dialog

Signature:

Public Sub AssignFoldersForTesting(ByVal selections As Variant)

Parameters:


Used in (17 file(s))