The Excel code below is designed to go to a webpage, search a hyperlink and download PDF file under it and save it on desktop.
I need to amend it for Outlook:
So that it detects a Sender email, e.g. generic#gmail.com
Detect the hyperlink in the email and on the webpage to detect a button 'Export Details' and press it
Then on next page press 'Export' button and save CVS file on Desktop: "C:\Users\mlad1406\Desktop\Test".
Sub DownPDF()
' This macro downloads the pdf file from webpage
' Need to download MSXML2 and MSHTML parsers and install
Dim sUrl As String
Dim xHttp As MSXML2.XMLHTTP
Dim hDoc As MSHTML.HTMLDocument
Dim hAnchor As MSHTML.HTMLAnchorElement
Dim Ret As Long
Dim sPath As String
Dim i As Long
sPath = "C:\Users\mlad1406\Desktop\Test"
sUrl = "https://copernicus.my.salesforce.com/00O20000006WD95"
'Get the directory listing
Set xHttp = New MSXML2.XMLHTTP
xHttp.Open "GET", sUrl
xHttp.Send
'Wait for the page to load
Do Until xHttp.readyState = 4
DoEvents
Loop
'Put the page in an HTML document
Set hDoc = New MSHTML.HTMLDocument
hDoc.Body.innerHTML = xHttp.responseText
'Loop through the hyperlinks on the directory listing
For i = 0 To hDoc.getElementsByTagName("a").Length - 1
Set hAnchor = hDoc.getElementsByTagName("a").Item(i)
'test the pathname to see if it matches your pattern
If hAnchor.PathName Like "Ordin-*.2013.pdf" Then
Ret = UrlDownloadToFile(0, sUrl & hAnchor.PathName, sPath, 0, 0)
If Ret = 0 Then
Debug.Print sUrl & hAnchor.PathName & " downloaded to " & sPath
Else
Debug.Print sUrl & hAnchor.PathName & " not downloaded"
End If
End If
Next i
End Sub
Here is some code, that should help you to start (if you do look in mails to find the sender address) :
The field you are looking for is : oMailItem.SenderEmailAddress
Sub Extract_Body_Subject_From_Mails()
Dim oNS As Outlook.NameSpace
Dim oFld As Outlook.Folder
Dim oMails As Outlook.Items
Dim oMailItem As Outlook.MailItem
Dim oProp As Outlook.PropertyPage
Dim sSubject As String
Dim sBody
'On Error GoTo Err_OL
Set oNS = Application.GetNamespace("MAPI")
Set oFld = oNS.GetDefaultFolder(olFolderInbox)
Set oMails = oFld.Items
For Each oMailItem In oMails
MsgBox oMailItem.SenderEmailAddress
'MsgBox oMails.Count 'oMails.Item(omails.Find(
sBody = oMailItem.Body
sSubject = oMailItem.Subject
'MsgBox sSubject
MsgBox sBody
Next
Exit Sub
Err_OL:
If Err <> 0 Then
MsgBox Err.Number & " - " & Err.Description
Err.Clear
Resume Next
End If
End Sub
'First create a rule that looks at the subject of incoming messages and fires when it sees "A new incident". Have the rule run a script. I called mine "Check_For_Ticket" in this example. See the pic of my rule attached.
Sub Check_For_Ticket(MyMail As MailItem)
On Error GoTo Proc_Error
Dim strTicket, strSubject As String
' Default value in case # is not found in the subject line
strTicket = "None"
' Grab the subject from the message
strSubject = MyMail.Subject
' See if it has a hash symbol in it
If InStr(1, strSubject, "#") > 0 Then
' Trim off leading stuff up to and including the hash symbol
strSubject = Mid(strSubject, InStr(strSubject, "#") + 1)
' Now find the trailing space after the ticket number and chop it off after that
If InStr(strSubject, " ") > 0 Then
strTicket = Left(strSubject, InStr(strSubject, " ") - 1)
End If
End If
MsgBox "Your Ticket # is: " & strTicket
Proc_Done:
Exit Sub
Proc_Error:
MsgBox "An error has occured in Check_For_Ticket. Error #" & Err & " - " & Err.Description
GoTo Proc_Done
End Sub
'Of course, you would substitute whatever processing you want where the messagebox shows the ticket number.
Related
I'm completely new to VB and I'm trying to extract the attachment which is saved available inside the .msg file using the below code.
Could someone help me if this is the right approach to do this ?
I'm facing below compiler errors. Could someone help me how to resolve this issue ?
Outlook.Attachment is not defined.
End Sub' must be preceded by a matching 'Sub'
Reference to a non-shared member requires an object reference.
Statement cannot appear within a method body. End of method assumed
Method arguments must be enclosed in parentheses.
Type 'Outlook.MailItem' is not defined.
Sub SaveOlAttachments()
Dim msg As Outlook.MailItem
Dim att As Outlook.Attachment
Dim strFilePath As String
Dim strAttPath As String
Dim strFile As String
strFilePath = "C:\Users\...\Desktop\Test\"
strAttPath = "C:\Users\...\extracted attachment\"
strFile = Dir(strFilePath & "<Doc Name>.msg")
Do While Len(strFile) > 0
msg = Application.CreateItemFromTemplate(strFilePath & strFile)
If msg.Attachments.Count > 0 Then
For Each att In msg.Attachments
att.SaveAsFile strAttPath & att.FileName
Next
End If
strFile = Dir
Loop
End Sub
First of all, check out the file path where you try to find the template:
msg = Application.CreateItemFromTemplate(strFilePath & strFile)
The strFilePath string may include the file name already:
strFile = Dir(strFilePath & "<Doc Name>.msg")
Second, make sure attachments are saved using unique file names:
att.SaveAsFile strAttPath & att.FileName
The FileName string can be the same in different emails. I'd recommend adding IDs or the current time and etc. to the file name to uniquely name attached files on the disk.
Here is the code we use to grab a daily report attachment. I left a few commented statements in case you might need them (we didn't).
Sub Extract_Outlook_Email_Attachments()
On Error GoTo ErrHandler
Dim OutlookApp As Outlook.Application
Dim OutlookNamespace As Namespace
Dim folder As MAPIFolder
Dim OutlookMail As Variant
Dim i As Integer
Dim olNS As Outlook.Namespace
Dim objOwner As Outlook.Recipient
Set OutlookApp = New Outlook.Application
Set OutlookNamespace = OutlookApp.GetNamespace("MAPI")
Dim saveFolder As String
saveFolder = strAttPath ' SAVE THE ATTACHMENT TO
'this bit is added to get a shared email
Set objOwner = OutlookNamespace.CreateRecipient("SHARED FOLDER NAME")
objOwner.Resolve
If objOwner.Resolved Then
Debug.Print "Outlook GB Fulfillment is good."
Set folder = OutlookNamespace.GetSharedDefaultFolder(objOwner, olFolderInbox) 'can use olFolderInbox or olFolderSentMail
End If
'Write mail to spreadsheet - create named range, from and to dates on the spreadsheet
i = 1
For Each OutlookMail In folder.Items
' Debug.Print "SenderEmailAddress: " & OutlookMail.SenderEmailAddress
'If OutlookMail.SenderEmailAddress = "no-reply#OurCompany.com" Then
If OutlookMail.subject = "Daily Report" Then
' If OutlookMail.SenderName = "no-reply#OurCompany.com" And OutlookMail.Subject = "Daily New Subscriber Plan Election Fulfillment" And OutlookMail.Attachments(1) = "NewSubscriberPlanElectionFulfillment_Subscription.xls" Then
Debug.Print "Received: " & OutlookMail.ReceivedTime
Debug.Print "Attach: " & OutlookMail.Attachments(1)
dateformat = Format(OutlookMail.ReceivedTime, "m-d-yy")
Debug.Print dateformat
FName = dateformat & " " & OutlookMail.Attachments(1).fileName
Debug.Print "FName: " & FName
Dim strFileExists As String
strFileExists = Dir(saveFolder & FName)
If strFileExists = "" Then
' MsgBox "The selected file doesn't exist"
Else
' MsgBox "The selected file exists"
Exit Sub
End If
OutlookMail.Attachments(1).SaveAsFile saveFolder & FName
Set outAttachment = Nothing
End If
Next OutlookMail
Set folder = Nothing
Set OutlookNamespace = Nothing
Set OutlookApp = Nothing
ErrHandler:
Debug.Print Err.Description
End Sub
Instead of using CreateItemFromTemplate, you can use Namespace.OpenSharedItem to open an MSG file.
You also need to add Outlook to your VB.Net project references.
I've got this block of code to go through all the emails in my "Today" folder in Outlook, then save all the emails (.msg) to a folder named as the sender name.
Sometimes the files are saving with the file type "file".
How do I fix this to make sure the emails are saved as .msg files?
Sub SaveAttachments()
'https://www.fontstuff.com/outlook/oltut01.htm
'Declare Variables
Dim ns As NameSpace
Dim Inbox As Outlook.MAPIFolder
Dim Item As Object
Dim Atmt As Attachment
Dim Savefolder As String
Dim i As Integer
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox).Folders("Today")
i = 0
'Stop script if there are no emails
If Inbox.Items.Count = 0 Then
MsgBox "There are no messages in the Inbox.", vbInformation, "Nothing Found"
Exit Sub
End If
'Display the number of emails
MsgBox Inbox.Items.Count, vbInformation, _
"Number of Emails?"
'Go through each email
For Each Item In Inbox.Items
'Create a path for the save folder
Savefolder = "C:\Users\work\Desktop\22_11_18\Test\" & Item.SenderName
'If the email has attachments, then create a folder
If Item.Attachments.Count > 0 Then
MkDir Savefolder
'If the folder already exists, skip to the next statement
On Error Resume Next
'Save the email as a .msg file
Item.SaveAs Savefolder & "\" & Item.Subject & ".msg"
End If
Next Item
End Sub
You can use subject if the characters in the subject are all valid.
Option Explicit
Private Sub SaveMail_ContainingAttachments_ValidSubject()
'Declare Variables
Dim ns As Namespace
Dim targetFolder As Folder
Dim itm As Object
Dim atmt As Attachment
Dim strSaveFolder As String
Dim validSubject As String
Set ns = GetNamespace("MAPI")
Set targetFolder = ns.GetDefaultFolder(olFolderInbox)
Set targetFolder = targetFolder.Folders("Today")
'Stop script if there are no emails
If targetFolder.Items.count = 0 Then
MsgBox "There are no messages in " & targetFolder & ".", vbInformation, "Nothing Found"
Exit Sub
End If
'Display the number of emails
MsgBox targetFolder.Items.count, vbInformation, "Number of Emails?"
'Go through each email
For Each itm In targetFolder.Items
'If the email has attachments, then create a folder
If itm.Attachments.count > 0 Then
'Create a path for the save folder
strSaveFolder = "C:\Users\work\Desktop\22_11_18\Test\" & itm.senderName
' Bypass error if the folder already exists
On Error Resume Next
MkDir strSaveFolder
' Discontinue error bypass as soon as the purpose is served
' Let unknown errors generate then fix them
On Error GoTo 0
' Replace or remove invalid characters
' Possible options "_" or " " or "" ....
validSubject = ReplaceIllegalChar(itm.subject, "_")
If validSubject <> itm.subject Then
Debug.Print itm.subject
Debug.Print validSubject
End If
'Save the email as a .msg file
itm.SaveAs strSaveFolder & "\" & validSubject & ".msg"
End If
Next itm
End Sub
Private Function ReplaceIllegalChar(strInput, strReplace)
Dim RegX As Object
Set RegX = CreateObject("vbscript.regexp")
RegX.Pattern = "[\" & Chr(34) & "\!\#\#\$\%\^\&\*\(\)\=\+\|\[\]\{\}\`\'\;\:\<\>\?\/\,]"
RegX.IgnoreCase = True
RegX.Global = True
' Replace with another string
ReplaceIllegalChar = RegX.Replace(strInput, strReplace)
ExitFunction:
Set RegX = Nothing
End Function
I take emails a user selects and then save them as text files, with the name of the text file as a portion of the subject line and then move that email to another folder in Outlook.
I managed to get all that working, but I also want the code to leave anything with two trip numbers in the subject line (Signified as Trip#XXXXXXXXX) alone and not move it, instead moving to the next selected email.
Exit Sub is a hard stop and I want to loop through the rest of the selection. Next oMail is something I'm only allowed one of and need at the end and GoTo that location skipping the rest of the code doesn't help.
Should I be using something other than For Each oMail In Application.ActiveExplorer.Selection?
The whole thing is as follows:
Sub SaveSentEmailAsParsedSubjectAndMove()
Dim oMail As Outlook.MailItem
'Folder path and file name
Dim strDesktop As String, strFileName As String, strFolderPath As String
'Four letters at the start of a trip/PAPS/PARS and the number itself
Dim strSCAC As String, strTripNumber As String
'Trip number counter
Dim strSubject As String, strSubject2 As String
Dim intTrips As Integer, intTrips1 As Integer, intTrips2 As Integer
'Duplicate checker
'Dim strTestStr As String, strTestPath As String
Dim strVersion As String, strVersionCheck As String
'File saved counter
Dim intFilesSaved As Integer
intFilesSaved = 0
'X carries the value for the file name, trying to save one higher in the event of a duplicate
Dim x As Integer
'Creates a text file on the desktop that will have all saved trip numbers written into it for the day.
Dim objFSO As Object
'Dim objFSO As New FileSystemObject
Dim objDailyLog As Object
'Dim objDailyLog As TextStream
Dim strTextFilePath As String
Dim strTextFilePathTest As String
'Constants for reading/writing to the daily log file - Appending adds data to the end.
'For Reading = 1
'For Writing = 2
'For Appending = 8
'Variables for the timers
'Daily log save time timer
Dim sngStart As Single, sngEnd As Single, sngElapsed As Single
Dim sngStart2 As Single, sngEnd2 As Single, sngElapsed2 As Single
If ActiveExplorer.Selection.Count = 0 Then
MsgBox "No files selected"
Exit Sub
End If
'Start timer
sngStart = Timer
sngStart2 = Timer
1
x = 1
'Set folder path - This will have to change to the J daily fax for release - J:\Fax Confirmations Daily
strDesktop = Environ("userprofile")
strFolderPath = strDesktop & "\Desktop\Test Folder\"
If Len(Dir(strFolderPath)) = 0 Then
MkDir strFolderPath
Else
End If
'strFolderPath = "J:\Fax Confirmations Daily\"
'Sets the path to create the record keeping text file in.
strTextFilePath = strDesktop & "\Desktop\" & Month(Date) & " " & Day(Date) & " Saved Faxes.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Len(Dir(strTextFilePath)) = 0 Then
'MsgBox "File does NOT exist"
Set objDailyLog = objFSO.CreateTextFile(strTextFilePath)
objDailyLog.Close
Else
'MsgBox "File already exists"
End If
'This will save all emails selected
For Each oMail In Application.ActiveExplorer.Selection
'Gets the subject line of the mail item
strSubject = oMail.Subject
'Gets the SCAC code from the subject line, the first four characters counting from left
strSCAC = strSubject
strSCAC = Left(strSCAC, 4)
'Counter. Stops process and returns error if there is more than one trip number detected.
strSubject2 = oMail.Subject
strSubject2 = Replace(strSubject2, "#", "")
intTrips1 = Len(strSubject)
intTrips2 = Len(strSubject2)
intTrips = intTrips1 - intTrips2
If intTrips > 1 Then
MsgBox "You have selected an email with more than one trip number in the subject. Please only select messages with a single trip number. Thanks.", 0, "Multiple Trip Numbers Detected"
GoTo 3
'Exit Sub
Else
'Gets the trip number, hereby defined as everything to the RIGHT of the # in the subject line
strTripNumber = strSubject
strTripNumber = Mid(strSubject, InStr(strSubject, "#") + 1)
'Set the File name
strVersion = ""
strFileName = strSCAC & strTripNumber & strVersion
2
'Test if file name exists. If yes, increase version number by 1 and try again.
'If no, save and continue processing.
If Len(Dir(strFolderPath & strFileName & " Sent" & strVersion & ".txt")) = 0 Then
'Save the text file with the completed file name to the previously defined folder
oMail.SaveAs strFolderPath & strFileName & " Sent" & strVersion & ".txt", olTXT
intFilesSaved = intFilesSaved + 1
'Open daily log file for addending (do not overwrite current data, merely add new lines to bottom)
Set objDailyLog = objFSO.OpenTextFile(strTextFilePath, 8, True)
objDailyLog.WriteLine (strFileName & " " & strVersion)
'Close the daily log text file
objDailyLog.Close
Else
'If the file already exists, increase the version counter by 1 and try again.
x = x + 1
strVersion = " " & x
GoTo 2
End If
End If
x = 1
'MoveToBackup
3
Next oMail
If intTrips > 1 Then
Set objDailyLog = objFSO.OpenTextFile(strTextFilePath, 8, True)
objDailyLog.WriteLine (Time)
objDailyLog.WriteLine "Saved in " & sngElapsed & " seconds"
objDailyLog.WriteLine "Error detected: Multiple trip numbers in subject line!"
objDailyLog.WriteBlankLines (1)
objDailyLog.Close
sngEnd2 = Timer
sngElapsed2 = Format(sngEnd2 - sngStart2, "Fixed")
MsgBox intFilesSaved & " file(s) saved successfully" & " in " & sngElapsed2 & " seconds", 0, "Files Saved"
intTrips = 0
Else
MoveToBackup
sngEnd = Timer
sngElapsed = Format(sngEnd - sngStart, "Fixed")
Set objDailyLog = objFSO.OpenTextFile(strTextFilePath, 8, True)
objDailyLog.WriteLine (Time)
objDailyLog.WriteLine "Saved in " & sngElapsed & " seconds"
objDailyLog.WriteBlankLines (1)
objDailyLog.Close
sngEnd2 = Timer
sngElapsed2 = Format(sngEnd2 - sngStart2, "Fixed")
MsgBox intFilesSaved & " file(s) saved successfully" & " in " & sngElapsed2 & " seconds", 0, "Files Saved"
End If
End Sub
'Outlook VB Macro to move selected mail item(s) to a target folder
Sub MoveToBackup()
On Error Resume Next
Dim ns As Outlook.NameSpace
Dim moveToFolder As Outlook.MAPIFolder
Dim objItem As Outlook.MailItem
Set ns = Application.GetNamespace("MAPI")
'Define path to the target folder - this was the original code,
Set moveToFolder = ns.GetDefaultFolder(olFolderSentMail).Folders("Backup")
If Application.ActiveExplorer.Selection.Count = 0 Then
MsgBox ("No item selected")
Exit Sub
End If
If moveToFolder Is Nothing Then
MsgBox "Target folder not found!", vbOKOnly + vbExclamation, "Move Macro Error"
End If
For Each objItem In Application.ActiveExplorer.Selection
If moveToFolder.DefaultItemType = olMailItem Then
If objItem.Class = olMail Then
objItem.Move moveToFolder
End If
End If
Next
Set objItem = Nothing
Set moveToFolder = Nothing
Set ns = Nothing
End Sub
You are already dropping items from the selection with
If intTrips > 1 Then
but later you move all mail in the selection.
You could move validated mail immediately.
Sub MoveValidatedMail()
Dim oMail As mailItem
'Four letters at the start of a trip/PAPS/PARS and the number itself
Dim strSCAC As String, strTripNumber As String
'Trip number counter
Dim strSubject As String, strSubject2 As String
Dim intTrips As Integer, intTrips1 As Integer, intTrips2 As Integer
'Move vaidated mail one at a time,
' within this code, rather than bulk move all mail
Dim ns As namespace
Dim moveToFolder As Folder
Dim objItem As Object
Set ns = GetNamespace("MAPI")
'Define path to the target folder
' If there is a typo or missing folder there would be an error.
' Bypass this one error only.
On Error Resume Next
Set moveToFolder = ns.GetDefaultFolder(olFolderSentMail).folders("Backup")
On Error GoTo 0
If moveToFolder Is Nothing Then
' Handle the bypassed error, if any
MsgBox "Target folder not found!", vbOKOnly + vbExclamation, "Move Macro Error"
Exit Sub
End If
If moveToFolder.DefaultItemType <> olMailItem Then
MsgBox "DefaultItemType <> olMailItem!", vbOKOnly + vbExclamation, "Move Macro Error"
Exit Sub
End If
If ActiveExplorer.Selection.count = 0 Then
MsgBox "No files selected"
Exit Sub
End If
For Each objItem In ActiveExplorer.Selection
If objItem.Class = olMail Then
Set oMail = objItem
'Gets the subject line of the mail item
strSubject = oMail.subject
'Gets the SCAC code from the subject line,
' the first four characters counting from left
strSCAC = strSubject
strSCAC = Left(strSCAC, 4)
'Counter. Stops process and returns error
' if there is more than one trip number detected.
strSubject2 = oMail.subject
strSubject2 = Replace(strSubject2, "#", "")
intTrips1 = Len(strSubject)
intTrips2 = Len(strSubject2)
intTrips = intTrips1 - intTrips2
If intTrips > 1 Then
MsgBox "Mail not moved " & oMail.subject
Else
' Move validated mail
objItem.move moveToFolder
MsgBox oMail.subject & " moved to " & moveToFolder
End If
End If
Set oMail = Nothing
Next objItem
Set oMail = Nothing
Set objItem = Nothing
Set moveToFolder = Nothing
Set ns = Nothing
End Sub
You could just use like
If oMail.Subject like "*TRIP*TRIP*" Then
I need to move the incoming message to the related folder depending on a key in the subject of the message.
I developed a script for getting the key in the subject of new message. How can I search rest of messages by a key and retrieve related folder?
Sub CustomMailMessageRule(Item As Outlook.MailItem)
Dim strTicket, strSubject As String
Dim strFolder As String
strTicket = "None"
strSubject = Item.Subject
If InStr(1, strSubject, "#-") > 0 Then
strSubject = Mid(strSubject, InStr(strSubject, "#-") + 2)
If InStr(strSubject, " ") > 0 Then
strTicket = Left(strSubject, InStr(strSubject, " ") - 1)
End If
End If
the unknown part, search all folders by key and retrieve the related folder
strFolder = "???"
and finally, move the incoming message to the related folder by below code
If InStr(strFolder) > 0 Then
Item.Move Session.GetDefaultFolder(olFolderInbox).folders(strFolder)
MsgBox "Your New Message has been moved to related folder "
End Sub
I'm new in VBA.
This searches folders recursively for an item by subject.
Option Explicit
Sub CustomMailMessageRule(Item As mailItem)
Dim strSubject As String
Dim strDynamic As String
Dim strFilter As String
Dim originFolder As Folder
Dim startFolder As Folder
Dim uPrompt As String
strSubject = Item.subject
Set startFolder = Session.GetDefaultFolder(olFolderInbox)
' To reference any inbox not specifically the default inbox
'Set startFolder = Session.folders("email address").folders("Inbox")
Set originFolder = startFolder
' For testing the mail subject is "This is a test"
If InStr(1, strSubject, "This is") > 0 Then
' For testing the dynamically determined key is "a test"
strDynamic = "a test"
strFilter = "#SQL=" & Chr(34) & "urn:schemas:httpmail:subject" & Chr(34) & " LIKE '%" & strDynamic & "%'"
Debug.Print strFilter
' Advanced search requires "Scope" to be specified so it appears
' not easy/possible to process every subfolder in the way described here
' https://stackoverflow.com/questions/43638711/outlook-macro-advanced-search
' This recursively processes every subfolder
processFolder originFolder, startFolder, strFilter, Item
uPrompt = "Mail with " & strDynamic & " in subject not found in subfolders of " & startFolder.Name
Debug.Print uPrompt
MsgBox uPrompt
End If
ExitRoutine:
Set startFolder = Nothing
End Sub
Private Sub processFolder(ByVal originFolder As Folder, ByVal oParent As Folder, strFilter As String, oIncomingMail As mailItem)
Dim oFolder As Folder
Dim oObj As Object
Dim filteredItems As items
Dim uResp As VbMsgBoxResult
Debug.Print oParent
If originFolder.EntryID <> oParent.EntryID Then
' This narrows the search.
' https://stackoverflow.com/questions/21549938/vba-search-in-outlook
Set filteredItems = oParent.items.Restrict(strFilter)
If filteredItems.count > 0 Then
Debug.Print oParent
Debug.Print "Mail found in " & oParent.Name
uResp = MsgBox(Prompt:="Move Message to folder: " & oParent.Name & "?", _
Buttons:=vbYesNoCancel)
If uResp = vbYes Then
oIncomingMail.move oParent
End
End If
If uResp = vbCancel Then End
End If
End If
If (oParent.folders.count > 0) Then
For Each oFolder In oParent.folders
processFolder originFolder, oFolder, strFilter, oIncomingMail
Next
End If
End Sub
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.