Is there a SaveAs dialog?

5.4k views Asked by At

I want to save a mail attachment with a SaveAs file dialog. Is it possible to do this with VBA and Outlook?

3

There are 3 answers

2
Jean-François Corbett On BEST ANSWER

I don't think Outlook will let you open a file dialog!

An ugly but quick and functional workaround that I have used is to temporarily open an instance of Excel and use its GetSaveAsFilename method.

Set xlApp = CreateObject("Excel.application")
xlApp.Visible = False
strSaveAsFilename = xlApp.GetSaveAsFilename
xlApp.Quit
Set xlApp = Nothing

Then you can say MyAttachment.SaveAsFile(strSaveAsFilename).

If Excel is not necessarily installed, then you can do a similar trick using Word and the FileDialog method (Word doesn't have GetSaveAsFilename). See VBA help on FileDialog for an example.

There is probably a more elegant solution out there, but the above will work...

0
Filipe On

Don't forget the BrowseForFolder function:

Function BrowseForFolder(Optional OpenAt As String) As String 

Dim ShellApp As Object 

Set ShellApp = CreateObject("Shell.Application"). _ 
BrowseForFolder(0, "Please choose a folder", 0, OpenAt) 

On Error Resume Next 
BrowseForFolder = ShellApp.self.Path 
On Error GoTo 0 

Select Case Mid(BrowseForFolder, 2, 1) 
Case Is = ":" 
    If Left(BrowseForFolder, 1) = ":" Then 
        BrowseForFolder = "" 
    End If 
Case Is = "\" 
    If Not Left(BrowseForFolder, 1) = "\" Then 
        BrowseForFolder = "" 
    End If 
Case Else 
    BrowseForFolder = "" 
End Select 

ExitFunction: 

Set ShellApp = Nothing 

End Function
0
JimmyPena On

There are two ways to simulate this behavior (I assume Outlook 2003 here):

Use File » Save Attachments

This code will programmatically call the "Save Attachments" menu item on the File Menu. The three ancillary functions below are necessary and should be pasted into the same project. Select or open an email with attachments and run the SaveAttachments procedure.

Sub SaveAttachments()

Dim obj As Object
Dim msg As Outlook.mailItem
Dim insp As Outlook.Inspector

Set obj = GetCurrentItem
If TypeName(obj) = "MailItem" Then
  Set msg = obj
  Set insp = msg.GetInspector
  With insp
    .Display
    ' execute the File >> Save Attachments control
    .CommandBars.FindControl(, 3167).Execute
    .Close olDiscard ' or olPromptForSave, or olSave
  End With
End If

End Sub

Function GetCurrentItem() As Object
  Select Case True
  Case IsExplorer(Application.ActiveWindow)
    Set GetCurrentItem = ActiveExplorer.Selection.item(1)
  Case IsInspector(Application.ActiveWindow)
    Set GetCurrentItem = ActiveInspector.CurrentItem
  End Select
End Function
Function IsExplorer(itm As Object) As Boolean
  IsExplorer = (TypeName(itm) = "Explorer")
End Function
Function IsInspector(itm As Object) As Boolean
  IsInspector = (TypeName(itm) = "Inspector")
End Function

Note that if there are multiple attachments, you will be prompted to choose which one(s) you want to save before being shown the save dialog:

save attachments with multiple files

Use BrowseForFolder

I use the BrowseForFolder function found on VBAX. This will show the Shell.Application's BrowseForFolder dialog:

shell app browse for folder

Select or open an email with attachments and run the SaveAttachments procedure. After selecting a folder in the dialog, all attachments to the email will be saved to the selected folder.

Sub SaveAttachments()

  Dim folderToSave As String
  Dim obj As Object
  Dim msg As Outlook.mailItem
  Dim msgAttachs As Outlook.attachments
  Dim msgAttach As Outlook.Attachment

  folderToSave = BrowseForFolder

  If folderToSave <> "False" Then

    Set obj = GetCurrentItem
    If TypeName(obj) = "MailItem" Then
      Set msg = obj
      Set msgAttachs = msg.attachments

      For Each msgAttach In msgAttachs
        msgAttach.SaveAsFile folderToSave & "\" & msgAttach.FileName
      Next msgAttach
    End If

  End If

End Sub

Function GetCurrentItem() As Object
  Select Case True
  Case IsExplorer(Application.ActiveWindow)
    Set GetCurrentItem = ActiveExplorer.Selection.item(1)
  Case IsInspector(Application.ActiveWindow)
    Set GetCurrentItem = ActiveInspector.CurrentItem
  End Select
End Function
Function IsExplorer(itm As Object) As Boolean
  IsExplorer = (TypeName(itm) = "Explorer")
End Function
Function IsInspector(itm As Object) As Boolean
  IsInspector = (TypeName(itm) = "Inspector")
End Function