Application.GetOpenFileName() question

  • Thread starter Thread starter JimP
  • Start date Start date
J

JimP

To All,

I'm trying to get the results of the GetOpenFileName() to filter all
files in the directory so that only those files that begin with the
letters: "ROSTER" are presented as a choice to Select from.
Currently, my code presents all .xls files in the directory and when
the dialog box pops up, I have to type in the 'FileName' box: ROSTER*
(then tab key) - only then do the filtered results of the dialogue
box match what I'm attempting to do through code ...

Any guidance would be greatly appreciated ...

Dim sDir As String
sDir = ThisWorkbook.Path ' Set path = to directory workbook is
stored in
Dim fnROSTER_MASTER As Variant
Dim strFilter As String: Dim strTitle As Variant
strFilter = "Excel (*.xls),*.xls" ' Another Example of filtered
input
strTitle = "SELECT ROSTER file"
ChDrive sDir
ChDir sDir
' Get the CPC file name
fnROSTER_MASTER = Application.GetOpenFilename(strFilter,
Title:=strTitle)
' Did USER abort/cancel the reguest?
If fnROSTER_MASTER = False Then
Exit Function
End If
 
To the best of my knowledge, as you have discovered, GetOpenFileName does
not support partial name filtering.
 
You can use APIs to do it.

Create a class module and name it clsGetOpenFilename, and then add the code
at the end.

You can use it like so to get the name, you will still have to open it as
with the VBA function

Sub TestFileOpen()
Dim cGOPF As clsGetOpenFilename
Dim aryFiles

Set cGOPF = New clsGetOpenFilename
With cGOPF
.FileName = "*A&P*.xls"
.FileType = "Excel Files (*.xls)"
.MultiFile = "N"
If .SelectFile Then
MsgBox .SelectedFiles(1)
End If
End With
End Sub



Option Explicit


'-----------------------------­------------------------------­--------------
--
' Win32 API Declarations
'-----------------------------­------------------------------­--------------
--
Private Declare Function GetOpenFileName Lib "comdlg32.dll" _
Alias "GetOpenFileNameA" _
(pOpenfilename As OPENFILENAME) As Long


Private Declare Function GetSaveFileName Lib "comdlg32.dll" _
Alias "GetSaveFileNameA" _
(pOpenfilename As OPENFILENAME) As Long


Private Declare Function GetShortPathName Lib "kernel32" _
Alias "GetShortPathNameA" _
(ByVal lpszLongPath As String, _
ByVal lpszShortPath As String, _
ByVal cchBuffer As Long) As Long


Private Type OPENFILENAME
nStructSize As Long
hWndOwner As Long
hInstance As Long
sFilter As String
sCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
sFile As String
nMaxFile As Long
sFileTitle As String
nMaxTitle As Long
sInitialDir As String
sDialogTitle As String
flags As Long
nFileOffset As Integer
nFileExtension As Integer
sDefFileExt As String
nCustData As Long
fnHook As Long
sTemplateName As String
End Type


'-----------------------------­------------------------------­--------------
--
' Private Variables
'-----------------------------­------------------------------­--------------
--
Private OFN As OPENFILENAME


Private sFileType As String 'Type of file narrative
Private sFileName As String 'Filename string to restrict list
Private sReadOnly As String 'Y/N flag
Private sMultiFile As String 'Allow selection of multiple files
Private sTitle As String 'Title in file dialog box


