I am rather new to VBA and was hoping to get some help on a project. To give you some background, I get an email in outlook about every 15 minutes with an excel attachment. I need to open the attachment once the email gets in and view it / compare it to the email that was sent 15 minutes prior. If there is a difference in the emails then I must preform an action. I was hoping to automate at least some of this process. Ideally, I could use a macro to scan my inbox for any new message from a particular sender. If it finds a message it could then check for an attachment and if the attachment is there it would download and open it.
In an ideal world the other thing I could do is compare the prior excel attachment to the current one and ping a message (alert) if it is different.
Any help would be much appreciated. As I said, I am new to VBA but I am trying my best to understand functions.
This should get you started. Assuming you have selected the e-mail in outlook:
Sub check_for_changes()
'Created by Fredrik Östman www.scoc.se
Dim myOlApp As New Outlook.Application
Dim myOlExp As Outlook.Explorer
Dim myOlSel As Outlook.Selection
Set myOlExp = myOlApp.Explorers.Item(1)
Set myOlSel = myOlExp.Selection
Set mymail = myOlSel.Item(1)
Dim myAttachments As Outlook.Attachments
Set myAttachments = mymail.Attachments
Dim Atmt As Attachment
Set Atmt = myAttachments(1)
new_file_name = "C:\tmp\new_received_file.xlsx"
old_file_name = "C:\tmp\old_received_file.xlsx"
FileCopy new_file_name, old_file_name
Atmt.SaveAsFile new_file_name
Dim eApp As Object
Set eApp = CreateObject("Excel.Application")
eApp.Application.Visible = True
Dim new_file As Object
eApp.workbooks.Open new_file_name
Set new_file = eApp.ActiveWorkbook
Dim old_file As Object
eApp.workbooks.Open old_file_name
Set old_file = eApp.ActiveWorkbook
'Find range to compare
start_row = old_file.sheets(1).usedrange.Row
If new_file.sheets(1).usedrange.Row > start_row Then start_row = new_file.sheets(1).usedrange.Row
end_row = old_file.sheets(1).usedrange.Row + old_file.sheets(1).usedrange.Rows.Count
If new_file.sheets(1).usedrange.Rows.Count + new_file.sheets(1).usedrange.Row > end_row Then end_row = new_file.sheets(1).usedrange.Rows.Count + new_file.sheets(1).usedrange.Row
start_col = old_file.sheets(1).usedrange.Column
If new_file.sheets(1).usedrange.Column > start_col Then start_col = new_file.sheets(1).usedrange.Column
end_col = old_file.sheets(1).usedrange.Column + old_file.sheets(1).usedrange.Columns.Count
If new_file.sheets(1).usedrange.Columns.Count + new_file.sheets(1).usedrange.Column > end_row Then end_row = new_file.sheets(1).usedrange.Columns.Count + new_file.sheets(1).usedrange.Column
'Check all cells
something_changed = False
For i = start_row To end_row
For j = start_col To end_col
If new_file.sheets(1).Cells(i, j) <> old_file.sheets(1).Cells(i, j) Then
new_file.sheets(1).Cells(i, j).Interior.ColorIndex = 3 'Mark red
something_changed = True
End If
Next j
Next i
If something_changed Then
new_file.Activate
Else
new_file.Close
old_file.Close
If eApp.workbooks.Count = 0 Then eApp.Quit
MsgBox "No changes"
End If
End Sub
Interesting question, I'll get you started with the outlook part. You'll probably want to split the question between Outlook and Excel.
Here is some code I use to save every attachment I have been sent in Outlook to save space.
Public Sub SaveAttachments()
Dim objOL As Outlook.Application
Dim pobjMsg As Outlook.MailItem 'Object
Dim objSelection As Outlook.Selection
On Error Resume Next
' Instantiate an Outlook Application object.
Set objOL = CreateObject("Outlook.Application")
' Get the collection of selected objects.
Set objSelection = objOL.ActiveExplorer.Selection
For Each pobjMsg In objSelection
SaveAttachments_Parameter pobjMsg
Next
ExitSub:
Set pobjMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
MsgBox "Export Complete"
End Sub
Public Sub SaveAttachments_Parameter(objMsg As MailItem)
Dim objAttachments As Outlook.Attachments
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
' Get the path to your My Documents folder
strFolderpath = "C:\Users\******\Documents\Reports\"
'On Error Resume Next
' Set the Attachment folder.
strFolderpath = strFolderpath & "Outlook Attachments\"
' Get the Attachments collection of the item.
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
If lngCount > 0 Then
' We need to use a count down loop for removing items' from a collection. Otherwise, the loop counter gets' confused and only every other item is removed.
For i = lngCount To 1 Step -1
' Save attachment before deleting from item.
' Get the file name.
strFile = objAttachments.Item(i).FileName
If Right(strFile, 4) = ".png" Or Right(strFile, 4) = ".jpg" Or Right(strFile, 4) = ".gif" Then
GoTo cont
End If
' Combine with the path to the Temp folder.
strFile = strFolderpath & objMsg.SenderName & "." & Format(objMsg.ReceivedTime, "yyyy-MM-dd h-mm-ss") & "." & strFile
' Save the attachment as a file.
objAttachments.Item(i).SaveAsFile strFile
' Delete the attachment - You might not want this part
'objAttachments.Item(i).Delete
'write the save as path to a string to add to the message
'check for html and use html tags in link
If objMsg.BodyFormat = olFormatHTML Then
strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & Replace(strFile, " ", "%20") & ">"
Else
strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & Replace(strFile, " ", "%20") & ">"
End If
cont:
Next i
' Adds the filename string to the message body and save it
' Check for HTML body
If objMsg.BodyFormat = olFormatHTML Then
objMsg.Body = "The file(s) were saved to " & strDeletedFiles & vbCrLf & objMsg.Body
Else
objMsg.HTMLBody = "The file(s) were saved to " & strDeletedFiles & vbCrLf & objMsg.HTMLBody
End If
objMsg.Save
End If
ExitSub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objOL = Nothing
End Sub
The part in the code which says
If Right(strFile, 4) = ".png" Or Right(strFile, 4) = ".jpg" Or Right(strFile, 4) = ".gif" Then
GoTo cont
you could change to something like:
If objMsg.SenderName = "John Smith" Then
GoTo cont
that way it will only save the attachment from that specific sender.
Then, once you have two or more files, you can load the files using another macro in excel and compare the two files, then send you an email if there are any discrepancies.
Hope that gets you started.
Related
referring to the amazing script found here Save Outlook attachment to disk
I'd like to filter attachments on size. I am using the script for a while now, but the script also saves company logo's etc. This gives numerous 1kb files and changes the mail layout.
I would like the script to ignore files smaller than 10kb. Is there anyone who can help me implement this in the script below;
Public Sub SaveAttachments()
Dim objOL As Outlook.Application
Dim pobjMsg As Outlook.MailItem 'Object
Dim objSelection As Outlook.Selection
' Get the path to your My Documents folder
strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
On Error Resume Next
' Instantiate an Outlook Application object.
Set objOL = CreateObject("Outlook.Application")
' Get the collection of selected objects.
Set objSelection = objOL.ActiveExplorer.Selection
For Each pobjMsg In objSelection
SaveAttachments_Parameter pobjMsg
Next
ExitSub:
Set pobjMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
End Sub
Public Sub SaveAttachments_Parameter(objMsg As MailItem)
Dim objAttachments As Outlook.Attachments
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
' Get the path to your My Documents folder
strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
On Error Resume Next
' Set the Attachment folder.
strFolderpath = "\\path\"
' Get the Attachments collection of the item.
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
If lngCount > 0 Then
' We need to use a count down loop for removing items
' from a collection. Otherwise, the loop counter gets
' confused and only every other item is removed.
For i = lngCount To 1 Step -1
' Save attachment before deleting from item.
' Get the file name.
strFile = objAttachments.Item(i).FileName
'=======================================================
tempstr = strFile 'strtoclean
charArray = Array("?", "/", "\", ":", "*", """", "<", ">", ",", "&", "#", "~", "%", "{", "}", "+", "_")
For Each tmpChar In charArray
Select Case tmpChar
Case "&"
changeTo = " and "
Case ":"
changeTo = "-"
Case Else
changeTo = " "
End Select
tempstr = Replace(tempstr, tmpChar, changeTo)
Next
strFile = tempstr
'==========================================================
' Combine with the path to the Temp folder.
strFile = strFolderpath & Format(objMsg.ReceivedTime, "yyyy-MM-dd h-mm-ss") & "." & strFile
' Save the attachment as a file.
objAttachments.Item(i).SaveAsFile strFile
' Delete the attachment.
objAttachments.Item(i).Delete
'write the save as path to a string to add to the message
'check for html and use html tags in link
If objMsg.BodyFormat <> olFormatHTML Then
strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
Else
strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & strFile & "'>" & strFile & "</a>"
End If
Next i
End If
' Adds the filename string to the message body and save it
' Check for HTML body
If objMsg.BodyFormat <> olFormatHTML Then
objMsg.Body = objMsg.Body & vbCrLf & _
"The file(s) were saved to " & strDeletedFiles
Else
objMsg.HTMLBody = objMsg.HTMLBody & "" & _
"The file(s) were saved to " & strDeletedFiles & ""
End If
objMsg.Save
ExitSub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objOL = Nothing
End Sub
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
End Sub
There is the Attachment.Size property which might help.
You can do
For i = lngCount To 1 Step -1
if objAttachments.Item(i).Size >= 10240 then
...
end if
Next i
I've spent a couple of weeks playing with VBA, I am not by any means an expert on this.
What I'm looking for is a modification of this code.
Public Sub SaveAttachments()
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem 'Object
Dim objAttachments As Outlook.Attachments
Dim objSelection As Outlook.Selection
Dim i As Integer
Dim lngCount As Integer
Dim strFile As String
Dim strFolderpath As String
Dim strFileName As String
Dim objSubject As String
Dim strDeletedFiles As String
' Get the path to your My Documents folder
'strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
On Error Resume Next
' Instantiate an Outlook Application object.
Set objOL = CreateObject("Outlook.Application")
' Get the collection of selected objects.
Set objSelection = objOL.ActiveExplorer.Selection
' The attachment folder needs to exist
' You can change this to another folder name of your choice
' Set the Attachment folder.
strFolderpath = "C:\Users\demkep\Documents\"
' Check each selected item for attachments.
For Each objMsg In objSelection
'Set FileName to Subject
objSubject = objMsg.Subject
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
If lngCount > 0 Then
' Use a count down loop for removing items
' from a collection. Otherwise, the loop counter gets
' confused and only every other item is removed.
For i = lngCount To 1 Step -1
' Get the file name.
strFileName = objSubject & ".pdf"
' Combine with the path to the Temp folder.
strFile = strFolderpath & strFileName
Debug.Print strFile
' Save the attachment as a file.
objAttachments.Item(i).SaveAsFile strFile
Next i
End If
Next
ExitSub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
End Sub
It is the closest to what I am trying to accomplish.
However when I get an email with multiple attachments, it will simply overwrite the last file. if possible. I'd like it to save (sometimes up to 30 .pdf files) as "emailsubject, emailsubject(1), emailsubject(2), emailsubject(3)" etc...
any help would be appreciated.
You are not changing the filename within the loop. Something like
strFileName = objSubject & "(" & i & ").pdf"
should take care of that.
If you only want numbers if there is more than one attachment you can check lngCount before setting the name or use IIf
If lngCount > 1 Then
strFileName = objSubject & "(" & i & ").pdf"
Else
strFileName = objSubject & ".pdf"
End If
Or
strFileName = objSubject & IIf(lngCount>1, "(" & i & ")", "") & ".pdf"
You shouldn't use On Error Resume Next on your whole sub btw.
Here is Function that will do exactly what you need
Function UniqueName(FilePath As String) As String
Dim FSO As Object
Set FSO = CreateObject("Scripting.FilesystemObject")
Dim FileName As String
FileName = FilePath
Dim Ext As String
Ext = Chr(46) & FSO.GetExtensionName(FilePath)
Dim i As Long
i = 1
Do While FSO.FileExists(FileName)
FileName = Left(FilePath, Len(FilePath) - Len(Ext)) & " (" & i & ")" & Ext
i = i + 1
Loop
UniqueName = FileName
End Function
And change this strFile = strFolderpath & strFileName To strFile = UniqueName(strFolderpath & strFileName)
I'm trying to create a macro where I can save the attachments from an email. The problem I'm currently having is that I want the macro to add the ReceivedTime of the email on the file name it saves (i.e.: File TESTSHEET.xls was received on 2016-01-01 3:02AM. I want the saved file to show 201601010302AM-TESTSHEET.xls or something similar)
Here's my current code:
Public itm As Object
Public Sub saveAttachtoDisk()
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
saveFolder = "C:\Users\Username\Documents\TEST REPORTS"
For Each objAtt In itm.Attachments
objAtt.SaveAsFile objAtt.DisplayName
Next objAtt
End Sub
Public Sub SaveAttachments()
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem 'Object
Dim objAttachments As Outlook.Attachments
Dim objSelection As Outlook.Selection
Dim objDate As String
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim StrDate As String
Dim strFolderpath As String
Dim strDeletedFiles As String
Set itm = Application.CreateItem(olMailItem)
Dim CurrentMsg As Outlook.MailItem
' Get the path to your My Documents folder
strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
On Error Resume Next
' Instantiate an Outlook Application object.
Set objOL = CreateObject("Outlook.Application")
' Get the collection of selected objects.
Set objSelection = objOL.ActiveExplorer.Selection
' Set the Attachment folder.
strFolderpath = strFolderpath & "\TEST REPORTS\"
' Check each selected item for attachments. If attachments exist,
' save them to the strFolderPath folder and strip them from the item.
For Each objMsg In objSelection
' This code only strips attachments from mail items.
' If objMsg.class=olMail Then
' Get the Attachments collection of the item.
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
strDeletedFiles = ""
If lngCount > 0 Then
' We need to use a count down loop for removing items
' from a collection. Otherwise, the loop counter gets
' confused and only every other item is removed.
For i = lngCount To 1 Step -1
' Save attachment before deleting from item.
' Get the file name.
strFile = objAttachments.Item(i).FileName
' Combine with the path to the Save folder.
StrDate = Format(itm.ReceivedTime, "yyyy-mm-dd Hmm ")
strFile = strFolderpath & StrDate & strFile
' Save the attachment as a file.
MsgBox strFile
objAttachments.Item(i).SaveAsFile strFile
' Delete the attachment.
objAttachments.Item(i).Delete
'write the save as path to a string to add to the message
'check for html and use html tags in link
If objMsg.BodyFormat <> olFormatHTML Then
strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
Else
strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & _
strFile & "'>" & strFile & "</a>"
End If
'Use the MsgBox command to troubleshoot. Remove it from the final code.
'MsgBox strDeletedFiles
Next i
' Adds the filename string to the message body and save it
' Check for HTML body
If objMsg.BodyFormat <> olFormatHTML Then
objMsg.Body = vbCrLf & "The file(s) were saved to " & strDeletedFiles & vbCrLf & objMsg.Body
Else
objMsg.HTMLBody = "<p>" & "The file(s) were saved to " & strDeletedFiles & "</p>" & objMsg.HTMLBody
End If
objMsg.Save
End If
Next
ExitSub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
End Sub
Thank you in advance for your help!!
Use objMsg not itm.
' StrDate = Format(itm.ReceivedTime, "yyyy-mm-dd Hmm ")
StrDate = Format(objMsg.ReceivedTime, "yyyy-mm-dd Hmm ")
Additionally drop other code with itm and as well objOL
' Set itm = Application.CreateItem(olMailItem)
' Dim CurrentMsg As Outlook.MailItem
' On Error Resume Next
' Instantiate an Outlook Application object.
' Set objOL = CreateObject("Outlook.Application")
Do not use On Error Resume Next until you know what you are doing.
I found numerous examples of VBA scripts to automatically move attachments to my hard drive. This one I've found online works when I run the macro in Outlook as is, but will not work when I set it to a rule.
When I run the macro without the "item as outlook.mailitem" parameter in the sub header and have the email containing the file I want saved selected, it will function properly.
However, as soon as I add that information so I can run it as a rule, outlook throws an error and it disables the rule.
Option Explicit
Public Sub moveAttachmentsAlpha(item As Outlook.MailItem)
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem 'Object
Dim objAttachments As Outlook.Attachments
Dim objSelection As Outlook.Selection
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
' Get the path to your My Documents folder
strFolderpath = "C:\DailyFlash\"
On Error Resume Next
' Instantiate an Outlook Application object.
Set objOL = CreateObject("Outlook.Application")
' Get the collection of selected objects.
Set objSelection = objOL.ActiveExplorer.Selection
' Check each selected item for attachments. If attachments exist,
' save them to the strFolderPath folder and strip them from the item.
For Each objMsg In objSelection
' This code only strips attachments from mail items.
' If objMsg.class=olMail Then
' Get the Attachments collection of the item.
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
strDeletedFiles = ""
If lngCount > 0 Then
' We need to use a count down loop for removing items
' from a collection. Otherwise, the loop counter gets
' confused and only every other item is removed.
For i = lngCount To 1 Step -1
' Save attachment before deleting from item.
' Get the file name.
strFile = objAttachments.item(i).FileName
' Combine with the path to the Temp folder.
strFile = strFolderpath & strFile
' Save the attachment as a file.
objAttachments.item(i).SaveAsFile strFile
'write the save as path to a string to add to the message
'check for html and use html tags in link
If objMsg.BodyFormat <> olFormatHTML Then
strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
Else
strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & _
strFile & "'>" & strFile & "</a>"
End If
'Use the MsgBox command to troubleshoot. Remove it from the final code.
'MsgBox strDeletedFiles
Next i
' Adds the filename string to the message body and save it
' Check for HTML body
If objMsg.BodyFormat <> olFormatHTML Then
objMsg.Body = vbCrLf & "The file(s) were saved to " & strDeletedFiles & vbCrLf & objMsg.Body
Else
objMsg.HTMLBody = "<p>" & "The file(s) were saved to " & strDeletedFiles & "</p>" & objMsg.HTMLBody
End If
objMsg.Save
End If
Next
ExitSub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
End Sub
Keep most of the script. Remove the reference to Outlook.Selection and the for loop associated to it. Then, in it's place, assign item to objMsg to allow the rest of the of the script to function as normal. After testing I have decided to steal it and use it myself as well.
Public Sub moveAttachmentsAlpha(item As Outlook.MailItem)
Dim objMsg As Outlook.MailItem 'Object
Dim objAttachments As Outlook.Attachments
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
' Get the path to your My Documents folder
strFolderpath = "C:\temp\"
On Error Resume Next
Set objMsg = item
' This code only strips attachments from mail items.
' If objMsg.class=olMail Then
' Get the Attachments collection of the item.
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
strDeletedFiles = ""
If lngCount > 0 Then
' We need to use a count down loop for removing items
' from a collection. Otherwise, the loop counter gets
' confused and only every other item is removed.
For i = lngCount To 1 Step -1
' Save attachment before deleting from item.
' Get the file name.
strFile = objAttachments.item(i).FileName
' Combine with the path to the Temp folder.
strFile = strFolderpath & strFile
' Save the attachment as a file.
objAttachments.item(i).SaveAsFile strFile
'write the save as path to a string to add to the message
'check for html and use html tags in link
If objMsg.BodyFormat <> olFormatHTML Then
strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
Else
strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & _
strFile & "'>" & strFile & "</a>"
End If
Next i
' Adds the filename string to the message body and save it
' Check for HTML body
If objMsg.BodyFormat <> olFormatHTML Then
objMsg.Body = vbCrLf & "The file(s) were saved to " & strDeletedFiles & vbCrLf & objMsg.Body
Else
objMsg.HTMLBody = "<p>" & "The file(s) were saved to " & strDeletedFiles & "</p>" & objMsg.HTMLBody
End If
objMsg.Save
End If
ExitSub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
End Sub
FYI: I changed nothing after the line ' This code only strips attachments from mail items. Except for a Next
I changed some codes for getting selected messages attachments to my hard drive like below :
Public Sub SaveAttachments()
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem 'Object
Dim objAttachments As Outlook.Attachments
Dim objSelection As Outlook.Selection
Dim I As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
Dim Counter As Long
strFolderpath = "D:\attachments"
If (Dir$(strFolderpath, vbDirectory) = "") Then
MsgBox "'" & strFolderpath & "' not exist"
MkDir strFolderpath
MsgBox "'" & strFolderpath & "' we create it"
Else
MsgBox "'" & strFolderpath & "' exist"
End If
' Get the path to your My Documents folder
'strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
strFolderpath = strFolderpath & "\"
On Error Resume Next
' Instantiate an Outlook Application object.
Set objOL = CreateObject("Outlook.Application")
' Get the collection of selected objects.
Set objSelection = objOL.ActiveExplorer.Selection
' The attachment folder needs to exist
' You can change this to another folder name of your choice
' Set the Attachment folder.
strFolderpath = strFolderpath
' Check each selected item for attachments.
Counter = 1
For Each objMsg In objSelection
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
If lngCount > 0 Then
' Use a count down loop for removing items
' from a collection. Otherwise, the loop counter gets
' confused and only every other item is removed.
For I = lngCount To 1 Step -1
' Get the file name.
strFile = objAttachments.Item(I).FileName
' Combine with the path to the Temp folder.
strFile = strFolderpath & Counter & "_" & strFile
' Save the attachment as a file.
objAttachments.Item(I).SaveAsFile strFile
Counter = Counter + 1
Next I
End If
Next
ExitSub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
MsgBox "All Selected Attachments Have Been Downloaded ..."
End Sub
my goal email uses imap service...
this vb codes works perfect!
but my problem is when download is finished we have not All needed files in attachments folder! (just some of them are there)
I have 450 UNREAD emails in my inbox that all of them have attachmen/s...
but we only have 200 files in attachments folder! (created by upper codes)
how can I fix this issue?
it seems this problem is in relationship with Unread Messages And My ADSL speed (but it should n't , I don't know?!)
when u read an email it seems Outlook does some stuff with that email and so next time that email runs faster because of it's caching.
how can I do this job for my unread emails with upper codes?
or is there any idea about this problem?
at last I would be really appreciate
for review and add or correct my codes
EDITION After comments :
my new code is like below :
Public Sub SaveAttachments()
Dim OlApp As Outlook.Application
Dim Inbox As MAPIFolder
Dim Item As Object
Dim ItemAttachments As Outlook.Attachments
Dim ItemAttachment As Object
Dim ItemAttCount As Long
Dim strFolderpath As String
Dim strFileName As String
Dim Counter As Long
Dim ItemsCount As Long
Dim ItemsAttachmentsCount As Long
strFolderpath = "d:\attachments"
If (Dir$(strFolderpath, vbDirectory) = "") Then
MsgBox "'" & strFolderpath & "' not exist"
MkDir strFolderpath
MsgBox "'" & strFolderpath & "' we create it"
Else
MsgBox "'" & strFolderpath & "' exist"
End If
' Get the path to your My Documents folder
'strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
strFolderpath = strFolderpath & "\"
'On Error Resume Next
' Instantiate an Outlook Application object.
Set OlApp = CreateObject("Outlook.Application")
Set Inbox = OlApp.ActiveExplorer.CurrentFolder
Counter = 1
ItemsCount = 0
ItemsAttachmentsCount = 0
For Each Item In Inbox.Items
ItemsCount = ItemsCount + 1
For Each ItemAttachment In Item.Attachments
ItemsAttachmentsCount = ItemsAttachmentsCount + 1
' Get the file name.
strFileName = ItemAttachment.FileName
' Combine with the path to the Attachments folder.
strFileName = strFolderpath & Counter & "_" & strFileName
' Save the attachment as a file.
ItemAttachment.SaveAsFile strFileName
Counter = Counter + 1
Next ItemAttachment
Next Item
ExitSub:
Set ItemAttachment = Nothing
Set ItemAttachments = Nothing
Set Item = Nothing
Set Inbox = Nothing
Set OlApp = Nothing
MsgBox "All Selected Folder Attachments Have Been Downloaded ..."
MsgBox "ItemsCount : " & ItemsCount
MsgBox "ItemsAttachmentsCount : " & ItemsAttachmentsCount
End Sub
but the previous problem is still there
all of my emails in inbox(SELECTED FOLDER FOR UPPER CODE) are 455 (5 Read + 450 Unread)
MsgBox "ItemsCount : " & ItemsCount returns -> 455
MsgBox "Sum Of All ItemAttCount : " & ItemsAttachmentsCount returns 200 or a bit more
any idea?
A possible problem is that not all your messages are selected in the explorer. Your code requires the messages to be selected in the current Outlook explorer window.
Try printing the count of selected e-mails:
Set objSelection = Application.ActiveExplorer.Selection
Debug.Print objSelection.Count
If the result (visible in the debug window) is not 450, then not all your 450 messages are selected, and that's why some of them are ignored.
EDIT: According to your updated question, the code correctly finds all the e-mail messages, but only some of the attachments. This calls for some good old-fashioned debugging, beyond what can be answered on this website.
Try Debug.Print Item.Attachments.Count at the beginning of the For Each Item... loop. Is the attachment count sometimes zero? For which messages is it zero?
EDIT 2: You speculate that there is some kind of caching of attachment for opened mails. To test this (and to solve the problem if this is indeed the issue), you could open the mail items before saving the attachments (and then close the mail item when done). This can be done like this:
For Each Item In Inbox.Items
' Open the mail item
Item.Display
' Your code to save the attachments goes here.
' Close the mail item
Item.Close olDiscard
Next Item