9

I want to retrieve emails from Outlook based on certain conditions.

I denote a certain folder in my code. In the example below the folder is "PRE Customer".
I would like to retrieve emails from Inbox or better from all Outlook folders.

My inbox consists of many subfolders. I may not know all the subfolders names as there are many users and someone can have the emails in Personal Folders.

The problem line is 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
Community
  • 1
  • 1
Artur Rutkowski
  • 487
  • 4
  • 9
  • 17
  • 3
    Because of Outlook's security system, it is much easier to write to Excel from Outlook than to read Outlook from Excel. These two answers of mine may give you a start. [How to copy Outlook mail message into excel using VBA or Macros](http://stackoverflow.com/a/12146315/973283) [How to import the outlook mail data to Excel](http://stackoverflow.com/a/8560136/973283) – Tony Dallimore May 19 '14 at 20:27

2 Answers2

13

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?

L42
  • 19,427
  • 11
  • 44
  • 68
  • Thanks a lot, now I have to try to make it to check only e-mails from today first and then with other conditions, as now there are a lot of e-mails so it works slowly. – Artur Rutkowski May 20 '14 at 09:28
  • Hi, the outputs the right data but in the place there are no e mails with conditions there is a empty place in Excel, which results that there are empty rows between retrieved e mails.Dou Maybe You have idea how can I resolve this? – Artur Rutkowski May 20 '14 at 17:50
  • Fix Empty rows: Move the `j = j + 1` up 2 lines. – PatricK May 20 '14 at 23:59
  • @ArturRutkowski See my edit. Directly accessing the last empty row is possible the best way. – L42 May 21 '14 at 01:03
  • I know I'm a bit late to the party but just tried this and it stops at 269 lines, although I have no idea for the life of me why. Any thoughts? – Steven Walker Apr 27 '16 at 07:07
  • @StevenWalker What do you mean stop? Does it produce error? Does it simply stop without error? Please elaborate. – L42 Apr 27 '16 at 10:12
  • @L42 Yes the code runs fine but when it's completed there's only 269 rows of emails (which I know I have more of). I think it may be that the code is only searching folders nested within my inbox, and not folders nested within folders. – Steven Walker Apr 29 '16 at 08:19
  • @StevenWalker Ah yes, this only search subfolders of Inbox. You will have to tweak it more or less to adopt to your needs. – L42 Apr 29 '16 at 09:25
  • @StevenWalker I think the other answer took care of your problem. I was about to post the solution but it turns out Patrick already covered it. – L42 Apr 29 '16 at 09:37
  • @L42 Thanks for coming back to me. If you have the solution readily available, please could you ping it through to me? I tried Patrick's solution but get a 'Object doesn't support this property' error on the `For each oItem` line – Steven Walker Apr 29 '16 at 12:04
  • @StevenWalker At which line? Btw, I'll try to come up with a possible fix. But by looking at Patrick's Solution, it should work. Also, this comment is getting longer and longer. If you don't mind, you can create your own question. Just reference this post. Also that way, more and more guru's will see your post and help. Thanks. – L42 May 03 '16 at 03:17
  • Thanks for the above solution. I've a couple of requirements **1.** Is there a way to identify images (inline) in a message? **2.** Looking for an option to edit the message and save it back to outlook using excel vba. Appreciate your inputs. – Sriram Jun 14 '17 at 13:10
4

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
PatricK
  • 6,375
  • 1
  • 21
  • 25
  • Thanks a lot, I will try this also today . Cheers – Artur Rutkowski May 20 '14 at 09:31
  • You can do recursive into all folders within Inbox, but do you need to know the folder path in Excel? Or EntryID if you want to reference it later? – PatricK May 20 '14 at 11:32
  • I need only the e-mails properties (subject, time, from) no matter from which outlook folder, only with added conditions like "word" in subject and for today (i want to do this to check todays date first in order to immediate dont check if the date isnt today) – Artur Rutkowski May 20 '14 at 12:07
  • @ArturRutkowski Try the updated code for recursive mode given a root folder. – PatricK May 20 '14 at 23:57
  • 1
    This might generate an error when `olMail` within the `olFldr` is not a `MailItem`. +1 though for `LateBinding` since this will be used by multiple users as the OP points out. That will eliminate difference in versions. – L42 May 21 '14 at 00:56
  • True that should check for item type before assuming it is of MailItem. @ArturRutkowski should combine type check from L42 in the `Sub GetFromFolder`, let us know if you get stuck. – PatricK May 21 '14 at 03:29