1

ProblemI am creating a macro to get email by subject and received date in our team shared box. My problem is that once I select date (e,g 1/16/2018 to 1/17/2018), only few emails are stored in object. In below screenshot, I have 9 items which are applied restrict method. It should be 14 items emails which are received after 1/16/2018 to now(right outlook mail in screenshot), but 5 emails are not stored in object. can anyone help me out? I'm STUCK!

Sub GetFromOutlook()

Dim OutlookApp As Outlook.Application
Dim OutlookNamespace As Namespace
Dim Folder As MAPIFolder
Dim OutlookMail As Variant
Dim i As Integer
Dim olItems As Outlook.Items
Dim myItems As Outlook.Items
Dim DateStr As Date
Dim DateEnd As Date
Dim oOlResults As Object

Dim DateToCheck As String
Dim DateToCheck2 As String
Dim DateToCheck3 As String

Set OutlookApp = New Outlook.Application
Set OutlookNamespace = OutlookApp.GetNamespace("MAPI")

Dim olShareName As Outlook.Recipient
Set olShareName = OutlookNamespace.CreateRecipient("Mailbox.sharedmailbox@example.ca")
Set Folder = OutlookNamespace.GetSharedDefaultFolder(olShareName, olFolderInbox).Folders("sub1").Folders("sub2")
Set olItems = Folder.Items


'DateStr = 1/16/2018
'DateEnd = 1/17/2018

DateStr = Format(Range("From_Date").Value, "DDDDD HH:NN")
DateEnd = Format(Range("To_Date").Value, "DDDDD HH:NN")

'DateStr = DateAdd("d", -1, DateStr)
'DateEnd = DateAdd("d", 1, DateEnd)

DateToCheck = "[ReceivedTime] > """ & DateStr & """"
DateToCheck2 = "[ReceivedTime] <= """ & DateEnd & """"
DateToCheck3 = "[SenderName] = ""no-reply@example.com"""

Set myItems = olItems.Restrict(DateToCheck)
Set myItems = myItems.Restrict(DateToCheck2)
Set myItems = myItems.Restrict(DateToCheck3)

i = 1

For Each myitem In myItems
    ' MsgBox myitem.ReceivedTime

     Range("eMail_subject").Offset(i, 0).Value = myitem.Subject
     Range("eMail_date").Offset(i, 0).Value = myitem.ReceivedTime

     i = i + 1

Next myitem

Set Folder = Nothing
Set OutlookNamespace = Nothing
Set OutlookApp = Nothing


