Open File Dialog / Folder Browser Dialog

jal

Registered User.
Local time
Today, 05:05
Joined
Mar 30, 2007
Messages
1,709
I can add a reference to Microsoft Office 12.0 Object Library.

However, is this DLL associated with Office 2003? Or is it Office 2007?

(I used to have the trial version of Office 2007 - now I only have 2003).

Without this reference, the code doesn't work as well. That is to say, I can probably refer to:

Application.FileDialog(1)

But I can't do the following (until I add the reference):


Dim dlg as Office.FileDialog
Set dlg = Application.FileDialog(msoFileDialogFilePicker)

However, as I am not licensed for 2007, I will add this reference only if it is associated with Office 2003.


Anyone know?
 

jal

Registered User.
Local time
Today, 05:05
Joined
Mar 30, 2007
Messages
1,709
Not sure what method you are referencing, but the most common and easiest to use are:

API: BrowseFolder Dialog
API: Call the standard Windows File Open/Save dialog box

Well, actually, the Office.FileDialog is a bit less code and easier to understand (and it also serves as a FolderBrowserDialog). Your statement does, however, confirm my suspicion that this feature isn't well known (because most people have grown so accustomed to using the API). So I'll provide some sample code here.

In trying to answer my own question, by the way, I'm guessing that office 2007 may have irrecoverably replaced my older version of the DLL (probably MSO.DLL). I just found out, however, that the Office.FileDialog was licensed at least to Office 2002, if not earlier, so I am licensed for it.
Anyway, here's some sample code that I recently added to my notebook.


WARNING: THIS IS NOT ZERO-INDEXED. IT IS 1-INDEXED. Note: if the user cancels the dialog, it does not throw a runtime error.

Dim dlg As Office.FileDialog, path As String
Set dlg = Application.FileDialog(msoFileDialogFilePicker)
dlg.Filters.Clear
dlg.Filters.Add "Excel Files", "*.xls"
'if there are multiple filters, set index to 0
dlg.FilterIndex = 0
dlg.Show
If dlg.SelectedItems.Count = 1 Then
path = dlg.SelectedItems(1)
MsgBox path
Else
MsgBox ("No file selected.")
End If

Set the filter index to zero because otherwise it might not show the first filter on top - it might be second, and thus available only through the drop down menu, like this

All Files (*.*)
Excel Files (*.XLS) <------ shown only in drop down menu

Not good. So I decided to add code that accepts a standard .Net-style filter string and sets the filter index to 0

Private Sub FilterTheFileDialog(dlg As Office.FileDialog, strFilter As String)
dlg.Filters.Clear
Dim words() As String, i As Long
words = Split(strFilter, "|")
For i = 0 To UBound(words) - 1 Step 2
dlg.Filters.Add words(i), words(i + 1)
Next i
dlg.FilterIndex = 0
End Sub

And you call it like this (just add a vertical bar between each standard entry).

Set dlg = Application.FileDialog(msoFileDialogFilePicker)
FilterTheFileDialog dlg, "Excel Files|*.xls|All Files|*.*"
dlg.Show

Another issue is that the SaveAs dialog doesn't accept a filter string. I'm not happy about that.
 
Last edited:

jal

Registered User.
Local time
Today, 05:05
Joined
Mar 30, 2007
Messages
1,709
I was thinking that the OpenFileDialog (which DOES accept a filter string) could also be used as a SaveFileDialog (but now it seems silly of me to suppose so).

I guess in this case, if I really needed a filter string, I might have to fall back on the API.
 

jwhite

Software Developer
Local time
Today, 08:05
Joined
Sep 24, 2006
Messages
141
IMO, the API is better as it does not require Office to be installed (from what I see above). Every now and then, I run across a PC without Office.
 

jal

Registered User.
Local time
Today, 05:05
Joined
Mar 30, 2007
Messages
1,709
IMO, the API is better as it does not require Office to be installed (from what I see above). Every now and then, I run across a PC without Office.

Interesting. I had assumed that, as long as one office app (such as Access) was installed, the MSO.DLL (or whatever DLL is the Office library) would be present as well. I suppose I was wrong. Wouldn't be the first time. :)
 

sailinxtc

Registered User.
Local time
Today, 07:05
Joined
Apr 27, 2008
Messages
34
I have been reading alot about this and have come to the conclusion based on some of the discussions I need to use the API method and module.

I basically want to use a button to browse to a location and find a file and then be able to save that file to another location.

I was able to use the button to select the file and then save the file to another location, but it really isn't happening.