'-----------------------------­------------------------------­--------------
--
' Private Constants
'-----------------------------­------------------------------­--------------
--
Private Const OFN_ALLOWMULTISELECT As Long = &H200
Private Const OFN_CREATEPROMPT As Long = &H2000
Private Const OFN_ENABLEHOOK As Long = &H20
Private Const OFN_ENABLETEMPLATE As Long = &H40
Private Const OFN_ENABLETEMPLATEHANDLE As Long = &H80
Private Const OFN_EXPLORER As Long = &H80000
Private Const OFN_EXTENSIONDIFFERENT As Long = &H400
Private Const OFN_FILEMUSTEXIST As Long = &H1000
Private Const OFN_HIDEREADONLY As Long = &H4
Private Const OFN_LONGNAMES As Long = &H200000
Private Const OFN_NOCHANGEDIR As Long = &H8
Private Const OFN_NODEREFERENCELINKS As Long = &H100000
Private Const OFN_NOLONGNAMES As Long = &H40000
Private Const OFN_NONETWORKBUTTON As Long = &H20000
Private Const OFN_NOREADONLYRETURN As Long = &H8000& '*see comments
Private Const OFN_NOTESTFILECREATE As Long = &H10000
Private Const OFN_NOVALIDATE As Long = &H100
Private Const OFN_OVERWRITEPROMPT As Long = &H2
Private Const OFN_PATHMUSTEXIST As Long = &H800
Private Const OFN_READONLY As Long = &H1
Private Const OFN_SHAREAWARE As Long = &H4000
Private Const OFN_SHAREFALLTHROUGH As Long = 2
Private Const OFN_SHAREWARN As Long = 0
Private Const OFN_SHARENOWARN As Long = 1
Private Const OFN_SHOWHELP As Long = &H10
Private Const OFS_MAXPATHNAME As Long = 260


'OFS_FILE_OPEN_FLAGS and OFS_FILE_SAVE_FLAGS below are mine to save long
'statements; they're not a standard Win32 type.
Private Const OFS_FILE_OPEN_FLAGS = OFN_EXPLORER Or _
OFN_LONGNAMES Or _
OFN_CREATEPROMPT Or _
OFN_NODEREFERENCELINKS


Private Const OFS_FILE_SAVE_FLAGS = OFN_EXPLORER Or _
OFN_LONGNAMES Or _
OFN_OVERWRITEPROMPT Or _
OFN_HIDEREADONLY


'-----------------------------­------------------------------­--
' Class Properties
'-----------------------------­------------------------------­--
Public SelectedFiles As New Collection


Public Property Let FileType(FileType As String)
sFileType = FileType
End Property


Public Property Let FileName(FileName As String)
sFileName = FileName
End Property


Public Property Let MultiFile(MultiFile As String)
sMultiFile = UCase(MultiFile)
End Property


Public Property Let DialogTitle(Title As String)
sTitle = Title
End Property


Public Property Get ReadOnly()
ReadOnly = sReadOnly
End Property


'-----------------------------­------------------------------­--
' Class Methods
'-----------------------------­------------------------------­--
Public Function SelectFile() As Long
'-----------------------------­------------------------------­--
Dim i
Dim sFilters As String
Dim sBuffer As String
Dim sLongname As String
Dim sShortname As String


If ValidInput Then
'create a string of filters for the dialog
sFilters = sFileType & vbNullChar & vbNullChar

With OFN

.nStructSize = Len(OFN) 'Size of the OFN structure
.sFilter = sFilters 'Filters for the dropdown
combo
.nFilterIndex = 1 'Index to the initial filter

'Default filename, plus additional padding for
user's
' final selection(s). Must be double-null
terminated
.sFile = sFileName & Space$(1024) & vbNullChar & vbNullChar

.nMaxFile = Len(.sFile) 'the size of the buffer
'Default if file has no extension
.sDefFileExt = sFileName & vbNullChar & vbNullChar
'Make space for file title if single selection made,
' double-null terminated, and its size
.sFileTitle = vbNullChar & Space$(512) & _
vbNullChar & vbNullChar
.nMaxTitle = Len(OFN.sFileTitle)
'Starting folder, double-null terminated
.sInitialDir = ThisWorkbook.Path & vbNullChar

.sDialogTitle = sTitle 'the dialog title string

'Default open flags and multiselect
.flags = OFS_FILE_OPEN_FLAGS Or _
OFN_NOCHANGEDIR

If sMultiFile = "Y" Then .flags = .flags Or _
OFN_ALLOWMULTISELECT

End With

SelectFile = GetOpenFileName(OFN)
If SelectFile Then
'Remove trailing pair of terminating nulls and
' trim returned file string
sBuffer = Trim$(Left$(OFN.sFile, Len(OFN.sFile) - 2))
'If multiple select, first member is the path,
remaining
' members are the files under that path
Do While Len(sBuffer) > 3
SelectedFiles.Add StripDelimitedItem( _
sBuffer, vbNullChar)
Loop


