Download attachment (attachment not found) - vba

I've got a code from here and I'm tweaking it for my need. My need is quite simple: I need it to download if it has the name of the Daily Tracker I'm keeping track of (as it changes daily with the Format(Now)). The problem is that it is not finding the attachment.
The code can find the email if I substitute the ElseIf to Next part for oOlItm.Display, but won't download the attachment.
Sub AttachmentDownload()
Const olFolderInbox As Integer = 6
'~~> Path for the attachment
Const AttachmentPath As String = "C:\TEMP\TestExcel"
Dim oOlAp As Object
Dim oOlns As Object
Dim oOlInb As Object
Dim oOlItm As Object
Dim oOlAtch As Object
Dim NewFileName As String
NewFileName = "Daily Tracker " & Format(Now, "dd/MM/yyyy")
Set oOlAp = GetObject(, "Outlook.application")
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
For Each oOlItm In oOlInb.Items
If InStr(oOlItm.Subject, NewFilename)) <> 0 Then
ElseIf oOlItm.Attachments.Count <> 0 Then
For Each oOlAtch In oOlItm.Attachments
oOlAtch.SaveAsFile (AttachmentPath)
Exit For
Next
Else
MsgBox "No attachments found"
End If
Exit For
Next
End Sub
The email:

This should work for you:
Sub AttachmentDownload()
Const olFolderInbox As Integer = 6
'~~> Path for the attachment
Const AttachmentPath As String = "C:\TEMP\TestExcel"
Dim oOlAp As Object
Dim oOlns As Object
Dim oOlInb As Object
Dim oOlItm As Object
Dim oOlAtch As Object
Dim oOlResults As Object
Dim x As Long
Dim NewFileName As String
NewFileName = "Daily Tracker " & Format(Now, "dd-MM-yyyy")
'You can only have a single instance of Outlook, so if it's already open
'this will be the same as GetObject, otherwise it will open Outlook.
Set oOlAp = CreateObject("Outlook.Application")
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
'No point searching the whole Inbox - just since yesterday.
Set oOlResults = oOlInb.Items.Restrict("[ReceivedTime]>'" & Format(Date - 1, "DDDDD HH:NN") & "'")
'If you have more than a single attachment they'll all overwrite each other.
'x will update the filename.
x = 1
For Each oOlItm In oOlResults
If oOlItm.attachments.Count > 0 Then
For Each oOlAtch In oOlItm.attachments
If GetExt(oOlAtch.FileName) = "xlsx" Then
oOlAtch.SaveAsFile AttachmentPath & "\" & NewFileName & "-" & x & ".xlsx"
End If
x = x + 1
Next oOlAtch
End If
Next oOlItm
End Sub
'----------------------------------------------------------------------
' GetExt
'
' Returns the extension of a file.
'----------------------------------------------------------------------
Public Function GetExt(FileName As String) As String
Dim mFSO As Object
Set mFSO = CreateObject("Scripting.FileSystemObject")
GetExt = mFSO.GetExtensionName(FileName)
End Function
Another way of doing it is from within Outlook:
Create a new folder in your Outlook Inbox and set a rule to move the email to this folder when it arrives. You can then write code to watch this folder and save the file as soon as it arrives.
Place this code within the ThisOutlookSession module in Outlook.
Dim WithEvents TargetFolderItems As Items
Const FILE_PATH As String = "C:\TEMP\TestExcel\"
Private Sub Application_Startup()
Dim ns As Outlook.NameSpace
Set ns = Application.GetNamespace("MAPI")
Set TargetFolderItems = ns.Folders.Item("Mailbox - Darren Bartrup-Cook") _
.Folders.Item("Inbox") _
.Folders.Item("My Email For Processing").Items
End Sub
Sub TargetFolderItems_ItemAdd(ByVal Item As Object)
'when a new item is added to our "watched folder" we can process it
Dim olAtt As Attachment
Dim i As Integer
Dim sTmpFileName As String
Dim objFSO As Object
Dim sExt As String
If Item.Attachments.Count > 0 Then
Set objFSO = CreateObject("Scripting.FileSystemObject")
For i = 1 To Item.Attachments.Count
Set olAtt = Item.Attachments(i)
sExt = objFSO.GetExtensionName(olAtt.FileName)
If sExt = "xlsx" Then
sTmpFileName = "Daily Tracker " & Format(Now, "dd-mm-yyyy") & ".xlsx"
End If
Item.UnRead = False
olAtt.SaveAsFile FILE_PATH & sTmpFileName
DoEvents
Next
End If
Set olAtt = Nothing
MsgPopup "A new attachment has been saved.", vbOKOnly, "New Daily Tracker"
End Sub
Private Sub Application_Quit()
Dim ns As Outlook.NameSpace
Set TargetFolderItems = Nothing
Set ns = Nothing
End Sub
Create a new module in Outlook and put this code in there. This will create a messagebox that won't stop whatever you're doing.
Public Function MsgPopup(Optional Prompt As String, _
Optional Buttons As VbMsgBoxStyle = vbOKOnly, _
Optional Title As String, _
Optional SecondsToWait As Long = 0) As VbMsgBoxResult
' Replicates the VBA MsgBox() function, with an added parameter
' to automatically dismiss the message box after n seconds
' If dismissed automatically, this will return -1: NOT ‘cancel’ or the default button choice.
' Nigel Heffernan, 2006. This code is in the public domain.
' Uses late-binding: bad for performance and stability, useful for code portability
' The correct declaration is: Dim objWshell As IWshRuntimeLibrary.WshShell
Dim objWshell As Object
Set objWshell = CreateObject("WScript.Shell")
MsgPopup = objWshell.Popup(Prompt, SecondsToWait, Title, Buttons)
Set objWshell = Nothing
End Function