End Sub
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Jason
  • 91
  • 3
  • 9
  • 1
    Can you check what the `ReceivedTime` is of the emails that weren't selected please. I suspect that this is a time zone issue of some sort, i.e. the **displayed** time in Outlook is offset from what is stored in `ReceivedTime`. (But I don't use Outlook VBA, so I could be wildly wrong.) – YowE3K Jan 17 '18 at 20:39
  • Also concerning is that emails from other users (e.g. "support@croesus.com") were selected, despite your `DateToCheck3` restriction. – YowE3K Jan 17 '18 at 20:47
  • @YowE3K Yes, you're right I edited my code below DateToCheck = "[ReceivedTime] > '" & Format("1/16/18 12:01am", "ddddd h:nn AMPM") & "'" DateToCheck2 = "[ReceivedTime] < '" & Format("1/17/18 23:59pm", "ddddd h:nn AMPM") & "'" DateToCheck3 = "[SenderName] = ""no-reply@croesus.com""" – Jason Jan 17 '18 at 20:49
  • The main problem is time format. User will insert specified date in Excel but they don't usually type the time. Let's say 1/15/18 to 1/17/18. how can I date add time as I gave dummy data in above code? I know DateAdd function but I don't know how I can apply this in my code – Jason Jan 17 '18 at 20:51
  • I'm afraid I can't really help - I don't have easy access to Outlook VBA, so I can't play with it to see how `ReceivedTime` is stored, or how the `Restrict` method works. – YowE3K Jan 17 '18 at 21:32
  • [Check one of my post regarding *Restrict* requirement on dates](https://stackoverflow.com/a/48162914/2685412). – L42 Jan 18 '18 at 07:33
  • Is there a way to add 'todays date' to the filter? – Lynn Sep 28 '20 at 00:49

3 Answers3

2

If you are missing most recent mail then set DateEnd, without time, one day later. This should calculate to the beginning of the day at time 00:00.

Sub GetFromOutlook()

Dim OutlookApp As Outlook.Application
Dim OutlookNamespace As Namespace
Dim Folder As MAPIFolder
Dim OutlookMail As Variant

Dim i As Integer

Dim olItems As Outlook.Items
Dim myItems As Outlook.Items
Dim myitem As Object

Dim DateStr As String
Dim DateEnd As String

Dim oOlResults As Object

Dim DateToCheck As String
Dim DateToCheck2 As String
Dim DateToCheck3 As String

Set OutlookApp = New Outlook.Application
Set OutlookNamespace = OutlookApp.GetNamespace("MAPI")

Dim olShareName As Outlook.Recipient
'Set olShareName = OutlookNamespace.CreateRecipient("Mailbox.sharedmailbox@example.ca")
'Set Folder = OutlookNamespace.GetSharedDefaultFolder(olShareName, olfolderinbox).Folders("sub1").Folders("sub2")

' for my testing
Set Folder = OutlookNamespace.getdefaultfolder(olfolderinbox)

Set olItems = Folder.Items

DateStr = "2018-01-16"
Debug.Print DateStr

' User input DateEnd without a time
DateEnd = "2018-01-17"
Debug.Print DateEnd

' Calculated DateEnd is the beginning of the next day
DateEnd = DateAdd("d", 1, DateEnd)
' This is 2018-01-18 00:00
Debug.Print DateEnd

DateToCheck = "[ReceivedTime] > """ & DateStr & """"
Debug.Print vbCr & "Filter 1: " & DateToCheck

Set myItems = olItems.Restrict(DateToCheck)

For Each myitem In myItems
    Debug.Print myitem.ReceivedTime & ": " & myitem.Subject
Next myitem

'DateToCheck2 = "[ReceivedTime] <= """ & DateEnd & """"
DateToCheck2 = "[ReceivedTime] < """ & DateEnd & """"
Debug.Print vbCr & "Filter 2: " & DateToCheck2

Set myItems = myItems.Restrict(DateToCheck2)

For Each myitem In myItems
    Debug.Print myitem.ReceivedTime & ": " & myitem.Subject
Next myitem

DateToCheck3 = "[SenderName] = ""no-reply@example.com"""
Debug.Print vbCr & "Filter 3: " & DateToCheck3

Set myItems = myItems.Restrict(DateToCheck3)

For Each myitem In myItems
    Debug.Print myitem.ReceivedTime & ": " & myitem.Subject
Next myitem

Set Folder = Nothing
Set OutlookNamespace = Nothing
Set OutlookApp = Nothing

End Sub
niton
  • 8,771
  • 21
  • 32
  • 52
1

Expounding my comment you can try using below with the following considerations:

  1. Received date, datereceived is expressed in UTC. So you need to adjust your time depending on your UTC. In my case it is UTC8 so I need to adjust the time 8 hours earlier (Note: No documentation to support this, but when I did my testing, it is expressed in UTC.
    It may or may not always be the case).
  2. Date should be expressed as string as stated here.

    Although dates and times are typically stored with a Date format, the Find and Restrict methods require that the date and time be converted to a string representation.

    Example:

    mydate = Format(Now,"\'m/d/yyy hh:mm AM/PM\'") '/* will give '1/23/2018 01:36 PM' */
    
  3. sendername may contain the email address or the email name.

Sub stancial()
    Dim olItems As Outlook.Items
    Dim olFolder As Outlook.Folder
    Dim olNS As Outlook.NameSpace
    Dim olEmail As Outlook.MailItem
    Dim i As Long

    Dim efilter As String, startdt As String, endindt As String, _
        myUTC As Integer, sentby As String

    myUTC = 8 '/* this is your UTC, change to suit (in my case 8) */

    startdt = Format(DateAdd("h", -myUTC, _
              CDate("1/18/2018 12:00 PM")), "\'m/d/yyyy hh:mm AM/PM\'")
    endindt = Format(DateAdd("h", -myUTC, _
              CDate("1/18/2018 4:00 PM")), "\'m/d/yyyy hh:mm AM/PM\'")
    sentby = "'john.doe@email.com'" '/* can be sendername, "doe, john" */

    Set olNS = Application.GetNamespace("MAPI")
    Set olFolder = olNS.GetDefaultFolder(olFolderInbox)
    '/* filter in one go, where datereceived is
    'expressed in UTC (Universal Coordinated Time) */
    efilter = "@SQL= (urn:schemas:httpmail:sendername = " & sentby & _
              " And (urn:schemas:httpmail:datereceived >= " & startdt & _
              " And urn:schemas:httpmail:datereceived <= " & endindt & "))"

    Set olItems = olFolder.Items.Restrict(efilter)

    With olItems
        For i = .Count To 1 Step -1 '/* starting from most recent */
            If TypeOf .Item(i) Is MailItem Then
                Set olEmail = .Item(i)
                Debug.Print olEmail.Subject, olEmail.ReceivedTime
            End If
        Next
    End With
End Sub
L42
  • 19,427
  • 11
  • 44
  • 68
0

Your code only uses the DateToCheck3 restriction - the other two are ignored by your code. If you want to combine multiple restrictions, combine them into a single query using the AND operator.

Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78