sReadOnly = Abs((OFN.flags And OFN_READONLY))


End If
End If


End Function


Private Sub Class_Initialize()
sTitle = "GetOpenFileName"
End Sub


Private Sub Class_Terminate()
Set SelectedFiles = Nothing
End Sub


'-----------------------------­------------------------------­------
Private Function ValidInput() As Boolean
'-----------------------------­------------------------------­------
Dim i As Long

ValidInput = True

i = 1
If IsEmpty(sFileName) Then
sFileName = " - a file description must be supplied"
i = i + 1
ValidInput = False
End If

If IsEmpty(sFileType) Then
sFileType = " - a file extension must be supplied"
i = i + 1
ValidInput = False
End If

If sMultiFile <> "Y" And sMultiFile <> "N" Then
sMultiFile = "Multiple files must be Y or N"
i = i + 1
ValidInput = False
End If

End Function


'-----------------------------­------------------------------­------
Private Function StripDelimitedItem(startStrg As String, _
delimiter As String) As String
'-----------------------------­------------------------------­------
'take a string separated by nulls, split off 1 item, and shorten
' the string
' so the next item is ready for removal.
'-----------------------------­------------------------------­------
Dim iPos As Long

iPos = InStr(1, startStrg, delimiter)

If iPos Then
StripDelimitedItem = Mid$(startStrg, 1, iPos)
startStrg = Mid$(startStrg, iPos + 1, Len(startStrg))
End If

End Function


'-----------------------------­------------------------------­------
Private Function TrimNull(item As String) As String
'-----------------------------­------------------------------­------
Dim iPos As Long

iPos = InStr(item, Chr$(0))
If iPos Then
TrimNull = Left$(item, iPos - 1)
Else
TrimNull = item
End If

End Function


--

HTH

RP
(remove nothere from the email address if mailing direct)
 
Bob,

Your code is exactly what I've been looking for with one exception. When I set the .FileName of the "Sub TestFileOpen()" to the following: .FileName = "*lf*", it filters down to the correct file. The file name I want to filter for could change since it is named by a human instead of automation. I'm not fluent in APIs and classes, so how would an additional option to view all files if the specific file is not present be coded (like a contingency plan)?

Thanks

You can use APIs to do it.

Create a class module and name it clsGetOpenFilename, and then add the code
at the end.

You can use it like so to get the name, you will still have to open it as
with the VBA function

Sub TestFileOpen()
Dim cGOPF As clsGetOpenFilename
Dim aryFiles

Set cGOPF = New clsGetOpenFilename
With cGOPF
.FileName = "*A&P*.xls"
.FileType = "Excel Files (*.xls)"
.MultiFile = "N"
If .SelectFile Then
MsgBox .SelectedFiles(1)
End If
End With
End Sub



Option Explicit


'-----------------------------*------------------------------*--------------
--
' Win32 API Declarations
'-----------------------------*------------------------------*--------------
--
Private Declare Function GetOpenFileName Lib "comdlg32.dll" _
Alias "GetOpenFileNameA" _
(pOpenfilename As OPENFILENAME) As Long


Private Declare Function GetSaveFileName Lib "comdlg32.dll" _
Alias "GetSaveFileNameA" _
(pOpenfilename As OPENFILENAME) As Long


Private Declare Function GetShortPathName Lib "kernel32" _
Alias "GetShortPathNameA" _
(ByVal lpszLongPath As String, _
ByVal lpszShortPath As String, _
ByVal cchBuffer As Long) As Long


Private Type OPENFILENAME
nStructSize As Long
hWndOwner As Long
hInstance As Long
sFilter As String
sCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
sFile As String
nMaxFile As Long
sFileTitle As String
nMaxTitle As Long
sInitialDir As String
sDialogTitle As String
flags As Long
nFileOffset As Integer
nFileExtension As Integer
sDefFileExt As String
nCustData As Long
fnHook As Long
sTemplateName As String
End Type


'-----------------------------*------------------------------*--------------
--
' Private Variables
'-----------------------------*------------------------------*--------------
--
Private OFN As OPENFILENAME