Related

OutLook VBA Email or Notification Causes Out of Bounds Error

I have some outlook VBA code which works fine to save attachments, however every time I get an email or a meeting notification in Outlook it causes an instant Out of Bounds error If I don't get any emails or notifications the code will run fine through to completion.
Is there a way to ensure that these notifications will not stop the code from running?
Option Explicit
Sub SaveAttachmentsFromSelectedItemsPDF2_ForNext()
Dim currentItem As Object
Dim currentAttachment As Attachment
Dim saveToFolder As String
Dim savedFileCountPDF As Long
Dim i As Long
Dim j As Long
saveToFolder = "c:\dev\outlookexport" 'change the path accordingly
savedFileCountPDF = 0
For i = 1 To ActiveExplorer.Selection.Count
Set currentItem = ActiveExplorer.Selection(i)
For j = 1 To currentItem.Attachments.Count
Set currentAttachment = currentItem.Attachments(j)
If UCase(Right(currentAttachment.DisplayName, 5)) = UCase(".xlsx") Then
currentAttachment.SaveAsFile saveToFolder & "\" & _
Left(currentAttachment.DisplayName, Len(currentAttachment.DisplayName) - 5) & ".xlsx"
savedFileCountPDF = savedFileCountPDF + 1
End If
' If For Next does not release memory automatically then
' uncomment to see if this has an impact
'Set currentAttachment = Nothing
Next
' If For Next does not release memory automatically then
' uncomment to see if this has an impact
'Set currentItem = Nothing
Next
MsgBox "Number of PDF files saved: " & savedFileCountPDF, vbInformation
End Sub
This is what I tried to create from the answer below:
Option Explicit
Sub SaveAttachmentsFromSelectedItemsPDF2_ForNext()
Dim currentItem As Object
Dim currentAttachment As Attachment
Dim saveToFolder As String
Dim savedFileCountPDF As Long
Dim i As Long
Dim j As Long
Dim x As Long
Dim myOlExp As Object
Dim myOlSel As Object
' New
Set myOlExp = Application.ActiveExplorer
Set myOlSel = myOlExp.Selection
saveToFolder = "c:\dev\outlookexport" 'change the path accordingly
savedFileCountPDF = 0
For x = 1 To myOlSel.Count
If myOlSel.Item(x).Class = OlObjectClass.olMail Then
Set currentItem = ActiveExplorer.Selection(i)
For j = 1 To currentItem.Attachments.Count
Set currentAttachment = currentItem.Attachments(j)
If UCase(Right(currentAttachment.DisplayName, 5)) = UCase(".xlsx") Then
currentAttachment.SaveAsFile saveToFolder & "\" & _
Left(currentAttachment.DisplayName, Len(currentAttachment.DisplayName) - 5) & ".xlsx"
savedFileCountPDF = savedFileCountPDF + 1
End If
Next
End If
Next
MsgBox "Number of PDF files saved: " & savedFileCountPDF, vbInformation
End Sub
The Selection property of the Explorer class returns a Selection object that contains the item or items that are selected in the explorer window. In your code I've noticed the following lines of code:
For i = 1 To ActiveExplorer.Selection.Count
Set currentItem = ActiveExplorer.Selection(i)
So, if the selection is changed in Outlook between these two lines of code you may get out of range exception at runtime. Instead, I'd recommend caching the selection object and use it through the code to make sure it remains the same:
Set myOlExp = Application.ActiveExplorer
Set myOlSel = myOlExp.Selection
For x = 1 To myOlSel.Count
If myOlSel.Item(x).Class = OlObjectClass.olMail Then
' do something here
End If
Next
Another important thing is that a folder may contain different types of items. You'd need to check their message class to distinguish different kind of Outlook items.

