Visual Basic FAQ

Pure VB: Retrieve Multiple Filenames from the Common Dialog Control
Posted:   Sunday December 29, 1996
Updated:   Monday December 26, 2011
Applies to:   VB4-32, VB5, VB6
Related:   GetOpenFileName: File Open/Save Common Dialog API - Overview
Using the GetSaveFileName Common Dialog API
Centering the Open & Save Common Dialogs Using Callbacks
Centering the Open & Save Common Dialogs Using Callbacks, Advanced
Hooking the Open & Save Common Dialogs To Manipulate Components

The following demonstrates how to properly extract the filenames returned from a standard VB File Open Common Dialog.

There are two versions of the code, one for VB6 with the Split function, and a more involved method for VB4-32 and VB5, as well as VB6 if desired. Regardless, either method targets situation where the application is displaying the common dialog with both the cdlOFNAllowMultiselect and cdlOFNExplorer constants specified as the Flags component. These flags make a difference not only in the control's appearance on older systems, but also how the data is returned.

Previously, with the old 16-bit VB2/VB3/VB4-16 common dialog control, the dialog the returned string of selected files where each separated by a Chr$(32) (a space). When the operating system did not support spaces in filenames, like the old Win3x, this was an acceptable method.

But older space-reliant legacy parsing routines won't work with in 32-bit operating systems and 32-bit VB when cdlOFNExplorer is specified as in doing so the OS returns the selected file data separated by Chr$(0) (vbNullChar). Attempting to use the 16-bit file parsing code on a Win32 system without cdlOFNExplorer can still return incorrect data if the path name contains spaces.  Therefore, in VB4-32, VB5 and VB6 under 32-bit Windows, always add the cdlOFNExplorer flag.

As an example, assume that the user has selected the files "Demo File1.txt" and "Demo File2.txt", both located in the path "c:\my documents\demos\". Using the code in the routines below, and with the cdlOFNExplorer flag specified, the routine correctly parses the returned common dialog filename string as:

  • returned: c:\my documents\demos¶Demo File1.txt¶Demo File2.txt¶¶ 
  • extracted path: c:\my documents\demos
  • extracted file1: Demo File1.txt
  • extracted file2: Demo File2.txt

(where ¶ represents a chr$(0)).

Without the cdlOFNExplorer flag, because of the long-filenames (and the non-cdlOFNExplorer separator being a space), the routine would return all data as one file as the string, whose elements were separated by a space, would be incorrectly parsed.

 BAS Module Code

 Form Code
Add a Common Control, a command button and two text boxes (Text1, Text2) to a form. Set the Multiline property of Text2 to True, and add the following:

Option Explicit
' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
Private Sub Command1_Click()
  'working variables
   Dim cnt As Integer
   Dim y As Integer
   Dim sFile As String
   Dim startStrg As String
   Dim tmp As String
  'dim an array to hold the files selected
   Dim FileArray() As String
  'set the max buffer large enough to retrieve multiple files
   CommonDialog1.MaxFileSize = 4096
   CommonDialog1.filename = ""
   CommonDialog1.Filter = "All Files|*.*"
   CommonDialog1.Flags = cdlOFNAllowMultiselect Or cdlOFNExplorer
   CommonDialog1.ShowOpen     ' = 1
  'assign the string returned from the
  'common dialog to startStrg for further processing.  
  'Note that two "nulls" are appended to the 
  'end of the string.  This is required by the StripItem 
  'routine below.
   startStrg = CommonDialog1.filename & Chr(0) & Chr(0)
  'Extract each returned filename.
  'If only 1 file was selected, then the string 
  'contains the fully-qualified path to the file.
  'If more than 1 string file was selected, the 
  'string contains the path as the first item, 
  'and the FileArray as the rest of the string,
  'each separated by a space.
   For cnt = 1 To Len(CommonDialog1.filename)
     'extract 1 item from the string
      sFile = StripItem(startStrg, Chr(0))
     'if nothing's there, we're done
      If sFile = "" Then Exit For
        'ReDim the filename array
        'to add the new file. FileArray(0) is either the
        'path (if more than 1 file selected), or the 
        'fully qualified filename (if only 1 file selected).
         ReDim Preserve FileArray(0 To y)
         FileArray(y) = LCase(sFile)
        'increment y by 1 for the next pass
         y = y + 1
     'display the results
      Text1.Text = ""
      Text2.Text = ""
     'starting with 0, and ending with y-1 (because
     'the above will add 1 more 'y' 
     'than there is actual array members)
      For cnt = 0 To y - 1
        'if its the first item, display it in Text1,
        'otherwise build string of files to display in Text2
         If cnt = 0 Then
            Text1.Text = FileArray(cnt)
            tmp = tmp & FileArray(cnt) & vbCrLf
         End If
      Text2.Text = tmp
End Sub

Private Sub Command2_Click()

  'working variables
   Dim cnt As Integer
   Dim tmp As String
  'dim an array to hold the files selected
   Dim sFileArray() As String
  'set the max buffer large enough
  'to retrieve multiple files
   With CommonDialog1
      .MaxFileSize = 4096
      .FileName = ""
      .Filter = "All Files|*.*"
      .Flags = cdlOFNAllowMultiselect Or cdlOFNExplorer
     'test the string for a Chr$(0)
     'character. If present, a multiple
     'selection was made.
      If InStr(.FileName, vbNullChar) Then
        'use Split to create an array
        'of the path and files selected
         sFileArray() = Split(.FileName, vbNullChar)
         For cnt = LBound(sFileArray) To UBound(sFileArray)
            If cnt = 0 Then
              'item 0 is always the path
               Text1.Text = sFileArray(0)
              'the files - add to a buffer
              'and assign later
               tmp = tmp & sFileArray(cnt) & vbCrLf
            End If
        'no null char, so a single selection was made
         Text1.Text = .FileName
      End If
     'assign the buffer
      Text2.Text = tmp
   End With
End Sub

Private Function StripItem(startStrg As String, parser As String) As String
'this takes a string separated by the chr passed in Parser,
'splits off 1 item, and shortens startStrg so that the next
'item is ready for removal.

   Dim cnt As Integer
   Dim item As String
   cnt = 1
      If Mid(startStrg, cnt, 1) = parser Then
         item = Mid(startStrg, 1, cnt - 1)
         startStrg = Mid(startStrg, cnt + 1, Len(startStrg))
         StripItem = item
         Exit Function
      End If
      cnt = cnt + 1

End Function
Save the app & run, click the button and select as many files as you like. The path will be returned in Text1, and the list of selected files into Text2. If you are returning truncated entries filenames, try increasing the common dialog's MaxFileSize property.


PayPal Link
Make payments with PayPal - it's fast, free and secure!


Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy


Hit Counter