Private sFileType As String 'Type of file narrative
Private sFileName As String 'Filename string to restrict list
Private sReadOnly As String 'Y/N flag
Private sMultiFile As String 'Allow selection of multiple files
Private sTitle As String 'Title in file dialog box


'-----------------------------*------------------------------*--------------
--
' Private Constants
'-----------------------------*------------------------------*--------------
--
Private Const OFN_ALLOWMULTISELECT As Long = &H200
Private Const OFN_CREATEPROMPT As Long = &H2000
Private Const OFN_ENABLEHOOK As Long = &H20
Private Const OFN_ENABLETEMPLATE As Long = &H40
Private Const OFN_ENABLETEMPLATEHANDLE As Long = &H80
Private Const OFN_EXPLORER As Long = &H80000
Private Const OFN_EXTENSIONDIFFERENT As Long = &H400
Private Const OFN_FILEMUSTEXIST As Long = &H1000
Private Const OFN_HIDEREADONLY As Long = &H4
Private Const OFN_LONGNAMES As Long = &H200000
Private Const OFN_NOCHANGEDIR As Long = &H8
Private Const OFN_NODEREFERENCELINKS As Long = &H100000
Private Const OFN_NOLONGNAMES As Long = &H40000
Private Const OFN_NONETWORKBUTTON As Long = &H20000
Private Const OFN_NOREADONLYRETURN As Long = &H8000& '*see comments
Private Const OFN_NOTESTFILECREATE As Long = &H10000
Private Const OFN_NOVALIDATE As Long = &H100
Private Const OFN_OVERWRITEPROMPT As Long = &H2
Private Const OFN_PATHMUSTEXIST As Long = &H800
Private Const OFN_READONLY As Long = &H1
Private Const OFN_SHAREAWARE As Long = &H4000
Private Const OFN_SHAREFALLTHROUGH As Long = 2
Private Const OFN_SHAREWARN As Long = 0
Private Const OFN_SHARENOWARN As Long = 1
Private Const OFN_SHOWHELP As Long = &H10
Private Const OFS_MAXPATHNAME As Long = 260


'OFS_FILE_OPEN_FLAGS and OFS_FILE_SAVE_FLAGS below are mine to save long
'statements; they're not a standard Win32 type.
Private Const OFS_FILE_OPEN_FLAGS = OFN_EXPLORER Or _
OFN_LONGNAMES Or _
OFN_CREATEPROMPT Or _
OFN_NODEREFERENCELINKS


Private Const OFS_FILE_SAVE_FLAGS = OFN_EXPLORER Or _
OFN_LONGNAMES Or _
OFN_OVERWRITEPROMPT Or _
OFN_HIDEREADONLY


'-----------------------------*------------------------------*--
' Class Properties
'-----------------------------*------------------------------*--
Public SelectedFiles As New Collection


Public Property Let FileType(FileType As String)
sFileType = FileType
End Property


Public Property Let FileName(FileName As String)
sFileName = FileName
End Property


Public Property Let MultiFile(MultiFile As String)
sMultiFile = UCase(MultiFile)
End Property


Public Property Let DialogTitle(Title As String)
sTitle = Title
End Property


Public Property Get ReadOnly()
ReadOnly = sReadOnly
End Property


'-----------------------------*------------------------------*--
' Class Methods
'-----------------------------*------------------------------*--
Public Function SelectFile() As Long
'-----------------------------*------------------------------*--
Dim i
Dim sFilters As String
Dim sBuffer As String
Dim sLongname As String
Dim sShortname As String


If ValidInput Then
'create a string of filters for the dialog
sFilters = sFileType & vbNullChar & vbNullChar

With OFN

.nStructSize = Len(OFN) 'Size of the OFN structure
.sFilter = sFilters 'Filters for the dropdown
combo
.nFilterIndex = 1 'Index to the initial filter

'Default filename, plus additional padding for
user's
' final selection(s). Must be double-null
terminated
.sFile = sFileName & Space$(1024) & vbNullChar & vbNullChar