VBA - Searching for a SPECIFIC file in a folder and attaching it in an Outlook Mail

I am working with VBA that would send error logs to multiple user. This error log can be found in a folder together with a process log file. These files have dates on their names and are not dependent on Now().
I only want to attach the error log and disregard the process log. I have done multiple research with similar topics and was able to made this code:
Sub SendEmailFail()
Dim OutlookApp As Outlook.Application
Dim OutlookMail As Outlook.MailItem
Dim RecipientF As Object
Dim myRecipientF As Outlook.Recipient
Dim sToF As Object
Dim CCf As Object
Dim myCCf As Outlook.Recipient
Dim sCcF As Object
Dim FilesF As VBA.Collection
Dim mDoneF As String
Dim FileF As Scripting.File
Dim AttsF As Outlook.Attachments
Application.ScreenUpdating = False
Set OutlookApp = New Outlook.Application
Set OutlookMail = OutloookApp.CreateItem(0)
Set FilesF = GetFilesF
mDoneF = Environ("userprofile") & _
"\Documents\Automation Anywhere Files\Automation Anywhere\My Reports\ABC\Logs\Done"
'=========================================START========================================='
Workbooks("ConfigFile.xlsm").Activate
Sheets("Sheet1").Activate
Range("C2").Select
Set RecipientF = Range(ActiveCell, ActiveCell.End(xlDown))
ActiveCell.Offset(0, 1).Select
Set CCf = Range(ActiveCell, ActiveCell.End(xlDown))
On Error Resume Next
With OutlookMail
.Display
End With
With OutlookMail
'Get all recipients from Column C
For Each sToF In RecipientF
Set myRecipientF = OutlookMail.Recipients.Add(sToF)
myRecipientF.Type = olTo
myRecipientF.Resolve
If Not myRecipientF.Resolved Then
myRecipientF.Delete
End If
Next sToF
'Get all CCs from Column D
For Each sCcF In CCf
Set myCCf = OutlookMail.Recipients.Add(sCcF)
myCCf.Type = olCC
myCCf.Resolve
If Not myCCf.Resolved Then
myCCf.Delete
End If
Next sCcF
.Body = ThisWorkbook.Sheets("Sheet1").Range("F2").Value & vbNewLine & _
vbNewLine & ThisWorkbook.Sheets("Sheet1").Range("F3").Value & vbNewLine & _
vbNewLine & ThisWorkbook.Sheets("Sheet1").Range("F4").Value & vbNewLine & _
vbNewLine & "Thank You!"
'Adding Error Logs
If FilesF.Count Then
Set AttsF = OutlookMail.Attachments
For Each File In Files
AttsF.Add FileF.Path
Next
End If
End With
On Error GoTo 0
Set OutlookMail = Nothing
Set OutlookApp = Nothing
Application.ScreenUpdating = True
End Sub
Function GetFilesF() As VBA.Collection
Dim FolderF As Scripting.Folder
Dim FsoF As Scripting.FileSystemObject
Dim FilesF As Scripting.Files
Dim FileF As Scripting.File
Dim ListF As VBA.Collection
Dim mSendF As String
Dim mDoneF As String
Dim StrFileF As String
mSendF = Environ("userprofile") & _
"\Documents\Automation Anywhere Files\Automation Anywhere\My Reports\ABC\Logs\Send"
mDoneF = Environ("userprofile") & _
"\Documents\Automation Anywhere Files\Automation Anywhere\My Reports\ABC\Logs\Done"
Set ListF = New VBA.Collection
Set FsoF = New Scripting.FileSystemObject
Set FolderF = FsoF.GetFolder(mSendF)
Set FilesF = FolderF.FilesF
For Each FileF In FilesF
'Return only visible files
If (FileF.Attributes Or Hidden) <> FileF.Attributes Then
StrFileF = Dir(Environ("userprofile") & _
"\Documents\Automation Anywhere Files\Automation Anywhere\My Reports\ABC\Logs\Send\*Error Log*")
If Len(StrFileF) > 0 Then
List.Add FileF
End If
End If
Next
Set GetFilesF = ListF
End Function
However, I encountered a run time error "424" : object required. This MsgBox only has an OK and HELP Button and a little bit small compared to the usual MsgBox size for errors. I do not know where the error is even though I can the macro using F8 since it doesn't highlight the line after the error was displayed.
EDITED
Changed some declarations and I was able to completely run the macro. Yet, Error logs AND process logs were both attached. I know there is a problem with my codes in searching for a file with "ERROR LOG" on its filename. The modified code was as follows:
Sub SendEmailFail()
Dim OutlookApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim RecipientF As Object
Dim myRecipientF As Outlook.Recipient
Dim sToF As Object
Dim CCf As Object
Dim myCCf As Outlook.Recipient
Dim sCcF As Object
Dim Files As VBA.Collection
Dim mDoneF As String
Dim FileF As Scripting.File
Dim AttsF As Outlook.Attachments
Application.ScreenUpdating = False
Set OutlookApp = New Outlook.Application
Set OutMail = OutlookApp.CreateItem(olMailItem)
Set Files = GetFilesF
mDoneF = Environ("userprofile") & _
"\Documents\Automation Anywhere Files\Automation Anywhere\My Reports\AccentureCIO\Logs\Done"
'=========================================START========================================='
Workbooks("ConfigFile.xlsm").Activate
Sheets("Sheet1").Activate
Range("C2").Select
Set RecipientF = Range(ActiveCell, ActiveCell.End(xlDown))
ActiveCell.Offset(0, 1).Select
Set CCf = Range(ActiveCell, ActiveCell.End(xlDown))
On Error Resume Next
With OutMail
.Display
End With
With OutMail
'Get all recipients from Column C
For Each sToF In RecipientF
Set myRecipientF = OutMail.Recipients.Add(sToF)
myRecipientF.Type = olTo
myRecipientF.Resolve
If Not myRecipientF.Resolved Then
myRecipientF.Delete
End If
Next sToF
'Get all CCs from Column D
For Each sCcF In CCf
Set myCCf = OutMail.Recipients.Add(sCcF)
myCCf.Type = olCC
myCCf.Resolve
If Not myCCf.Resolved Then
myCCf.Delete
End If
Next sCcF
.Body = ThisWorkbook.Sheets("Sheet1").Range("F2").Value & vbNewLine & _
vbNewLine & ThisWorkbook.Sheets("Sheet1").Range("F3").Value & vbNewLine & _
vbNewLine & ThisWorkbook.Sheets("Sheet1").Range("F4").Value & vbNewLine & _
vbNewLine & "Thank You!"
'Adding Error Logs
If Files.Count Then
Set AttsF = OutMail.Attachments
For Each FileF In Files
AttsF.Add FileF.Path
Next
End If
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutlookApp = Nothing
Application.ScreenUpdating = True
End Sub
Function GetFilesF() As VBA.Collection
Dim FolderF As Scripting.Folder
Dim FsoF As Scripting.FileSystemObject
Dim FilesF As Scripting.Files
Dim FileF As Scripting.File
Dim ListF As VBA.Collection
Dim mSendF As String
Dim mDoneF As String
Dim StrFileF As String
mSendF = Environ("userprofile") & _
"\Documents\Automation Anywhere Files\Automation Anywhere\My Reports\AccentureCIO\Logs\Send"
mDoneF = Environ("userprofile") & _
"\Documents\Automation Anywhere Files\Automation Anywhere\My Reports\AccentureCIO\Logs\Done"
Set ListF = New VBA.Collection
Set FsoF = New Scripting.FileSystemObject
Set FolderF = FsoF.GetFolder(mSendF)
Set Files = FolderF.Files
For Each FileF In Files
'Return only visible files
If (FileF.Attributes Or Hidden) <> FileF.Attributes Then
StrFileF = Dir(Environ("userprofile") & _
"\Documents\Automation Anywhere Files\Automation Anywhere\My Reports\AccentureCIO\Logs\Send\*Error Log*")
If Len(StrFileF) > 0 Then
ListF.Add FileF
End If
End If
Next
Set GetFilesF = ListF
End Function

