9

I'm writing a VBA macro for Outlook and the Application.FileDialog method is not available.

The intent is for the user to select a folder - not an Outlook email folder, but a file system directory folder.

Here are the references I have enabled:

  • Visual Basic for Applications Microsoft Outlook 15.0 Object Library
  • Microsoft Office 15.0 Object Library OLE Automation Microsoft Forms
  • Microsoft Office 15.0 Object Library
  • OLE Automation Microsoft Forms Object Library
  • Microsoft Scripting Run-time
  • Microsoft Office 15.0 Access database engine Object Library

Any ideas?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
david wendelken
  • 191
  • 1
  • 8

2 Answers2

14

Outlook doesn't support the FileDialog object. Here's a workaround:

Dim xlApp As Object
Set xlApp = CreateObject("Excel.Application")
    xlApp.Visible = False

Dim fd As Office.FileDialog
Set fd = xlApp.Application.FileDialog(msoFileDialogFilePicker)

Dim selectedItem As Variant

If fd.Show = -1 Then
    For Each selectedItem In fd.SelectedItems
        Debug.Print selectedItem
    Next
End If

Set fd = Nothing
    xlApp.Quit
Set xlApp = Nothing
Kostas K.
  • 8,293
  • 2
  • 22
  • 28
  • 1
    Perfect! I only work in VBA a day or two every 5 years and I hadn't yet puzzled out how to create the Excel or Word application yet. Thanks for saving me hours! – david wendelken May 11 '17 at 17:25
  • Nice, simple workaround. But one detail to note is that you don't actually have to set the xlApp object's Visible property to False because that is its default state. – pstraton Feb 05 '21 at 19:30
  • 1
    For anyone using this method - you'll probably very quickly realize that the `FilePicker` opens behind all other windows and is difficult to find (it looks like Outlook is frozen). After a lot of searching, the fix is actually pretty simple. You'll need something like `Private Declare PtrSafe Function SetForegroundWindow Lib "user32" (ByVal win As LongPtr) As LongPtr` - see [MSDN](https://learn.microsoft.com/en-us/office/vba/language/concepts/getting-started/64-bit-visual-basic-for-applications-overview) and then before `fd.Show` just add `SetForegroundWindow (xlApp.hWnd)` – immobile2 Oct 08 '21 at 14:49
5

Here is another workaround that I have used

Option Explicit
' For Outlook 2010.
#If VBA7 Then
    ' The window handle of Outlook.
    Private lHwnd As LongPtr

    ' /* API declarations. */
    Private Declare PtrSafe Function FindWindow Lib "user32" _
            Alias "FindWindowA" (ByVal lpClassName As String, _
                                 ByVal lpWindowName As String) As LongPtr

' For the previous version of Outlook 2010.
#Else
    ' The window handle of Outlook.
    Private lHwnd As Long

    ' /* API declarations. */
    Private Declare Function FindWindow Lib "user32" _
            Alias "FindWindowA" (ByVal lpClassName As String, _
                                 ByVal lpWindowName As String) As Long
#End If
'
' Windows desktop -
' the virtual folder that is the root of the namespace.
Private Const CSIDL_DESKTOP = &H0

' Only return file system directories.
' If user selects folders that are not part of the file system,
' then OK button is grayed.
Private Const BIF_RETURNONLYFSDIRS = &H1

' Do not include network folders below
' the domain level in the dialog box's tree view control.
Private Const BIF_DONTGOBELOWDOMAIN = &H2

Public Sub SelectFolder()
    Dim objFSO As Object
    Dim objShell As Object
    Dim objFolder As Object
    Dim strFolderPath As String
    Dim blnIsEnd As Boolean

    blnIsEnd = False

    Set objShell = CreateObject("Shell.Application")
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFolder = objShell.BrowseForFolder( _
                lHwnd, "Please Select Folder to:", _
                BIF_RETURNONLYFSDIRS + BIF_DONTGOBELOWDOMAIN, CSIDL_DESKTOP)


    If objFolder Is Nothing Then
        strFolderPath = ""
        blnIsEnd = True
        GoTo PROC_EXIT
    Else
        strFolderPath = CGPath(objFolder.Self.Path)
    End If

PROC_EXIT:
    Set objFSO = Nothing
    If blnIsEnd Then End
End Sub

Public Function CGPath(ByVal Path As String) As String
    If Right(Path, 1) <> "\" Then Path = Path & "\"
    CGPath = Path
End Function
0m3r
  • 12,286
  • 15
  • 35
  • 71