.nMaxFile = Len(.sFile) 'the size of the buffer
'Default if file has no extension
.sDefFileExt = sFileName & vbNullChar & vbNullChar
'Make space for file title if single selection made,
' double-null terminated, and its size
.sFileTitle = vbNullChar & Space$(512) & _
vbNullChar & vbNullChar
.nMaxTitle = Len(OFN.sFileTitle)
'Starting folder, double-null terminated
.sInitialDir = ThisWorkbook.Path & vbNullChar

.sDialogTitle = sTitle 'the dialog title string

'Default open flags and multiselect
.flags = OFS_FILE_OPEN_FLAGS Or _
OFN_NOCHANGEDIR

If sMultiFile = "Y" Then .flags = .flags Or _
OFN_ALLOWMULTISELECT

End With

SelectFile = GetOpenFileName(OFN)
If SelectFile Then
'Remove trailing pair of terminating nulls and
' trim returned file string
sBuffer = Trim$(Left$(OFN.sFile, Len(OFN.sFile) - 2))
'If multiple select, first member is the path,
remaining
' members are the files under that path
Do While Len(sBuffer) > 3
SelectedFiles.Add StripDelimitedItem( _
sBuffer, vbNullChar)
Loop


sReadOnly = Abs((OFN.flags And OFN_READONLY))


End If
End If


End Function


Private Sub Class_Initialize()
sTitle = "GetOpenFileName"
End Sub


Private Sub Class_Terminate()
Set SelectedFiles = Nothing
End Sub


'-----------------------------*------------------------------*------
Private Function ValidInput() As Boolean
'-----------------------------*------------------------------*------
Dim i As Long

ValidInput = True

i = 1
If IsEmpty(sFileName) Then
sFileName = " - a file description must be supplied"
i = i + 1
ValidInput = False
End If

If IsEmpty(sFileType) Then
sFileType = " - a file extension must be supplied"
i = i + 1
ValidInput = False
End If

If sMultiFile <> "Y" And sMultiFile <> "N" Then
sMultiFile = "Multiple files must be Y or N"
i = i + 1
ValidInput = False
End If

End Function


'-----------------------------*------------------------------*------
Private Function StripDelimitedItem(startStrg As String, _
delimiter As String) As String
'-----------------------------*------------------------------*------
'take a string separated by nulls, split off 1 item, and shorten
' the string
' so the next item is ready for removal.
'-----------------------------*------------------------------*------
Dim iPos As Long

iPos = InStr(1, startStrg, delimiter)

If iPos Then
StripDelimitedItem = Mid$(startStrg, 1, iPos)
startStrg = Mid$(startStrg, iPos + 1, Len(startStrg))
End If

End Function


'-----------------------------*------------------------------*------
Private Function TrimNull(item As String) As String
'-----------------------------*------------------------------*------
Dim iPos As Long

iPos = InStr(item, Chr$(0))
If iPos Then
TrimNull = Left$(item, iPos - 1)
Else
TrimNull = item
End If

End Function


--

HTH

RP
(remove nothere from the email address if mailing direct)


"JimP" <[email protected]> wrote in message
news:[email protected]...
> To All,
>
> I'm trying to get the results of the GetOpenFileName() to filter all
> files in the directory so that only those files that begin with the
> letters: "ROSTER" are presented as a choice to Select from.
> Currently, my code presents all .xls files in the directory and when
> the dialog box pops up, I have to type in the 'FileName' box: ROSTER*
> (then tab key) - only then do the filtered results of the dialogue
> box match what I'm attempting to do through code ...
>
> Any guidance would be greatly appreciated ...
>
> Dim sDir As String
> sDir = ThisWorkbook.Path ' Set path = to directory workbook is
> stored in
> Dim fnROSTER_MASTER As Variant
> Dim strFilter As String: Dim strTitle As Variant
> strFilter = "Excel (*.xls),*.xls" ' Another Example of filtered
> input
> strTitle = "SELECT ROSTER file"
> ChDrive sDir
> ChDir sDir
> ' Get the CPC file name
> fnROSTER_MASTER = Application.GetOpenFilename(strFilter,
> Title:=strTitle)
> ' Did USER abort/cancel the reguest?
> If fnROSTER_MASTER = False Then
> Exit Function
> End If
>
 
Back
Top