I would assume it is not being copied or saved because I am missing the function to store it tempory in between the open and save function.

I am steering towards the API because I would like to package this in a runtime and not all users may have Office installed. Also wondered about Vista compatibility also.

I very new to the VB end of things.... any help or examples would be great.

Code used from example on forum:

Dim strFilter As String
Dim myStrFilter As String
Dim strInputFileName As String
Dim strSaveFileName As String
strFilter = ahtAddFilterItem(strFilter, "Bitmap Files (*.bmp)", "*.bmp")
strInputFileName = ahtCommonFileOpenSave( _
Filter:=strFilter, OpenFile:=True, _
DialogTitle:="Select GPS Bitmap file to Link to Log ID...", _
Flags:=ahtOFN_HIDEREADONLY)
strFilter = ahtAddFilterItem(myStrFilter, "Bitmap Files (*.bmp)", "*.bmp")
strSaveFileName = ahtCommonFileOpenSave( _
OpenFile:=False, _
Filter:=strFilter, _
Flags:=ahtOFN_OVERWRITEPROMPT Or ahtOFN_READONLY



Module code from example on Forum:

'***************** Code Start **************
' This code was originally written by Ken Getz.
' It is not to be altered or distributed, 'except as part of an application.
' You are free to use it in any application,
' provided the copyright notice is left unchanged.
'
' Code originally courtesy of:
' Microsoft Access 95 How-To
' Ken Getz and Paul Litwin
' Waite Group Press, 1996
' Revised to support multiple files:
' 28 December 2007
Type tagOPENFILENAME
lStructSize As Long
hwndOwner As Long
hInstance As Long
strFilter As String
strCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
strFile As String
nMaxFile As Long
strFileTitle As String
nMaxFileTitle As Long
strInitialDir As String
strTitle As String
Flags As Long
nFileOffset As Integer
nFileExtension As Integer
strDefExt As String
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type
Declare Function aht_apiGetOpenFileName Lib "comdlg32.dll" _
Alias "GetOpenFileNameA" (OFN As tagOPENFILENAME) As Boolean
Declare Function aht_apiGetSaveFileName Lib "comdlg32.dll" _
Alias "GetSaveFileNameA" (OFN As tagOPENFILENAME) As Boolean
Declare Function CommDlgExtendedError Lib "comdlg32.dll" () As Long
Global Const ahtOFN_READONLY = &H1
Global Const ahtOFN_OVERWRITEPROMPT = &H2
Global Const ahtOFN_HIDEREADONLY = &H4
Global Const ahtOFN_NOCHANGEDIR = &H8
Global Const ahtOFN_SHOWHELP = &H10
' You won't use these.
'Global Const ahtOFN_ENABLEHOOK = &H20
'Global Const ahtOFN_ENABLETEMPLATE = &H40
'Global Const ahtOFN_ENABLETEMPLATEHANDLE = &H80
Global Const ahtOFN_NOVALIDATE = &H100
Global Const ahtOFN_ALLOWMULTISELECT = &H200
Global Const ahtOFN_EXTENSIONDIFFERENT = &H400
Global Const ahtOFN_PATHMUSTEXIST = &H800
Global Const ahtOFN_FILEMUSTEXIST = &H1000
Global Const ahtOFN_CREATEPROMPT = &H2000
Global Const ahtOFN_SHAREAWARE = &H4000
Global Const ahtOFN_NOREADONLYRETURN = &H8000
Global Const ahtOFN_NOTESTFILECREATE = &H10000
Global Const ahtOFN_NONETWORKBUTTON = &H20000
Global Const ahtOFN_NOLONGNAMES = &H40000
' New for Windows 95
Global Const ahtOFN_EXPLORER = &H80000
Global Const ahtOFN_NODEREFERENCELINKS = &H100000
Global Const ahtOFN_LONGNAMES = &H200000
Function TestIt()
Dim strFilter As String
Dim lngFlags As Long
strFilter = ahtAddFilterItem(strFilter, "Access Files (*.mda, *.mdb)", _
"*.MDA;*.MDB")
strFilter = ahtAddFilterItem(strFilter, "dBASE Files (*.dbf)", "*.DBF")
strFilter = ahtAddFilterItem(strFilter, "Text Files (*.txt)", "*.TXT")
strFilter = ahtAddFilterItem(strFilter, "All Files (*.*)", "*.*")
' Uncomment this line to try the example
' allowing multiple file names:
' lngFlags = ahtOFN_ALLOWMULTISELECT Or ahtOFN_EXPLORER
Dim result As Variant
result = ahtCommonFileOpenSave(InitialDir:="C:\", _
Filter:=strFilter, FilterIndex:=3, Flags:=lngFlags, _
DialogTitle:="Hello! Open Me!")
If lngFlags And ahtOFN_ALLOWMULTISELECT Then
If IsArray(result) Then
Dim i As Integer
For i = 0 To UBound(result)
MsgBox result(i)
Next i
Else
MsgBox result
End If
Else
MsgBox result
End If
' Since you passed in a variable for lngFlags,
' the function places the output flags value in the variable.
Debug.Print Hex(lngFlags)
End Function
Function GetOpenFile(Optional varDirectory As Variant, _
Optional varTitleForDialog As Variant) As Variant
' Here's an example that gets an Access database name.
Dim strFilter As String
Dim lngFlags As Long
Dim varFileName As Variant
' Specify that the chosen file must already exist,
' don't change directories when you're done
' Also, don't bother displaying
' the read-only box. It'll only confuse people.
lngFlags = ahtOFN_FILEMUSTEXIST Or _
ahtOFN_HIDEREADONLY Or ahtOFN_NOCHANGEDIR
If IsMissing(varDirectory) Then
varDirectory = ""
End If
If IsMissing(varTitleForDialog) Then
varTitleForDialog = ""
End If
' Define the filter string and allocate space in the "c"
' string Duplicate this line with changes as necessary for
' more file templates.
strFilter = ahtAddFilterItem(strFilter, _
"Access (*.mdb)", "*.MDB;*.MDA")
' Now actually call to get the file name.
varFileName = ahtCommonFileOpenSave( _
OpenFile:=True, _
InitialDir:=varDirectory, _
Filter:=strFilter, _
Flags:=lngFlags, _
DialogTitle:=varTitleForDialog)
If Not IsNull(varFileName) Then
varFileName = TrimNull(varFileName)
End If
GetOpenFile = varFileName
End Function
Function ahtCommonFileOpenSave( _
Optional ByRef Flags As Variant, _
Optional ByVal InitialDir As Variant, _
Optional ByVal Filter As Variant, _
Optional ByVal FilterIndex As Variant, _
Optional ByVal DefaultExt As Variant, _
Optional ByVal FileName As Variant, _
Optional ByVal DialogTitle As Variant, _
Optional ByVal hwnd As Variant, _
Optional ByVal OpenFile As Variant) As Variant
' This is the entry point you'll use to call the common
' file open/save dialog. The parameters are listed
' below, and all are optional.
'
' In:
' Flags: one or more of the ahtOFN_* constants, OR'd together.
' InitialDir: the directory in which to first look
' Filter: a set of file filters, set up by calling
' AddFilterItem. See examples.
' FilterIndex: 1-based integer indicating which filter
' set to use, by default (1 if unspecified)
' DefaultExt: Extension to use if the user doesn't enter one.
' Only useful on file saves.
' FileName: Default value for the file name text box.
' DialogTitle: Title for the dialog.
' hWnd: parent window handle
' OpenFile: Boolean(True=Open File/False=Save As)
' Out:
' Return Value: Either Null or the selected filename
Dim OFN As tagOPENFILENAME
Dim strFileName As String
Dim strFileTitle As String
Dim fResult As Boolean
' Give the dialog a caption title.
If IsMissing(InitialDir) Then InitialDir = CurDir
If IsMissing(Filter) Then Filter = ""
If IsMissing(FilterIndex) Then FilterIndex = 1
If IsMissing(Flags) Then Flags = 0&
If IsMissing(DefaultExt) Then DefaultExt = ""
If IsMissing(FileName) Then FileName = ""
If IsMissing(DialogTitle) Then DialogTitle = ""
If IsMissing(hwnd) Then hwnd = Application.hWndAccessApp
If IsMissing(OpenFile) Then OpenFile = True
' Allocate string space for the returned strings.
strFileName = Left(FileName & String(256, 0), 256)
strFileTitle = String(256, 0)
' Set up the data structure before you call the function
With OFN
.lStructSize = Len(OFN)
.hwndOwner = hwnd
.strFilter = Filter
.nFilterIndex = FilterIndex
.strFile = strFileName
.nMaxFile = Len(strFileName)
.strFileTitle = strFileTitle
.nMaxFileTitle = Len(strFileTitle)
.strTitle = DialogTitle
.Flags = Flags
.strDefExt = DefaultExt
.strInitialDir = InitialDir
' Didn't think most people would want to deal with
' these options.
.hInstance = 0
'.strCustomFilter = ""
'.nMaxCustFilter = 0
.lpfnHook = 0
'New for NT 4.0
.strCustomFilter = String(255, 0)
.nMaxCustFilter = 255
End With
' This will pass the desired data structure to the
' Windows API, which will in turn it uses to display
' the Open/Save As Dialog.
If OpenFile Then
fResult = aht_apiGetOpenFileName(OFN)
Else
fResult = aht_apiGetSaveFileName(OFN)
End If
' The function call filled in the strFileTitle member
' of the structure. You'll have to write special code
' to retrieve that if you're interested.
If fResult Then
' You might care to check the Flags member of the
' structure to get information about the chosen file.
' In this example, if you bothered to pass in a
' value for Flags, we'll fill it in with the outgoing
' Flags value.
If Not IsMissing(Flags) Then Flags = OFN.Flags
If Flags And ahtOFN_ALLOWMULTISELECT Then
' Return the full array.
Dim items As Variant
Dim value As String
value = OFN.strFile
' Get rid of empty items:
Dim i As Integer
For i = Len(value) To 1 Step -1
If Mid$(value, i, 1) <> Chr$(0) Then
Exit For
End If
Next i
value = Mid(value, 1, i)
' Break the list up at null characters:
items = Split(value, Chr(0))
' Loop through the items in the "array",
' and build full file names:
Dim numItems As Integer
Dim result() As String
numItems = UBound(items) + 1
If numItems > 1 Then
ReDim result(0 To numItems - 2)
For i = 1 To numItems - 1
result(i - 1) = FixPath(items(0)) & items(i)
Next i
ahtCommonFileOpenSave = result
Else
' If you only select a single item,
' Windows just places it in item 0.
ahtCommonFileOpenSave = items(0)
End If
Else
ahtCommonFileOpenSave = TrimNull(OFN.strFile)
End If
Else
ahtCommonFileOpenSave = vbNullString
End If
End Function
Function ahtAddFilterItem(strFilter As String, _
strDescription As String, Optional varItem As Variant) As String
' Tack a new chunk onto the file filter.
' That is, take the old value, stick onto it the description,
' (like "Databases"), a null character, the skeleton
' (like "*.mdb;*.mda") and a final null character.
If IsMissing(varItem) Then varItem = "*.*"
ahtAddFilterItem = strFilter & _
strDescription & vbNullChar & _
varItem & vbNullChar
End Function
Private Function TrimNull(ByVal strItem As String) As String
Dim intPos As Integer
intPos = InStr(strItem, vbNullChar)
If intPos > 0 Then
TrimNull = Left(strItem, intPos - 1)
Else
TrimNull = strItem
End If
End Function
Private Function FixPath(ByVal path As String) As String
If Right$(path, 1) <> "\" Then
FixPath = path & "\"
Else
FixPath = path
End If
End Function
'************** Code End *****************
 

wiklendt

i recommend chocolate
Local time
Today, 22:05
Joined
Mar 10, 2008
Messages
1,746
I have been reading alot about this and have come to the conclusion based on some of the discussions I need to use the API method and module.

I basically want to use a button to browse to a location and find a file and then be able to save that file to another location.

I was able to use the button to select the file and then save the file to another location, but it really isn't happening.

I would assume it is not being copied or saved because I am missing the function to store it tempory in between the open and save function.

I am steering towards the API because I would like to package this in a runtime and not all users may have Office installed. Also wondered about Vista compatibility also.

I very new to the VB end of things.... any help or examples would be great.

first off, please use the code wrapper when posting code. it makes the code easier to read.

second, what's not "really happening"? are you receiving an error message? a weird or unexpected result? where are you having trouble and what do you see and think might be happening?
 

sailinxtc

Registered User.
Local time
Today, 07:05
Joined
Apr 27, 2008
Messages
34
Ok, will look into code wrapper, wasn't aware, new to the forum also, or havent used much...

I am able to browse and locate a file in any directory and then click the OK. Then another Browser deal comes up as expected with the save as box and area to type the file name and can also browse to the directory of choice, and am also able to click OK

What is not happening is the first file I browse to and select OK to isn't getting coppied to the directory I browse to with the second Save As browser window and select OK.

I simply am trying to browse to a file and save to another location and/or file name with using a button and the browse style method for ease.

Should be equivalent to copying a file from one directory to another directory either under the same file name, or being able to type the new file name.

I am guessing what is happening is that I need to somehow hold the file or pass it to the second browse window that pops up for saving to new location, just don't know how to go about it, or have I really missed something....
 

wiklendt

i recommend chocolate
Local time
Today, 22:05
Joined
Mar 10, 2008
Messages
1,746
sounds like you have not told access to actually temporarily store the path of the selected file.

what's the code you are using on your buttons (or however you're invoking the API code)? please only post the code pertinent to the button.
 

