ThreeWave Creating Nested Directories

This page describes code that you can use to create nested directories with a single line of code.
ShortFadeBar

Introduction

It is not an uncommon need to create a directory structure that is several levels deep. For example, your application may need to create a directory like C:\MyApplication\Settings\Templates\VB. While VBA does have a command named MkDir that creates a directory, it will not create any intermediate directories. Refering the directory above, you would need 4 separate calls to MkDir:

MkDir "C:\MyApplication"
MkDir "C:\MyApplication\Settings"
MkDir "C:\MyApplication\Settings\Templates"
MkDir "C:\MyApplication\Settings\Templates\VB"

This is cumbersome and aesthically displeasing. The Scripting.FileSystemObject, which we will see below, suffers this same limitation. It would be much cleaner to create all of the intermediate directory with one line of code. This page describes a procedure named MakeMultiStepDirectory that does just this.

You can call MakeMultiStepDirectory passing it the entire directory path and it will automatically create all the required intermediate directories:

MakeMultiStepDirectory C:\MyApplication\Settings\Templates\VB

The MakeMultiStepDirectory function can create directories on both the local machine (C:\MyApplication\Settings\Templates\VB), a mapped drive, or a UNC network share (\\BlackCow\MainShare\MyApplication\Settings\Templates\VB). Note that the function cannot create a share; the share must already exist and, of course, you must have permissions to create directories on that share. For example, with the paths above, \\BlackCow\MainShare must already exist and you must have permission on that share to create directories.

The MakeMultiStepDirectory function makes use of the Scripting.FileSystemObject, so your project will need a reference to the Microsoft Scripting Runtime Library. In VBA with your project open, go to the Tools menu, choose References and scroll down until you find Microsoft Scripting Runtime Library. Check the box next to this entry.

Return Values

The MakeMultiStepDirectory function returns values that are listed in an Enum named EMakeDirStatus, which is defined in the downloadable bas module file. This Enum is as follows:

    Public Enum EMakeDirStatus
        ErrSuccess = 0
        ErrRelativePath
        ErrInvalidPathSpecification
        ErrDirectoryCreateError
        ErrSpecIsFileName
        ErrInvalidCharactersInPath
    End Enum

where

  • ErrSuccess indicates the operation was successful.
  • ErrRelativePath indicates that a relative path was passed to the function. You must pass an absolute path (begining with either a drive letter or a UNC share name.
  • ErrInvalidPathSpecification indicates that the path is badly formed.
  • ErrDirectoryCreateError indicates that there was an error creating the directory. Most often, this is a security/permission issue.
  • ErrSpecIsFileName indicates the input parameter was a file name not a folder name.
  • ErrInvalidCharactersInPath indicates that there were invalid characters in the folder name.

The code for MakeMultiStepDirectory is shown below.

download You can download the bas module file with the code on this page.
    Private Declare Function PathIsRelative Lib "Shlwapi" _
        Alias "PathIsRelativeA" (ByVal Path As String) As Long

    Public Enum EMakeDirStatus
        ErrSuccess = 0
        ErrRelativePath
        ErrInvalidPathSpecification
        ErrDirectoryCreateError
        ErrSpecIsFileName
        ErrInvalidCharactersInPath
    End Enum
    Const MAX_PATH = 260
    
    Function MakeMultiStepDirectory(ByVal PathSpec As String) As EMakeDirStatus
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' MakeMultiStepDirectory
    ' This function creates a series of nested directories. The parent of
    ' every directory is create before a subdirectory is created, allowing a
    ' folder path specification of any number of directories (as long as the
    ' total length is less than MAX_PATH.
    '
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    
    Dim FSO As Scripting.FileSystemObject
    Dim DD As Scripting.Drive
    Dim B As Boolean
    Dim Root As String
    Dim DirSpec As String
    Dim N As Long
    Dim M As Long
    Dim S As String
    Dim Directories() As String
        
    Set FSO = New Scripting.FileSystemObject
        
    ' ensure there are no invalid characters in spec.
    On Error Resume Next
    Err.Clear
    S = Dir(PathSpec, vbNormal)
    If Err.Number <> 0 Then
        MakeMultiStepDirectory = ErrInvalidCharactersInPath
        Exit Function
    End If
    On Error GoTo 0
    
    ' ensure we have an absolute path
    B = CBool(PathIsRelative(PathSpec))
    If B = True Then
        MakeMultiStepDirectory = ErrRelativePath
        Exit Function
    End If
    
    ' if the directory already exists, get out with success.
    If FSO.FolderExists(PathSpec) = True Then
        MakeMultiStepDirectory = ErrSuccess
        Exit Function
    End If
    
    ' get rid of trailing slash
    If Right(PathSpec, 1) = "\" Then
        PathSpec = Left(PathSpec, Len(PathSpec) - 1)
    End If
    
    ' ensure we don't have a filename
    N = InStrRev(PathSpec, "\")
    M = InStrRev(PathSpec, ".")
    If (N > 0) And (M > 0) Then
        If M > N Then
            ' period found after last slash
            MakeMultiStepDirectory = ErrSpecIsFileName
            Exit Function
        End If
    End If
    
    If Left(PathSpec, 2) = "\\" Then
        ' UNC -> \\Server\Share\Folder...
        N = InStr(3, PathSpec, "\")
        N = InStr(N + 1, PathSpec, "\")
        Root = Left(PathSpec, N - 1)
        DirSpec = Mid(PathSpec, N + 1)
    Else
        ' Local or mapped -> C:\Folder....
        N = InStr(1, PathSpec, ":", vbBinaryCompare)
        If N = 0 Then
            MakeMultiStepDirectory = ErrInvalidPathSpecification
            Exit Function
        End If
        Root = Left(PathSpec, N)
        DirSpec = Mid(PathSpec, N + 2)
    End If
    Set DD = FSO.GetDrive(Root)
    Directories = Split(DirSpec, "\")
    DirSpec = DD.Path
    For N = LBound(Directories) To UBound(Directories)
        DirSpec = DirSpec & "\" & Directories(N)
        If FSO.FolderExists(DirSpec) = False Then
            On Error Resume Next
            Err.Clear
            FSO.CreateFolder (DirSpec)
            If Err.Number <> 0 Then
                MakeMultiStepDirectory = ErrDirectoryCreateError
                Exit Function
            End If
        End If
    Next N
    MakeMultiStepDirectory = ErrSuccess
    End Function

You can then call this code from your own code as follows:

    Sub AAA()
        Dim Result As EMakeDirStatus
        Result = MakeMultiStepDirectory("C:\One\Two\Three\Four")
        If Result = ErrSuccess Then
            Debug.Print "Success"
        Else
            Debug.Print "Error"
        End If
    End Sub
download You can download the bas module file with the code on this page.
ShortFadeBar
LastUpdate This page last updated: 12-Feb-2010.

-->