How to get Outlook Email received time

I need to extract attachments from Emails received in a user preferred time frame.
Say like extract for Emails received between 2PM to 4PM.
Please find the below code I've that extract files perfectly - but it did for all the Emails in the folder.
Please help me to resolve it.
Sub Unzip()
Dim ns As NameSpace 'variables for the main functionality
Dim Inbox As MAPIFolder
Dim SubFolder As MAPIFolder
Dim Atchmt As Attachment
Dim FileName As Variant
Dim msg As Outlook.MailItem
Dim FSO As Object 'variables for unzipping
Dim oApp As Object
Dim FileNameFolder As Variant
Dim Totalmsg As Object
Dim oFrom
Dim oEnd
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
Set SubFolder = Inbox.Folders("TEST")
Set Totalmsg = msg.ReceivedTime
oFrom = InputBox("Please give start time", ("Shadowserver report"))
oEnd = InputBox("Please give End time", ("Shadowserver report"))
If Totalmsg <= oFrom And Totalmsg >= oEnd Then
For Each msg In SubFolder.Items
For Each Atchmt In msg.Attachments
If (Right(Atchmt.FileName, 3) = "zip") Then
MsgBox "1"
FileNameFolder = "C:\Users\xxxx\Documents\test\"
FileName = FileNameFolder & Atchmt.FileName
Atchmt.SaveAsFile FileName
Set oApp = CreateObject("Shell.Application")
oApp.NameSpace(FileNameFolder).CopyHere oApp.NameSpace(FileName).Items
Kill (FileName)
On Error Resume Next
Set FSO = CreateObject("scripting.filesystemobject")
FSO.deletefolder Environ("Temp") & "\Temporary Directory*", True
End If
Next
Next
End If
End Sub
Made a few improvements to improve performance and clarity :
Test received time inside the loop on the messages
Defined related variables as Date (like MsG.ReceivedTime) and improved input messages
Added Option Explicit to avoid mishaps in future coding (VERY GOOD PRACTICE)
Use Environ$("USERPROFILE") to get User directory's path
Reorganize variables and initialisation outside of the loops
Added LCase to be sure to get all zips (including .ZIP)
Code :
Option Explicit
Sub Unzip()
'''Variables for the main functionality
Dim NS As NameSpace
Dim InboX As MAPIFolder
Dim SubFolder As MAPIFolder
Dim MsG As Outlook.MailItem
Dim AtcHmt As Attachment
Dim ReceivedHour As Date
Dim oFrom As Date
Dim oEnd As Date
'''Variables for unzipping
Dim FSO As Object
Dim ShellApp As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
Set ShellApp = CreateObject("Shell.Application")
Dim FileNameFolder As Variant
Dim FileName As Variant
'''Define the Outlook folder you want to scan
Set NS = GetNamespace("MAPI")
Set InboX = NS.GetDefaultFolder(olFolderInbox)
Set SubFolder = InboX.Folders("TEST")
'''Define the folder where you want to save attachments
FileNameFolder = Environ$("USERPROFILE") & "\Documents\test\"
'''Define the hours in between which you want to apply the extraction
oFrom = CDate(InputBox("Please give Start time" & vbCrLf & _
"Example: 9AM", ("Shadowserver report"), "9AM"))
oEnd = CDate(InputBox("Please give End time" & vbCrLf & _
"Example: 6PM", ("Shadowserver report"), "6PM"))
For Each MsG In SubFolder.items
ReceivedHour = MsG.ReceivedTime
If oFrom <= TimeValue(ReceivedHour) And _
TimeValue(ReceivedHour) <= oEnd Then
For Each AtcHmt In MsG.Attachments
FileName = AtcHmt.FileName
If LCase(Right(FileName, 3)) <> "zip" Then
Else
FileName = FileNameFolder & FileName
AtcHmt.SaveAsFile FileName
ShellApp.NameSpace(FileNameFolder).CopyHere _
ShellApp.NameSpace(FileName).items
Kill (FileName)
On Error Resume Next
FSO.deletefolder Environ$("Temp") & "\Temporary Directory*", True
End If
Next AtcHmt
End If
Next MsG
End Sub
I am just going to include the part that you need to change. Other lines will be the same. Basically, what you need to do is to set the Totalmsg inside your loop for each msg;
Sub Unzip()
'... copy your code till here
Set SubFolder = Inbox.Folders("TEST")
oFrom = InputBox("Please give start time", ("Shadowserver report"))
oEnd = InputBox("Please give End time", ("Shadowserver report"))
For Each msg In SubFolder.Items
Set Totalmsg = msg.ReceivedTime
If Totalmsg <= oFrom And Totalmsg >= oEnd Then 'You check it for each msg
'rest will be the same until ...
FSO.deletefolder Environ("Temp") & "\Temporary Directory*", True
End If
Next
End If
Next
End Sub

Downloading Attachments from Unread Emails of MS Outlook

I want to download all attachments of Unread emails from my MS Outlook. I found this below mentioned code on StackExchange which downloads attachments from first Unread email.
Can any one modify this code so i can apply it on all Unread emails.
Const olFolderInbox As Integer = 6
'~~> Path for the attachment
Const AttachmentPath As String = "C:\"
Sub DownloadAttachmentFirstUnreadEmail()
Dim oOlAp As Object, oOlns As Object, oOlInb As Object
Dim oOlItm As Object, oOlAtch As Object
'~~> New File Name for the attachment
Dim NewFileName As String
NewFileName = AttachmentPath & Format(Date, "DD-MM-YYYY") & "-"
'~~> Get Outlook instance
Set oOlAp = GetObject(, "Outlook.application")
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
'~~> Check if there are any actual unread emails
If oOlInb.Items.Restrict("[UnRead] = True").Count = 0 Then
MsgBox "NO Unread Email In Inbox"
Exit Sub
End If
'~~> Extract the attachment from the 1st unread email
For Each oOlItm In oOlInb.Items.Restrict("[UnRead] = True")
'~~> Check if the email actually has an attachment
If oOlItm.Attachments.Count <> 0 Then
For Each oOlAtch In oOlItm.Attachments
'~~> Download the attachment
oOlAtch.SaveAsFile NewFileName & oOlAtch.Filename
Exit For
Next
Else
MsgBox "The First item doesn't have an attachment"
End If
Exit For
Next
End Sub
When using Items.Restrict Method (Outlook) you may want to set the Filter for both Attachment and UnRead Items, Filter = "[attachment] = True And [Unread] = True" then use a For...Next and loop backwards
Example:
Option Explicit
Public Sub Example()
'// Declare your Variables
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Dim Items As Outlook.Items
Dim Item As Outlook.MailItem
Dim Atmt As Attachment
Dim Filter As String
Dim FilePath As String
Dim AtmtName As String
Dim i As Long
'// Set Inbox Reference
Set olNs = Application.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
FilePath = "C:\Temp\"
Filter = "[attachment] = True And [Unread] = True"
Set Items = Inbox.Items.Restrict(Filter)
'// Loop through backwards
For i = Items.Count To 1 Step -1
Set Item = Items(i)
DoEvents
If Item.Class = olMail Then
Debug.Print Item.Subject ' Immediate Window
For Each Atmt In Item.Attachments
AtmtName = FilePath & Atmt.FileName
Atmt.SaveAsFile AtmtName
Next
End If
Next
Set Inbox = Nothing
Set Items = Nothing
Set Item = Nothing
Set Atmt = Nothing
Set olNs = Nothing
End Sub
Much cleaner, batter & faster...

Copy emails from Outlook folder to system folder

I am using the below VBA code in Outlook to copy the selected emails to system folder. Instead of selecting emails I need to modify the code to copy all the emails from a particular folder in Outlook.
' General Declarations
Option Explicit
' Public declarations
' Public Enum olSaveAsTypeEnum
'olSaveAsTxt = 0
'olSaveAsRTF = 1
'olSaveAsMsg = 3
'End Enum
Sub UATExport_MailasMSG()
' Routine will take all selected mails and export them as .MSG files to the
' directory defined by
' Error Handling
On Error Resume Next
' Varaiable Declarations
Dim objItem As Outlook.MailItem
Dim strExportFolder As String: strExportFolder = "I:\Documents\Dscan\"
Dim strExportFileName As String
Dim strExportPath As String
Dim objRegex As Object
Dim OldName As String, NewName As String
' Initiate regex search
Set objRegex = CreateObject("VBScript.RegExp")
With objRegex
.Pattern = "(\s|\\|/|<|>|\|\|\?|:)"
.Global = True
.IgnoreCase = True
End With
' Check if any objects are selected.
If Application.ActiveExplorer.Selection.Count = 0 Then
MsgBox ("No item has been selected.")
Else
' Cycle all selected objects.
For Each objItem In Application.ActiveExplorer.Selection
' If the currently selected item is a mail item we can proceed
If TypeOf objItem Is Outlook.MailItem Then
' Export to the predefined folder.
strExportFileName = objRegex.Replace(objItem.Subject, "_")
strExportPath = strExportFolder & strExportFileName & ".txt"
objItem.SaveAs strExportPath, olSaveAsTxt
'MsgBox ("Email saved to: " & strExportPath)
OldName = Dir(strExportPath)
NewName = Left(strExportPath, Len(strExportPath) - Len(OldName)) & _
Left(OldName, Len(OldName) - 4) & "DircanReportfor asmsmrwerwdb1u" & _
CStr(Format(FileDateTime(strExportPath), "ddmmyyhhmmss")) & ".txt"
Name strExportPath As NewName
' declaration to go with the others
Dim strEmailBodybackup As String
' this will go in your for loop
' Save the body so that we can restore it after.
strEmailBodybackup = objItem.Body
' Edit the body of the mail to suit needs.
objItem.Body = Replace(objItem.Body, "To", "Tscanfile", , 1, vbTextCompare)
' Process the export like in your question
' Restore the body of the original mail
objItem.Body = strEmailBodybackup
Else
' This is not an email item.
End If
Next 'objItem
End If
' Clear routine memory
Set objItem = Nothing
Set objRegex = Nothing
End Sub
The Folder class provides the Items property which returns an Items collection object as a collection of Outlook items in the specified folder. Be aware, the index for the Items collection starts at 1, and the items in the Items collection object are not guaranteed to be in any particular order. So, you can iterate over all items in the folder using the Items collection.
If you need to find a particular set of items that corresponds to the conditon, you can use the Find/FindNext or Restrict methods of the Items class.
The Sort method sorts the collection of items by the specified property. For example:
Sub SortByDueDate()
Dim myNameSpace As Outlook.NameSpace
Dim myFolder As Outlook.Folder
Dim myItem As Outlook.TaskItem
Dim myItems As Outlook.Items
Set myNameSpace = Application.GetNamespace("MAPI")
Set myFolder = myNameSpace.GetDefaultFolder(olFolderTasks)
Set myItems = myFolder.Items
myItems.Sort "[DueDate]", False
For Each myItem In myItems
MsgBox myItem.Subject & "-- " & myItem.DueDate
Next myItem
End Sub