sailinxtc

Registered User.
Local time
Today, 07:05
Joined
Apr 27, 2008
Messages
34
The code I had posted prior is what my button was calling - on click - as an event procedure. I will have to look into further on tempory storing the file and location etc... not to experienced with that yet. thanks
 

wiklendt

i recommend chocolate
Local time
Today, 22:05
Joined
Mar 10, 2008
Messages
1,746
The code I had posted prior is what my button was calling - on click - as an event procedure. I will have to look into further on tempory storing the file and location etc... not to experienced with that yet. thanks

there are multiple functions in that code. what is the exact code you have on your on click event procedure. it must be calling a specific function from that module.

also, does the example you picked this code up from work properly as you expect it? does it require user intervention to save the selected file somewhere, or does the whole process (select, and save as) happen just upon the one button click?

it sound like you aren't storing that variable. here is a snippet of code i have in one of my databases which gets an external image file and does a few things: it copies the image to a subfolder of the current database location, it renames that copy from the original file name to a database-defined name (e.g., from "sally's apallosa.jpg" to correspond with the horse ID so something like "7_Photo_0.jpg", it has error handling so that if the user click "cancel" in the open dialog the database doesn't error-out.

i think my API module code is different to yours (but it's hard to say b/c the code you posted is so hard to read, and you haven't given a link to the original source) but i'm pretty sure it's quite similar enough for me to post the code i just spoke of and give you ideas on how you might do this in your own database. if you store the select path in a temporary string, then refer to that string when you call the "save as" code, i think that might help.

