0

The code below doesn't execute reply all property, hence, I am not able to edit the body of the email and keep the conversation of the email chain.

I think the best option is to use Application.advancesearch as it gives you latest email by searching through all folders. But I do not know how to run it through Excel.

Objective:
1) Search the inbox and subfolders (multiple) and Sent items folder for the latest email for selected "Subject"
2) select the latest email and reply to all

Sub ReplyMail()

    ' Variables
    Dim OutlookApp As Object
    Dim IsOutlookCreated As Boolean
    Dim sFilter As String, sSubject As String
    Dim SentTime As Long
    Dim IndoxTime As Long

    Dim olEmailIndox As Outlook.MailItem
    Dim olEmailSent As Outlook.MailItem

    ' Get/create outlook object
    On Error Resume Next
    Set OutlookApp = GetObject(, "Outlook.Application")
    If Err Then
        Set OutlookApp = CreateObject("Outlook.Application")
        IsOutlookCreated = True
    End If
    On Error GoTo 0

    Set olEmailIndox = OutlookApp.CreateItem(olMailItem)
    Set olEmailSent = OutlookApp.CreateItem(olMailItem)



        ' Restrict items
        sSubject = "Subject 1"
        sFilter = "[Subject] = '" & sSubject & "'"

        ' Main
        With OutlookApp.Session.GetDefaultFolder(olFolderSentMail).Items.Restrict(sFilter)
            If .Count > 0 Then
                .Sort "ReceivedTime", True
                Set olEmailSent = .Item(1)
                SentTime = olEmailSent.SentOn
            End If
        End With

        With OutlookApp.Session.GetDefaultFolder(olFolderInbox).Items.Restrict(sFilter)
            If .Count > 0 Then
                .Sort "ReceivedTime", True
                Set olEmailInbox = .Item(1)
                InboxTime = olEmailInbox.ReceivedTime
            End If
        End With

        If SentTime > InboxTime Then
            With olEmailSent
                .ReplyAll
                .Display
                '.body
                '.Send
            End With

        Else
            With olEmailInbox
                .ReplyAll
                .Display
                '.body
                '.Send
            End With

        End If



    ' Quit Outlook instance if it was created by this code
    If IsOutlookCreated Then
        OutlookApp.Quit
        Set OutlookApp = Nothing
    End If

End Sub
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
DJSingh
  • 15
  • 7

1 Answers1

0

I have tested the code below and even though you can polish it, should get you started.

Let me know and mark the answer if it helps.

Add in a vba module this code:

