How To Sanitize A Filename

As a part 2 to my post on Validating a Filename to ensure it conforms to Microsoft Windows naming convention, refer to:

I also wanted to demonstrate how we could alternatively sanitize any proposed filename.  So instead of validating, or reporting back issues with the proposed filename, how we could simply eliminate the issues and return a valid filename.


The principle is very similar to the code to perform validation, but instead, we replace the offending characters/terms.

The code thus turns into:

'---------------------------------------------------------------------------------------
' Procedure : Filename_Sanitize
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Sanitize a filename, thus eliminating any non-conforming characters/terms
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: None required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sFileName             : Filename to sanitize (including extension)
' sReplacementCharacter : Character to use to replace illegal characters/terms
'
' Usage:
' ~~~~~~
' ? Filename_Sanitize("VBA Samples and Explanations.docx")
'   Returns -> VBA Samples And Explanations.docx
'
' ? Filename_Sanitize("VBA Samples >>> Explanations.docx")
'   Returns -> VBA Samples ___ Explanations.docx
'
' ? Filename_Sanitize("VBA Samples >>> Explanations.docx", "")
'   Returns -> VBA Samples  Explanations.docx
'
' ? Filename_Sanitize("VBA Samples >>> Explanations.docx", "-")
'   Returns -> VBA Samples - --Explanations.docx
'
' ? Filename_Sanitize("COM3.docx")
'   Returns -> ____.docx
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2024-03-25              Public release
' 2         2024-03-28              Filename ending with '..' or '  '
'---------------------------------------------------------------------------------------
Public Function Filename_Sanitize(sFilename As String, _
                                  Optional sReplacementCharacter As String = "_") As String
    On Error GoTo Error_Handler
    Dim iCounter              As Long
    Dim aChars()              As String
    Dim aNames()              As String
    Dim sFilenameWOExt        As String    'Filename without extension
    Dim sFilenameExt          As String
    Const sIllegalChrs = "<,>,:,"",/,\,|,?,*"
    Const sIllegalNames = "CON,PRN,AUX,NUL,COM0,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8" & _
          ",COM9,COM¹,COM²,COM³,LPT0,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7" & _
          ",LPT8,LPT9,LPT¹,LPT²,LPT³"

    'illegal characters
    aChars = Split(sIllegalChrs, ",")
    For iCounter = 0 To UBound(aChars)
        sFilename = Replace(sFilename, aChars(iCounter), sReplacementCharacter)
    Next iCounter

    'Ascii 0 through 31
    For iCounter = 0 To 31
        sFilename = Replace(sFilename, Chr(iCounter), sReplacementCharacter)
    Next iCounter

    'Illegal names
    If InStr(sFilename, ".") > 0 Then
        sFilenameWOExt = Left(sFilename, InStrRev(sFilename, ".") - 1)
        sFilenameExt = Right(sFilename, Len(sFilename) - InStrRev(sFilename, "."))
    Else
        sFilenameWOExt = sFilename    'No Extension
    End If
    aNames = Split(sIllegalNames, ",")
    For iCounter = 0 To UBound(aNames)
        If sFilenameWOExt = aNames(iCounter) Then
            sFilename = String(Len(sFilenameWOExt), sReplacementCharacter) & _
                        "." & sFilenameExt
        End If
    Next iCounter

    'End with '..' or '  '
    If Right(sFilename, 2) = ".." Then
         sFilename = Left(sFilename, Len(sFilename) - 2) & sReplacementCharacter & "."
    End If
    If Right(sFilename, 2) = "  " Then
         sFilename = Left(sFilename, Len(sFilename) - 2) & sReplacementCharacter & "."
    End If

    Filename_Sanitize = sFilename

Error_Handler_Exit:
    On Error Resume Next
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Source: Filename_Sanitize" & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

Then, we can simply use it by doing:

    Dim sFilename             As String

    sFilename = "VBA Samples and Explanations.docx"
    sFilename = Filename_Sanitize(sFilename)
    Debug.Print sFilename

which would output

VBA Samples and Explanations.docx

Or

    Dim sFilename             As String

    sFilename = "VBA Samples > Explanat|ions.docx"
    sFilename = Filename_Sanitize(sFilename, "")
    Debug.Print sFilename

which in turn outputs

VBA Samples  Explanations.docx

Or

    Dim sFilename             As String

    sFilename = "COM3.docx"
    sFilename = Filename_Sanitize(sFilename, "-")
    Debug.Print sFilename

and the result is

----.docx

Also note that if you which to stop users from using other characters beyond those specifically mentioned by Microsoft in their documentation, all you have to do is add them to the sIllegalChrs declaration in the function.