Code:
' Particular thanks to CyberLynx on Access Word Forums for help with the image management code.

Option Compare Database
Option Explicit
Dim OriginalImagePath0, OriginalImagePath1, OriginalImagePath2, OriginalImagePath3, OriginalImagePath4, OriginalImagePath5, OriginalImagePath6 As Variant
Dim Msg As String

Private Sub cmdBrowseHorsePhoto0_Click()
On Error GoTo err_cmdBrowseHorsePhoto0

   Dim strDialogTitle As String
   Dim PathStrg As String
   Dim Msg As String
   Dim relativePath0 As String
   Dim dbPath As String

   'OriginalImagePath variable is always updated by the Form's OnCurrent Event
   If Nz(OriginalImagePath0, "") <> "" Then Me![HorsePhoto] = OriginalImagePath0

       strDialogTitle = "Select a default image for " & Me!FormHorseName
       PathStrg = GetOpenFile_CLT(".\", strDialogTitle)
       
   'If no file was selected then the PathStrg variable will be empty.
   'If there was a file selected then.....
   If PathStrg <> "" Then
   
        'setup new file name and appropriate DB subfolder
        relativePath0 = "\HorsePhotos\" & Me.ID & "_Photo_0.jpg"
        dbPath = Application.CurrentProject.Path
        
        'copy selected file with new name and subfolder
        FileCopy LCase(PathStrg), dbPath & relativePath0
        
        'update the table field with the new file name and relative location
        Me!HorsePhoto.Value = relativePath0
        'display the image from the subfolder of the DB
        Me!imgHorsePhoto0.Picture = dbPath & relativePath0
            
   End If

exit_cmdBrowseHorsePhoto0:
    Exit Sub
    
err_cmdBrowseHorsePhoto0:
        Msg = "Error # " & Str(Err.Number) & Chr(13) & Err.Description
        MsgBox Msg, vbOKOnly, "The PED", Err.HelpFile, Err.HelpContext
    Resume exit_cmdBrowseHorsePhoto0

End Sub
 

sailinxtc

Registered User.
Local time
Today, 07:05
Joined
Apr 27, 2008
Messages
34
The Code I posted was an example from the forum and also on MS Access site. If you search on browser API it comes up all over and also in search engine listings... I agree hard to follow and probably why I am having so much trouble.

All I want to do is use a browser GUI to copy a file from one directory to another using the browser GUI

probably need to step away from it for a day

thanks for your input... and example of code
 

Users who are viewing this thread

Top Bottom