Excel VBA Code to retrieve e-mails from outlook - excel

I am to write a VBA code that would retrive emails from Outlook based on certain conditions. The problem I have is that I have to denote a certain folder in my code (in the example below the folder denoted is "PRE Costumer". I would like to retrive all emails from my 'inbox' or in better case from all outlook folders. The problem is that my inbox consists of many subfolders (because of rules0. My problem is that I may not know all the subfolders names (as many useres are going to use the macro and even someone can have the e mails in Personal Folders).
Could you please advise is there a way to overcome this problem?
Please let me know if this question is vague (as I am newcomer)
Please find the line that I have probelm with marked with a comment.
Sub GetFromInbox()
Dim olApp As Outlook.Application
Dim olNs As Namespace
Dim Fldr As MAPIFolder
Dim olMail As Variant
Dim i As Integer
Set olApp = New Outlook.Application
Set olNs = olApp.GetNamespace("MAPI")
'Below is the line I have problem with
Set Fldr = olNs.GetDefaultFolder(olFolderInbox).Folders("PRE Customer")
i = 1
x = Date
For Each olMail In Fldr.Items
If InStr(olMail.Subject, "transactions") > 0 _
And InStr(olMail.ReceivedTime, x) > 0 Then
ActiveSheet.Cells(i, 1).Value = olMail.Subject
ActiveSheet.Cells(i, 2).Value = olMail.ReceivedTime
ActiveSheet.Cells(i, 3).Value = olMail.SenderName
i = i + 1
End If
Next olMail
Set Fldr = Nothing
Set olNs = Nothing
Set olApp = Nothing
End Sub

Just loop through all the folders in Inbox.
Something like this would work.
Edit1: This will avoid blank rows.
Sub test()
Dim olApp As Outlook.Application, olNs As Outlook.Namespace
Dim olFolder As Outlook.MAPIFolder, olMail As Outlook.MailItem
Dim eFolder As Outlook.Folder '~~> additional declaration
Dim i As Long
Dim x As Date, ws As Worksheet '~~> declare WS variable instead
Dim lrow As Long '~~> additional declaration
Set ws = Activesheet '~~> or you can be more explicit using the next line
'Set ws = Thisworkbook.Sheets("YourTargetSheet")
Set olApp = New Outlook.Application
Set olNs = olApp.GetNamespace("MAPI")
x = Date
For Each eFolder In olNs.GetDefaultFolder(olFolderInbox).Folders
'Debug.Print eFolder.Name
Set olFolder = olNs.GetDefaultFolder(olFolderInbox).Folders(eFolder.Name)
For i = olFolder.Items.Count To 1 Step -1
If TypeOf olFolder.Items(i) Is MailItem Then
Set olMail = olFolder.Items(i)
If InStr(olMail.Subject, "transactions") > 0 _
And InStr(olMail.ReceivedTime, x) > 0 Then
With ws
lrow = .Range("A" & .Rows.Count).End(xlup).Row
.Range("A" & lrow).Offset(1,0).value = olMail.Subject
.Range("A" & lrow).Offset(1,1).Value = olMail.ReceivedTime
.Range("A" & lrow).Offset(1,2).Value = olMail.SenderName
End With
End If
End If
Next i
Set olFolder = Nothing
Next eFolder
End Sub
Above takes care of all subfolders in Inbox.
Is this what you're trying?

To fix your error (olFolderInbox is a Outlook only constant, so you need to define it in vba that is not Outlook):
Const olFolderInbox = 6
'...
Set Fldr = olNs.GetDefaultFolder(olFolderInbox).Folders("PRE Customer")
Also to prevent missing Reference when run from another computer, I would:
Dim olApp As Object
Dim olNs As Object
Dim Fldr As Object
Dim olMail As Object
Dim i As Long
Set olApp = CreateObject("Outlook.Application")
'...
You might also want to disable ScreenUpdating, then enable it in Excel if you expect a long list.
UPDATE (Solution for all folders from a Root Folder)
I used something slightly different for comparing the dates.
Option Explicit
Private lRow As Long, x As Date, oWS As Worksheet
Sub GetFromInbox()
Const olFolderInbox = 6
Dim olApp As Object, olNs As Object
Dim oRootFldr As Object ' Root folder to start
Dim lCalcMode As Long
Set olApp = CreateObject("Outlook.Application")
Set olNs = olApp.GetNamespace("MAPI")
Set oRootFldr = olNs.GetDefaultFolder(olFolderInbox).Folders("PRE Customer")
Set oWS = ActiveSheet
x = Date
lRow = 1
lCalcMode = Application.Calculation
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
GetFromFolder oRootFldr
Application.ScreenUpdating = True
Application.Calculation = lCalcMode
Set oWS = Nothing
Set oRootFldr = Nothing
Set olNs = Nothing
Set olApp = Nothing
End Sub
Private Sub GetFromFolder(oFldr As Object)
Dim oItem As Object, oSubFldr As Object
' Process all mail items in this folder
For Each oItem In oFldr.Items
If TypeName(oItem) = "MailItem" Then
With oItem
If InStr(1, .Subject, "transactions", vbTextCompare) > 0 And DateDiff("d", .ReceivedTime, x) = 0 Then
oWS.Cells(lRow, 1).Value = .Subject
oWS.Cells(lRow, 2).Value = .ReceivedTime
oWS.Cells(lRow, 3).Value = .SenderName
lRow = lRow + 1
End If
End With
End If
Next
' Recurse all Subfolders
For Each oSubFldr In oFldr.Folders
GetFromFolder oSubFldr
Next
End Sub

Related

How to loop Outlook emails with particular subject line?

I have code that extracts the body of email which has the subject line "Volume data".
Let's say I have 10 emails in my inbox folder which has the subject line "Volume data".
I want to loop through all the emails, find which email has subject line "Volume data" and then extract the email body from those 10 emails.
My code is stopping at the first instance where it finds the mentioned subject.
Option Explicit
Sub impOutlookTable()
Dim wkb As Workbook
Set wkb = ThisWorkbook
Sheets("Sheet1").Cells.ClearContents
' point to the desired email
Const strMail As String = "emailaddress"
Dim oApp As Outlook.Application
Dim oMapi As Outlook.MAPIFolder
Dim oMail As Outlook.MailItem
Dim x As Long, y As Long
Dim destCell As Range
Dim i As Long
Dim oItem As Object
With ActiveSheet
Set destCell = .Cells(Rows.Count, "A").End(xlUp)
End With
On Error Resume Next
Set oApp = GetObject(, "OUTLOOK.APPLICATION")
If (oApp Is Nothing) Then Set oApp = CreateObject("OUTLOOK.APPLICATION")
On Error GoTo 0
Set oMapi = oApp.GetNamespace("MAPI").Folders(strMail).Folders("inbox")
Set oMail = oMapi.Items(oMapi.Items.Count)
For Each oItem In oMapi.Items
If oItem.Subject = "Volume data" Then
Exit For
End If
Next oItem
If Not oItem Is Nothing Then
' get html table from email object
Dim HTMLdoc As MSHTML.HTMLDocument
Dim tables As MSHTML.IHTMLElementCollection
Dim table As MSHTML.HTMLTable
Set HTMLdoc = New MSHTML.HTMLDocument
With HTMLdoc
.Body.innerHTML = oItem.HTMLBody
Set tables = .getElementsByTagName("table")
End With
'import in Excel
For Each table In tables
For x = 0 To table.Rows.Length - 1
For y = 0 To table.Rows(x).Cells.Length - 1
destCell.Offset(x, y).Value = table.Rows(x).Cells(y).innerText
Next y
Next x
Set destCell = destCell.Offset(x)
Next
End If
Set oApp = Nothing
Set oMapi = Nothing
Set oMail = Nothing
Set HTMLdoc = Nothing
Set tables = Nothing
wkb.SaveAs "C:\Users\Desktop\New_email.xlsm"
End Sub
Put all of the "Action" code inside the If statement inside your loop instead of after it, and then remove the Exit For.
You will also need a counter or something so that you aren't just saving overtop of the same file for each iteration.
UNTESTED
Option Explicit
Sub impOutlookTable()
Dim iCounter As Integer
iCounter = 1
Dim wkb As Workbook
Set wkb = ThisWorkbook
Sheets("Sheet1").Cells.ClearContents
' point to the desired email
Const strMail As String = "emailaddress"
Dim oApp As Outlook.Application
Dim oMapi As Outlook.MAPIFolder
Dim oMail As Outlook.MailItem
Dim x As Long, y As Long
Dim destCell As Range
Dim i As Long
Dim oItem As Object
With ActiveSheet
Set destCell = .Cells(Rows.Count, "A").End(xlUp)
End With
On Error Resume Next
Set oApp = GetObject(, "OUTLOOK.APPLICATION")
If (oApp Is Nothing) Then Set oApp = CreateObject("OUTLOOK.APPLICATION")
On Error GoTo 0
Set oMapi = oApp.GetNamespace("MAPI").Folders(strMail).Folders("inbox")
Set oMail = oMapi.Items(oMapi.Items.Count)
For Each oItem In oMapi.Items
If oItem.Subject = "Volume data" Then
' get html table from email object
Dim HTMLdoc As MSHTML.HTMLDocument
Dim tables As MSHTML.IHTMLElementCollection
Dim table As MSHTML.HTMLTable
Set HTMLdoc = New MSHTML.HTMLDocument
With HTMLdoc
.Body.innerHTML = oItem.HTMLBody
Set tables = .getElementsByTagName("table")
End With
'import in Excel
For Each table In tables
For x = 0 To table.Rows.Length - 1
For y = 0 To table.Rows(x).Cells.Length - 1
destCell.Offset(x, y).Value = table.Rows(x).Cells(y).innerText
Next y
Next x
Set destCell = destCell.Offset(x)
Next
Set oApp = Nothing
Set oMapi = Nothing
Set oMail = Nothing
Set HTMLdoc = Nothing
Set tables = Nothing
wkb.SaveAs "C:\Users\Desktop\New_email_" & iCounter & ".xlsm"
iCounter = iCounter + 1
End If
Next oItem
End Sub

Delete an Outlook appointment if a cell contains specific text

I currently have a code set up to add an appointment to Outlook if a cell in Excel contains the word "No". What I would like to be able to do is delete an existing appointment if the same cell is changed to "N/A". I've tried to adapt some code I found elsewhere for this but can't get it to work, currently it's displaying "Compile error: next without for"
Sub DeleteCalendarItems()
Dim r As Long, i As Long, wb As Workbook
Dim ws As Worksheet
Dim objOutlook As Outlook.Application
Dim objNamespace As Outlook.Namespace
Dim objFolder As Outlook.MAPIFolder
Dim objAppointment As Outlook.AppointmentItem
Dim strSubject As String
Set objOutlook = Outlook.Application
Set objNamespace = objOutlook.GetNamespace("MAPI")
Set objFolder = objNamespace.GetDefaultFolder(olFolderCalendar)
Set oItems = objFolder.Items
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Section 74")
r = ws.Cells(Rows.Count, 1).End(xlUp).Row 'Rows.Count should also have a reference to a wb & ws
For i = 2 To r
If ws.Cells(i, 9) = "N/A" Then
ws.Cells(i, 13) = "Yes"
Set objAppointment = oItems.Item(i)
With objAppointment
If .Subject = strSubject Then
objAppointment.Delete
End If
End With
End If
Next i
End Sub
A With, If and For statement (and more) should always be closed
Sub DeleteCalendarItems()
Dim wb As Workbook
Dim ws As Worksheet
Dim objOutlook As Outlook.Application
Dim objNamespace As Outlook.Namespace
Dim objFolder As Outlook.MAPIFolder
Dim objAppointment As Outlook.AppointmentItem
Dim strSubject As String
Set objOutlook = Outlook.Application
Set objNamespace = objOutlook.GetNamespace("MAPI")
Set objFolder = objNamespace.GetDefaultFolder(olFolderCalendar)
Set oItems = objFolder.Items
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Section 74")
r = ES.Cells(Rows.Count, 1).End(xlUp).Row 'Rows.Count should also have a reference to a wb & ws
For i = 2 To r
If ES.Cells(i, 9).Value = "N/A" Then
Set objAppointment = oItems.Item(i)
With objAppointment
If .Subject = strSubject Then
objAppointment.Delete
End If
End With
End If
Next i
End Sub
I've managed to work it out (somehow) - I needed to add a nested For loop
Sub DeleteNASec74()
Dim i As Long, j As Long
Dim wb As Workbook
Dim ws As Worksheet
Dim objOutlook As Outlook.Application
Dim objNamespace As Outlook.Namespace
Dim objFolder As Outlook.MAPIFolder
Dim objAppointment As Outlook.AppointmentItem
Set objOutlook = Outlook.Application
Set objNamespace = objOutlook.GetNamespace("MAPI")
Set objFolder = objNamespace.GetDefaultFolder(olFolderCalendar)
Set oItems = objFolder.Items
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Section 74")
r = ws.Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To r
For j = oItems.Count To 1 Step -1
If ws.Cells(i, 9).Value = "N/A" Then
ws.Cells(i, 13) = "Yes"
Set objAppointment = oItems.Item(j)
With objAppointment
If .Subject = "Send reminder email - " + ws.Cells(i, 2).Value Then
objAppointment.Delete
End If
End With
End If
Next j
Next i
End Sub

Top 50 emails from Outlook from new to old

How do I get the top 50 emails from Outlook using Excel VBA from new to old?
I am using the code below, however this is fetching the emails from last to first.
Sub GetFromInbox()
Dim olApp As Outlook.Application
Dim olNs As Namespace
Dim Fldr As MAPIFolder
Dim olMail As Variant
Dim i As Integer
Set olApp = New Outlook.Application
Set olNs = olApp.GetNamespace("MAPI")
Set Fldr = olNs.GetDefaultFolder(olFolderInbox)
i = 1
x = Date
For Each olMail In Fldr.Items
ActiveSheet.Cells(i, 1).Value = olMail.Subject
ActiveSheet.Cells(i, 2).Value = olMail.ReceivedTime
ActiveSheet.Cells(i, 3).Value = olMail.SenderName
i = i + 1
Next olMail
Set Fldr = Nothing
Set olNs = Nothing
Set olApp = Nothing
End Sub
Sort a collection of the items in the folder.
Option Explicit
Sub GetFromInbox()
Dim olApp As outlook.Application
Dim olNs As Namespace
Dim Fldr As MAPIFolder
Dim sortItems As Items
Dim olObj As Object
Dim i As Long
Dim maxIter As Long
Set olApp = New outlook.Application
Set olNs = olApp.GetNamespace("MAPI")
Set Fldr = olNs.GetDefaultFolder(olFolderInbox)
' Sort a collection of items, not Fldr.Items
Set sortItems = Fldr.Items
sortItems.Sort "[Received]", True
If sortItems.count > 50 Then
maxIter = 50
Else
maxIter = sortItems.count
End If
For i = 1 To maxIter
Set olObj = sortItems(i)
If olObj.Class = olMail Then
ActiveSheet.Cells(i, 1).Value = olObj.subject
ActiveSheet.Cells(i, 2).Value = olObj.ReceivedTime
ActiveSheet.Cells(i, 3).Value = olObj.senderName
End If
Next
Set olObj = Nothing
Set sortItems = Nothing
Set Fldr = Nothing
Set olNs = Nothing
Set olApp = Nothing
End Sub
If this grabs the wrong 50 emails you can try stepping through items the opposite way like:
For i = Fldr.Items.Count To Fldr.Items.Count - 50 Step -1
ActiveSheet.Cells(i, 1).Value = Fldr.Items(i).Subject
etc...
Add an exit once you hit 50, for ex:
If counter = 50 Then Exit For
Also, you can alternatively keep your existing code, then add a function to sort the emails by received date and only keep the top 50

How to retrieve SenderEmailAddress from each mail item in an Outlook folder?

I am trying to pull the sender's email address from every email in an inbox folder
I am not having any problems until I reach my For command for each email in the folder.
If I use the code as it is now I run into an error because olSender is not Dim As Variant, but if I change it to Dim As Variant I cannot Dim it as an Outlook.MailItem to retrieve the senderEmailAddress.
I'm assuming a nested For loop is the solution. Outlook 2013 is the version.
Sub ExportToExcel()
'EXCEL
'Opening Excel workbook
Dim oXLApp As Object, oXLwb As Object, oXLws As Object
Dim lRow As Long
On Error Resume Next
Set oXLApp = GetObject(, "Excel.Application")
'~~> If not found then create new instance
If Err.Number <> 0 Then
Set oXLApp = CreateObject("Excel.Application")
End If
Err.Clear
On Error GoTo 0
oXLApp.Visible = True
Set oXLwb = oXLApp.Workbooks.Open("C:\Users\******\Documents\******.xlsm")
Set oXLws = oXLwb.Sheets("Sheet1")
oXLws.Range("A" & 1).Select
'OUTLOOK
'Opening Outlook folder
Dim olNS As Outlook.NameSpace
Dim objOwner As Outlook.Recipient
Set olNS = Application.GetNamespace("MAPI")
Set objOwner = olNS.CreateRecipient("*********#email.com")
objOwner.Resolve
If objOwner.Resolved Then
Set BouncedEmailsFolder = olNS.GetSharedDefaultFolder(objOwner, olFolderInbox).Folders("Bounced Emails")
End If
Dim olItms As Outlook.Items
Dim olMail As Variant
Dim i As Long
Dim olSender As Outlook.MailItem
Set olItms = BouncedEmailsFolder.Items
olItms.Sort ("Subject")
i = 1
For Each olSender In olItms
oXLws.Select
oXLws.Cells(i, 1).Select
oXLws.Cells(i, 1).Value = olSender.SenderEmailAddress
i = i + 1
Next olSender
Set BouncedEmailsFolder = Nothing
Set olNS = Nothing
End Sub
Your code works for me when set to my default inbox.
olNS.GetDefaultFolder(olFolderInbox)
I wonder if you're not coming across non-mail items in your bounced emails? You may want to try the code below, which will retrieve mail items only (instead of also trying to extract the sender for meeting requests, task assignments, etc):
For Each olSender In olItms
If TypeOf olSender Is MailItem Then
oXLws.Select
oXLws.Cells(i, 1).Select
oXLws.Cells(i, 1).Value = olSender.SenderEmailAddress
i = i + 1
End If
Next olSender

How to forward email based on criteria?

How can I send mails automatically based on criteria?
I want to open the mail based on the subject provided in column A, add default content and forward this mail to the email address provided in Column B.
I know how to open an Outlook mail based on the subject.
Sub Test()
Dim olApp As Outlook.Application
Dim olNs As Namespace
Dim Fldr As MAPIFolder
Dim olMail As Variant
Dim i As Integer
Set olApp = New Outlook.Application
Set olNs = olApp.GetNamespace("MAPI")
Set Fldr = olNs.GetDefaultFolder(olFolderInbox)
i = 1
For Each olMail In Fldr.Items
If InStr(olMail.Subject, "") <> 0 Then
olMail.Display
i = i + 1
End If
Next olMail
End Sub
Subject (column A) Send to (Column B)
SP12345667 aaa#gmail.com
SP12345668 bbb#gmail.com
SP12345669 xxx#abc.com
SP12345670 yyy#abc.com
SP12345671 mmm#abc.com
SP12345672 nnn#abc.com
SP12345673 yyy#abc.com
Here is an Example on how to loop...
Option Explicit
Public Sub Example()
Dim olApp As Outlook.Application
Dim olNs As Outlook.Namespace
Dim Inbox As Outlook.MAPIFolder
Dim Item As MailItem
Dim MsgFwd As MailItem
Dim Items As Outlook.Items
Dim Recip As Recipient
Dim Email As String
Dim ItemSubject As String
Dim lngCount As Long
Dim i As Long
Set olApp = CreateObject("Outlook.Application")
Set olNs = olApp.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items
i = 2 ' i = Row 2
With Worksheets("Sheet1") ' Sheet Name
Do Until IsEmpty(.Cells(i, 1))
ItemSubject = .Cells(i, 1).Value '(i, 1) = (Row 2,Column 1)
Email = .Cells(i, 2).Value '(i, 2) = (Row 2,Column 2)
'// Loop through Inbox Items backwards
For lngCount = Items.Count To 1 Step -1
Set Item = Items.Item(lngCount)
If Item.Subject = ItemSubject Then ' if Subject found then
Set MsgFwd = Item.Forward
Set Recip = MsgFwd.Recipients.Add(Email) ' add Recipient
Recip.Type = olTo
MsgFwd.Display
End If
Next ' exit loop
i = i + 1 ' = Row 2 + 1 = Row 3
Loop
End With
Set olApp = Nothing
Set olNs = Nothing
Set Inbox = Nothing
Set Item = Nothing
Set MsgFwd = Nothing
Set Items = Nothing
End Sub

Resources