Public Sub ProcessEmails()

    Dim testOutlook As Object
    Dim oOutlook As clsOutlook
    Dim searchRange As Range
    Dim subjectCell As Range

    Dim searchFolderName As String

    ' Start outlook if it isn't opened (credits: https://stackoverflow.com/questions/33328314/how-to-open-outlook-with-vba)
    On Error Resume Next
    Set testOutlook = GetObject(, "Outlook.Application")
    On Error GoTo 0

    If testOutlook Is Nothing Then
        Shell ("OUTLOOK")
    End If

    ' Initialize Outlook class
    Set oOutlook = New clsOutlook

    ' Get the outlook inbox and sent items folders path (check the scope specification here: https://learn.microsoft.com/en-us/office/vba/api/outlook.application.advancedsearch)
    searchFolderName = "'" & Outlook.Session.GetDefaultFolder(olFolderInbox).FolderPath & "','" & Outlook.Session.GetDefaultFolder(olFolderSentMail).FolderPath & "'"

    ' Loop through excel cells with subjects
    Set searchRange = ThisWorkbook.Worksheets("Sheet1").Range("A2:A4")

    For Each subjectCell In searchRange

        ' Only to cells with actual subjects
        If subjectCell.Value <> vbNullString Then

            Call oOutlook.SearchAndReply(subjectCell.Value, searchFolderName, False)

        End If

    Next subjectCell

    MsgBox "Search and reply completed"

    ' Clean object
    Set testOutlook = Nothing

End Sub

Then add a class module and name it: clsOutlook

To the class module add the following code:

Option Explicit

' Credits: Based on this answer: https://stackoverflow.com/questions/31909315/advanced-search-complete-event-not-firing-in-vba

' Event handler for outlook
Dim WithEvents OutlookApp As Outlook.Application
Dim outlookSearch As Outlook.Search
Dim outlookResults As Outlook.Results

Dim searchComplete As Boolean


' Handler for Advanced search complete
Private Sub outlookApp_AdvancedSearchComplete(ByVal SearchObject As Search)
    'MsgBox "The AdvancedSearchComplete Event fired."
    searchComplete = True
End Sub


Sub SearchAndReply(emailSubject As String, searchFolderName As String, searchSubFolders As Boolean)

    ' Declare objects variables
    Dim customMailItem As Outlook.MailItem
    Dim searchString As String
    Dim resultItem As Integer

    ' Variable defined at the class level
    Set OutlookApp = New Outlook.Application

    ' Variable defined at the class level (modified by outlookApp_AdvancedSearchComplete when search is completed)
    searchComplete = False

    ' You can look up on the internet for urn:schemas strings to make custom searches
    searchString = "urn:schemas:httpmail:subject like '" & emailSubject & "'" ' Use: subject like '%" & emailSubject & "%'" if you want to include words see %

    ' Perform advanced search
    Set outlookSearch = OutlookApp.AdvancedSearch(searchFolderName, searchString, searchSubFolders, "SearchTag")

    ' Wait until search is complete based on outlookApp_AdvancedSearchComplete event
    While searchComplete = False
        DoEvents
    Wend

    ' Get the results
    Set outlookResults = outlookSearch.Results

    If outlookResults.Count = 0 Then Exit Sub

    ' Sort descending so you get the latest
    outlookResults.Sort "[SentOn]", True

    ' Reply only to the latest one
    resultItem = 1

    ' Some properties you can check from the email item for debugging purposes
    On Error Resume Next
    Debug.Print outlookResults.Item(resultItem).SentOn, outlookResults.Item(resultItem).ReceivedTime, outlookResults.Item(resultItem).SenderName, outlookResults.Item(resultItem).Subject
    On Error GoTo 0

    Set customMailItem = outlookResults.Item(resultItem).ReplyAll

    ' At least one reply setting is required in order to replyall to fire
    customMailItem.Body = "Just a reply text " & customMailItem.Body

    customMailItem.Display

End Sub
Ricardo Diaz
  • 5,658
  • 2
  • 19
  • 30
  • I am getting an error. Run-time error ‘287’ Application-defined or object-defined error. In the class module, SearchString = urn:schemas:httpmail:subject like 'Mid-Year Report'" So it is searching for subject. outlookSearch = "Search Tag" but then it just keep looping over the While Loop and then I get an error. – DJSingh Feb 28 '19 at 00:57
  • Just to be sure, a reference to the Microsoft Outlook library is required. Have you add it in the VBE? – Ricardo Diaz Feb 28 '19 at 00:59
  • Yes I did. Microsoft Outlook 15.0 Object Library is checked. – DJSingh Feb 28 '19 at 01:04
  • Please set a break point at that line and try to run the code so we can make sure that's the line that is raising the error – Ricardo Diaz Feb 28 '19 at 01:06
  • Thanks. I commented the line "customMailItem.Body = "Just a reply text " & customMailItem.Body" then the code was working. I do not know why this line is giving an error. Also, right now the code searches for only inbox and sent items. How do I search for all the folders in inbox. I have like 50 subfolders in inbox. – DJSingh Feb 28 '19 at 01:33
  • Sorry my bad. In my testing I left the searchsubfolders to false. Change the false to true in this line: Call oOutlook.SearchAndReply(subjectCell.Value, searchFolderName, False) – Ricardo Diaz Feb 28 '19 at 01:47
  • Awesome thanks!.. this works. Also when removed "& customMailItem.Body" from the commented line, i.e. from "customMailItem.Body = "Just a reply text " & customMailItem.Body" to "customMailItem.Body = "Just a reply text " ". This line works, However, the body of the reply contains only "Just a reply text" and email chain below is deleted. Is there any way I can retain the email chain while including text for new email? – DJSingh Feb 28 '19 at 03:08
  • Great! Please consider marking this answer. Regarding the final question, this part is the one to keep the original email: & customMailItem.Body There must be an special email/case that is raising the error. you could add an error handler – Ricardo Diaz Feb 28 '19 at 03:10
  • Thanks a ton. You saved me a lot of time. :) I am not able to mark the answer +1 but can only make the check mark green which I already did. – DJSingh Feb 28 '19 at 03:14