Show file browse for save or open in Visual Basic 6 (VBA)

Edit ArticleEdit Article

Excel VBA macro provides a helper function to browse the name of the file to save Application.GetSaveAsFilename or open Application.GetOpenAsFilename. These functions however only available in Excel VBA macros and is not available in other environments.

This example demonstrates how create a generic functions to browse for save or open file.

Private Declare PtrSafe Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" (pOpenfilename As OPENFILENAME) As Boolean
Private Declare PtrSafe Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Boolean

Private Type OPENFILENAME
  lStructSize As Long
  hwndOwner As LongPtr
  hInstance As LongPtr
  lpstrFilter As String
  lpstrCustomFilter As String
  nMaxCustFilter As Long
  nFilterIndex As Long
  lpstrFile As String
  nMaxFile As Long
  lpstrFileTitle As String
  nMaxFileTitle As Long
  lpstrInitialDir As String
  lpstrTitle As String
  Flags As LongPtr
  nFileOffset As Integer
  nFileExtension As Integer
  lpstrDefExt As String
  lCustData As Long
  lpfnHook As Long
  lpTemplateName As String
End Type

Const FILTER As String = "Text Files (*.txt)|*.txt|PNG Image Files (*.png)|*.png|All Files (*.*)|*.*"

Sub main()

    Dim filePath As String
    filePath = BrowseForFileSave("Select file path to save", FILTER)
    
    If filePath <> "" Then
        Debug.Print "Selected save file path: " & filePath
    Else
        Debug.Print "No save file selected"
    End If
    
    filePath = BrowseForFileOpen("Select file path to open", FILTER)
    
    If filePath <> "" Then
        Debug.Print "Selected open file path: " & filePath
    Else
        Debug.Print "No open file selected"
    End If

End Sub

Function BrowseForFileSave(title As String, filters As String) As String
    BrowseForFileSave = BrowseForFile(title, filters, True)
End Function

Function BrowseForFileOpen(title As String, filters As String) As String
    BrowseForFileOpen = BrowseForFile(title, filters, False)
End Function

Function BrowseForFile(title As String, filters As String, save As Boolean) As String
    
    Dim ofn As OPENFILENAME
    Const FILE_PATH_BUFFER_SIZE As Integer = 260
    
    ofn.lpstrFilter = Replace(filters, "|", Chr(0)) & Chr(0)
    ofn.lpstrTitle = title
    ofn.nMaxFile = FILE_PATH_BUFFER_SIZE
    ofn.nMaxFileTitle = FILE_PATH_BUFFER_SIZE
    ofn.lpstrFile = String(FILE_PATH_BUFFER_SIZE, Chr(0))
    ofn.lStructSize = LenB(ofn)
    
    Dim res As Boolean
    
    If save Then
        res = GetSaveFileName(ofn)
    Else
        res = GetOpenFileName(ofn)
    End If
    
    If res Then
        
        Dim filePath As String
        filePath = Left(ofn.lpstrFile, InStr(ofn.lpstrFile, vbNullChar) - 1)
        
        If save Then
            Dim vFilters As Variant
            vFilters = Split(FILTER, "|")
            Dim ext As String
            ext = vFilters((ofn.nFilterIndex - 1) * 2 + 1)
            ext = Right(ext, Len(ext) - InStrRev(ext, ".") + 1)
            
            If LCase(Right(filePath, Len(ext))) <> LCase(ext) Then
                filePath = filePath & ext
            End If
        End If
        
        BrowseForFile = filePath
        
    Else
        BrowseForFile = ""
    End If
    
End Function

Product of Xarial Product of Xarial