Have VBA loop through all inboxes in Outlook including shared inboxes - excel

My goal with this code is to reply to a specific email in the user's outlook depending on the subject(B8). Essentially have the code loop through all the user's inboxes including shared inboxes to find the email.
The first code I have will go into the user's outlook but only their main inbox and pull the email to reply to. This works without error.
Sub Display()
Dim Fldr As Outlook.Folder
Dim olfolder As Outlook.MAPIFolder
Dim olMail As Outlook.MailItem
Dim olReply As Outlook.MailItem
Dim olitems As Outlook.Items
Dim i As Long
Dim signature As String
Dim olitem As Object
Set Fldr = Session.GetDefaultFolder(olFolderInbox)
Set olitems = Fldr.Items
olitems.Sort "[Received]", True
For i = 1 To olitems.Count
Set olitem = olitems(i)
If Not TypeOf olitem Is Outlook.MailItem Then GoTo SkipToNext
Set olMail = olitem
signature = Environ("appdata") & "\Microsoft\Signatures\"
If Dir(signature, vbDirectory) <> vbNullString Then
signature = signature & Dir$(signature & "*.htm")
Else:
signature = ""
End If
signature = CreateObject("Scripting.FileSystemObject").GetFile(signature).OpenAsTextStream(1, -2).ReadAll
Set olMail = olitems(i)
If InStr(olMail.Subject, Worksheets("Checklist Form").Range("B8")) <> 0 Then
If Not olMail.Categories = "Executed" Then
Set olReply = olMail.ReplyAll
With olReply
.HTMLBody = "<p style='font-family:calibri;font-size:14.5'>" & "Hi Everyone," & "Regards," & "</p><br>" & signature & .HTMLBody
.Display
.Subject
End With
Exit For
olMail.Categories = "Executed"
Exit For
End If
End If
SkipToNext:
Next i
End Sub
This second section of code is my trial and error as well as the use of other resources attempt to have the code loop through all the inboxes of the user. The thing is it doesn't do anything anymore.
I did have working code for this scenario, then I mistakenly saved over it and I have not been successful in getting it back working. Below is as close as I have been able to get.
Any suggestions would be greatly appreciated.
The second script seems to be skipping from "Set olitems = Fldr.Items" to the bottom End If.
I thought maybe to move the End if right below "If not storeinbox Is Nothing Then" but the error "Object variable or With block variable not set" occurs.
When I do change the code line (While making the change above also) "Set Fldr = Storeinbox" to "Set Fldr = Session.GetDefaultFolder(olFolderInbox)" emails will populate, but only in the user's specific inbox(Does not pick up subject text, just most recent email).
I have added additional code to the second script
Set olitem = olitems(i)
If Not TypeOf olitem Is Outlook.MailItem Then GoTo SkipToNext
Set olMail = olitem
Which was missing. This will populate the email for the user's specific email address by the subject. If I type in a subject from another inbox then nothing will happen but it will go through the code with no errors.
Getting closer, but still nothing for the shared inboxes.
Sub Display()
Dim Fldr As Outlook.Folder
Dim olfolder As Outlook.MAPIFolder
Dim olMail As Outlook.MailItem
Dim olReply As Outlook.MailItem
Dim olItems As Outlook.Items
Dim i As Integer
Dim signature As String
Dim allStores As Stores
Dim storeInbox As Folder
Dim j As Long
Set allStores = Session.Stores
For j = 1 To allStores.Count
On Error Resume Next
Debug.Print j & " DisplayName - " & allStores(j).DisplayName
On Error GoTo 0
Set storeInbox = Nothing
On Error Resume Next
Set storeInbox = allStores(j).GetDefaultFolder(olFolderInbox)
On Error GoTo 0
If Not storeInbox Is Nothing Then
Set Fldr = storeinbox
Set olItems = Fldr.Items
olItems.Sort "[Received]", True
For i = 1 To olItems.Count
Set olitem = olitems(i)
If Not TypeOf olitem Is Outlook.MailItem Then GoTo SkipToNext
Set olMail = olitem
signature = Environ("appdata") & "\Microsoft\Signatures\"
If Dir(signature, vbDirectory) <> vbNullString Then
signature = signature & Dir$(signature & "*.htm")
Else
signature = ""
End If
signature = CreateObject("Scripting.FileSystemObject").GetFile(signature).OpenAsTextStream(1, -2).ReadAll
Set olMail = olItems(i)
If InStr(olMail.Subject, Worksheets("Checklist Form").Range("B8")) <> 0 Then
If Not olMail.Categories = "Executed" Then
Set olReply = olMail.ReplyAll
With olReply
.HTMLBody = "<p style='font-family:calibri;font-size:14.5'>" & "Hi Everyone," &
"Regards," & "</p><br>" & signature & .HTMLBody
.Display
.Subject
End With
Exit For
olMail.Categories = "Executed"
End If
End If
Next
End If
ExitRoutine:
Set allStores = Nothing
Set storeInbox = Nothing
SkipToNext:
Next j
End Sub

If you Set allStores = Nothing inside the j loop it will only be something in the first iteration.
Option Explicit
' Think of Option Explicit as being mandatory
' Tools | Options
' Editor tab
' Checkbox "Require Variable Declaration"
' Option Explict will generate automatically on new modules
' You may type it in at the top of an existing module
' This as well points out possible spelling errors in the variables
Sub Display()
'In Excel set reference to Outlook Object Library
Dim Fldr As Outlook.Folder
Dim olMail As Outlook.MailItem
Dim olItem As Object
Dim olReply As Outlook.MailItem
Dim olItems As Outlook.Items
Dim signature As String
Dim i As Long
Dim j As Long
Dim allStores As Stores
Dim storeInbox As Folder
signature = Environ("appdata") & "\Microsoft\Signatures\"
If Dir(signature, vbDirectory) <> vbNullString Then
signature = signature & Dir$(signature & "*.htm")
signature = CreateObject("Scripting.FileSystemObject").GetFile(signature).OpenAsTextStream(1, -2).ReadAll
Else
signature = ""
End If
' Usually works with Outlook open.
' If this proves to be unreliable,
' you may need a CreateObject("Outlook.Application")
Set allStores = Session.Stores
For j = 1 To allStores.Count
' No need to bypass wrong index error here
' The error has been fixed by using j not i
Debug.Print j & " DisplayName - " & allStores(j).DisplayName
' Reset storeInbox to nothing or it will remain the previous
' when there is an error on the current store
' This is one example of why to be careful with On Error Resume Next
Set storeInbox = Nothing
On Error Resume Next
' bypass error if store does not have an inbox
Set storeInbox = allStores(j).GetDefaultFolder(olFolderInbox)
On Error GoTo 0
If Not storeInbox Is Nothing Then
Set Fldr = storeInbox
Set olItems = Fldr.Items
' Not needed?
'olItems.Sort "[Received]", True
For i = 1 To olItems.Count
Set olItem = olItems(i)
If TypeOf olItem Is Outlook.MailItem Then
Set olMail = olItem
If InStr(olMail.Subject, Worksheets("Checklist Form").Range("B8")) <> 0 Then
If Not olMail.Categories = "Executed" Then
Set olReply = olMail.ReplyAll
With olReply
.HTMLBody = "<p style='font-family:calibri;font-size:14.5'>" & "Hi Everyone," & _
"Regards," & "</p><br>" & signature & .HTMLBody
.Display
' Generates a compile error. Appears not needed.
'.Subject
End With
olMail.Categories = "Executed"
olMail.Display 'olMail.Save
End If
End If
End If
Next
End If
Next j
ExitRoutine:
Set allStores = Nothing
Set storeInbox = Nothing
End Sub

Related

VBA: My Email .body doesn't concatenate with itself: application-defined or object-defined error

I have a script that searches a group inbox subfolder and replies to the first email with a matching subject. It then replies to all. When I populate the email I cannot add my text to the rest of the email. Only either or.
I've seen many responses to similar problems that show .HTMLBody = "test" & .HTMLBody as a solution but when the debug reaches this line, the second .HTMLBody is shown as 'application-defined or object-defined error'.
Any insight into whats causing the problem or where else I can get the info from previous emails in the chain to input it that way would be greatly appreciated.
Thanks,
Sub Find_Email()
Dim olMail As Outlook.MailItem
Dim olReply As Outlook.MailItem
Dim olItems As Outlook.Items
Dim olNS As Namespace
Dim olMailbox As Folder
Dim olFolder As Folder
Dim subFolder As Folder
Dim BodyText As String
Set olNS = GetNamespace("MAPI")
Set olMailbox = olNS.Folders("Group_Inbox")
Set olFolder = olMailbox.Folders("test_Folder")
Set subFolder = olFolder.Folders("test_subFolder")
Set olItems = subFolder.Items
TheDate = Format(Date, "DD-MM-YYYY")
TheDate1 = Format(Date, "YYYY-MM")
TheDate2 = Format(Date, "YYYYMMDD")
TheDate3 = Format(Date, "YYYY")
'Find most recent email and populate
olItems.Sort "ReceivedTime", True
For i = 1 To olItems.Count
Set olMail = olItems(i)
If InStr(olMail.Subject, "Desired_Subject " & TheDate) > 0 Then
Set olReply = olMail.ReplyAll
With olReply
.Display
.To = "Recipients#gmail.com"
.CC = ""
.Subject = "Test_Subject"
'.Attachments.Add "Document_destination"
.BodyFormat = olFormatHTML
.HTMLBody = "This is a test email sending in Excel" & .HTMLBody ' This is the problem line.
Exit Sub
End With
End If
Next i
End Sub
'I understand that it might be the fact it is in a group inbox, which means that it could work for you but 'still may not work for me.
'Thanks again,
Try this (i can't test it, just a thought )
'Somewehere declare this string variable
Dim incomingHTMLBody as string
olItems.Sort "ReceivedTime", True
For i = 1 To olItems.Count
Set olMail = olItems(i)
If InStr(olMail.Subject, "Desired_Subject " & TheDate) > 0 Then
incomingHTMLBody = olMail.HTMLBody
Set olReply = olMail.ReplyAll
With olReply
.Display
.To = "Recipients#gmail.com"
.CC = ""
.Subject = "Test_Subject"
'.Attachments.Add "Document_destination"
.BodyFormat = olFormatHTML
.HTMLBody = "This is a test email sending in Excel" & incomingHTMLBody
Exit Sub
End With
End If
Next i
End Sub
You may need a bit more care referencing Outlook objects in your environment.
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
' If desperate declare as Variant
Sub Find_Email()
Dim objApp As Outlook.Application
Set objApp = CreateObject("outlook.application")
Dim objNS As Namespace
Set objNS = objApp.GetNamespace("MAPI")
Dim objMailbox As Outlook.Folder
Set objMailbox = objNS.Folders("Group_Inbox")
Dim objFolder As Outlook.Folder
Set objFolder = objMailbox.Folders("test_Folder")
Dim subFolder As Outlook.Folder
Set subFolder = objFolder.Folders("test_subFolder")
Dim objItems As Outlook.Items
Set objItems = subFolder.Items
Dim TheDate As Date
TheDate = Format(Date, "DD-MM-YYYY")
'Find most recent email and populate
objItems.Sort "ReceivedTime", True
Dim i As Long
Dim objMail As Outlook.MailItem ' olMail is not a good variable name
Dim objReply As Outlook.MailItem
Debug.Print objItems.Count
For i = 1 To objItems.Count
Debug.Print objItems(i).Subject
If objItems(i).Class = olMail Then ' verify item is a mailitem
Set objMail = objItems(i)
If InStr(objMail.Subject, "Desired_Subject " & TheDate) > 0 Then
Set objReply = objMail.ReplyAll
With objReply
.Display
.To = "Recipients#gmail.com"
.CC = ""
.Subject = "Test_Subject"
'.Attachments.Add "Document_destination"
.BodyFormat = olFormatHTML
Debug.Print .htmlbody ' verify property is available
.htmlbody = "This is a test email sending in Excel" & .htmlbody ' This is the problem line.
Exit For
End With
End If
End If
Next i
End Sub

Excel macro to send Outlook emails will not send

I have this code which uses an Excel sheet to create Outlook emails with attachments. It creates the emails correctly and Display works fine, but I cannot get SendUsingAccount to send the emails (manual sending of each email after Display works fine).
Could someone please point out the error?
Many thanks!
Sub Send_Files()
Dim Sht As Worksheet
Dim olApp As Object, olMail As Object, olRecip As Object, olAtmt As Object
Dim iRow As Long
Dim Recip As String, Subject As String, Atmt As String
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim OutAccount As Outlook.Account
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
Set OutAccount = OutApp.Session.Accounts.Item(2)
Application.EnableEvents = False
Application.ScreenUpdating = False
iRow = 2
Set olApp = CreateObject("Outlook.Application")
Set Sht = ThisWorkbook.Worksheets("Mailinglist_1")
Do Until IsEmpty(Sht.Cells(iRow, 1))
Recip = Sht.Cells(iRow, 2).Value
Subject = Sht.Cells(iRow, 4).Value
Atmt = Sht.Cells(iRow, 3).Value
Set olMail = olApp.CreateItem(0)
With olMail
Set olRecip = .Recipients.Add(Recip)
Set olMail.SendUsingAccount = OutAccount
.Subject = "Test 2021"
.Body = "Dear " & Sht.Cells(iRow, 1).Value & "," & vbNewLine & vbNewLine & _
"Text" & vbNewLine & _
"Text" & vbNewLine & _
"The Team"
olRecip.Resolve
Set olAtmt = .Attachments.Add(Atmt)
Set .SendUsingAccount = OutAccount
.Send
End With
iRow = iRow + 1
Loop
Set olApp = Nothing
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub

VBA to search and reply in Outlook with specific criteria

I am Using windows 10, Excel 2013 and Outlook 2013
I am new to Macro. I need macro to perform below Task:
1) From Excel I want to open Outlook if Outlook is closed and move Point.2, If outlook is already open then move to Point.2
2) Search for a specific email in outlook in all folders and sub folders with criteria “A” and “B”
a) Latest dated received or sent email.
b) With specific Subject contains “Approved”, this to be taken from active cell.
3) Open the found latest mail as per above criteria do “Reply all”.
4) Write a comment and display the mail or send.
Below code was my start, but it has the following issues:
The code search for the exact name, while i need to search for any email contain the word which in active cell.
The code search only in sent emails, while i need to search in both inbox and sent.
The code just open the email, i need to write template comment as well.
Many thanks in advance.
Sub ReplyMail_No_Movements()
' Outlook's constant
Const olFolderSentMail = 5
' Variables
Dim OutlookApp As Object
Dim IsOutlookCreated As Boolean
Dim sFilter As String, sSubject As String
' 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
' Restrict items
sSubject = ActiveCell.Value
sFilter = "[Subject] = '" & sSubject & "'"
' Main
With OutlookApp.Session.GetDefaultFolder(olFolderSentMail).Items.Restrict(sFilter)
If .Count > 0 Then
.Sort "ReceivedTime", True
With .Item(1).replyall
.Display
'.Send
End With
Else
MsgBox "No emails found with Subject:" & vbLf & "'" & sSubject & "'"
End If
End With
' Quit Outlook instance if it was created by this code
If IsOutlookCreated Then
OutlookApp.Quit
Set OutlookApp = Nothing
End If
End Sub
It seems work now:
Sub ReplyAllLastEmailFromInboxAndSent()
Dim olApp As Outlook.Application
Dim olNs As Namespace
Dim Fldr As MAPIFolder
Dim objMail As Object
Dim objReplyToThisMail As MailItem
Dim lngCount As Long
Dim objConversation As Conversation
Dim objTable As Table
Dim objVar As Variant
Dim strBody As String
Dim searchFolderName As String
Set olApp = Session.Application
Set olNs = olApp.GetNamespace("MAPI")
Set Fldr = olNs.GetDefaultFolder(olFolderSentMail)
searchFolderName = "'" & Outlook.Session.GetDefaultFolder(olFolderInbox).FolderPath & "','" & Outlook.Session.GetDefaultFolder(olFolderSentMail).FolderPath & "'"
lngCount = 1
For Each objMail In Fldr.Items
If TypeName(objMail) = "MailItem" Then
If InStr(objMail.Subject, ActiveCell.Value) <> 0 Then
Set objConversation = objMail.GetConversation
Set objTable = objConversation.GetTable
objVar = objTable.GetArray(objTable.GetRowCount)
Set objReplyToThisMail = olApp.Session.GetItemFromID(objVar(UBound(objVar), 0))
With objReplyToThisMail.replyall
strBody = "Dear " & "<br>" & _
"<p>Following up with the below. May you please advise?" & _
"<p>Thank you," & vbCrLf
.HTMLBody = strBody & .HTMLBody
.Display
End With
Exit For
End If
End If
Next objMail
Set olApp = Nothing
Set olNs = Nothing
Set Fldr = Nothing
Set objMail = Nothing
Set objReplyToThisMail = Nothing
lngCount = Empty
Set objConversation = Nothing
Set objTable = Nothing
If IsArray(objVar) Then Erase objVar
End Sub

Runtime error 462 when sending multiple email notifications

I have a worksheet set up to send email notifications when certain cells contain values, such as "75%" and "Due".
Around half the time I get
Runtime error 462
It seems this is because I have not specified elements of my code properly.
Private Sub Worksheet_Change(ByVal Target As Range)
Call Check_Project_Progress
End Sub
Private Sub Send_Email(Optional ByVal email_title As String = "")
Dim olNS As Namespace
Dim olMail As MailItem
Set olNS = GetNamespace("MAPI")
Set olMail = CreateItem(olMailItem)
With olMail
.Subject = email_title
.To = "LearnDataAnalysis#outlook.com"
.Body = "Value reads 75%"
.SendUsingAccount = olNS.Accounts.Item(1)
.Display
'.Send
End With
Set olMail = Nothing
Set olNS = Nothing
End Sub
Private Sub Send_Email2(Optional ByVal email_title As String = "")
Dim olNS As Namespace
Dim olMail As MailItem
Set olNS = GetNamespace("MAPI")
Set olMail = CreateItem(olMailItem)
With olMail
.Subject = email_title
.To = "LearnDataAnalysis#outlook.com"
.Body = "PLA determination due"
.SendUsingAccount = olNS.Accounts.Item(1)
.Display
'.Send
End With
Set olMail = Nothing
Set olNS = Nothing
End Sub
Private Sub Check_Project_Progress()
Dim LastRow As Long, RowNumber As Long
Dim ws As Worksheet
Set ws = ActiveSheet
With ws
LastRow = 500
If 4 > LastRow Then Exit Sub
For RowNumber = 4 To LastRow
If .Cells(RowNumber, "AB").Value = 0.75 And .Cells(RowNumber, "AD").Value <> "S" Then
.Cells(RowNumber, "AD").Value = "S"
.Cells(RowNumber, "AE") = "Email sent on:" & Now()
Call Send_Email(.Cells(RowNumber, "C").Value & " is approaching deadline")
End If
If 4 > LastRow Then Exit Sub
If .Cells(RowNumber, "AC").Value = "Due" And .Cells(RowNumber, "AD").Value <> "S,S" Then
.Cells(RowNumber, "AD").Value = "S,S"
.Cells(RowNumber, "AF") = "Email sent on:" & Now()
Call Send_Email2(.Cells(RowNumber, "C").Value & " has met deadline")
End If
Next RowNumber
End With
Set ws = Nothing
End Sub
Again, the error message is Runtime error 462. I have little idea what I'm doing.
You are getting that error becuase the code is not able to connect to the outlook application.
Try this. I have shown you for Send_Email. Adapt it for Send_Email2 as well.
Private Sub Send_Email(Optional ByVal email_title As String = "")
Dim olNS As Object
Dim olMail As Object
Dim OutlookApp As Object
'~~> Establish an Outlook application object
On Error Resume Next
Set OutlookApp = GetObject(, "Outlook.Application")
If Err.Number <> 0 Then
Set OutlookApp = CreateObject("Outlook.Application")
End If
Err.Clear
On Error GoTo 0
'~~> Check if we managed to connect to Outlook
If OutlookApp Is Nothing Then
MsgBox "unable to connect to outlook"
Exit Sub
End If
Set olNS = OutlookApp.GetNamespace("MAPI")
Set olMail = OutlookApp.CreateItem(0)
With olMail
.Subject = email_title
.To = "LearnDataAnalysis#outlook.com"
.Body = "Value reads 75%"
.SendUsingAccount = olNS.Accounts.Item(1)
.Display
'.Send
End With
End Sub

Excel Macro to Save Outlook 2010 attachment, oldest email to newest email

Need to save excel attachments in Outlook emails from oldest email to newest email and mark email as read. The newer attachments will overwrite the older if there is more than one unread email.
I receive an number of emails daily that need to be saved to run a report. However, if one report is missed, it is ignored and I go to the next dataset. The following works but does not always save the oldest first...it jumps around.
I have tried a number of options to save oldest first, with no luck. Any help on how I could make this consistently take the oldest email first. Thanks
Sub Save_Attachments()
Dim olApp As Outlook.Application, olNameSpace As Outlook.Namespace
Dim olFolder As Outlook.MAPIFolder, olMail As Outlook.MailItem
Dim olAttachment As Outlook.Attachment, lngAttachmentCounter As Long
Dim i As String
On Error GoTo Oooops
Set olApp = New Outlook.Application
Set olNameSpace = olApp.GetNamespace("MAPI")
Set olFolder = olNameSpace.GetDefaultFolder(olFolderInbox).Folders("sub_folder")
If olFolder Is Nothing Then Exit Sub
For Each olMail In olFolder.Items
If olMail.UnRead = True Then
For Each olAttachment In olMail.Attachments
lngAttachmentCounter = lngAttachmentCounter + 1
olAttachment.SaveAsFile ThisWorkbook.Path & "\zzzzz.xls"
Next olAttachment
End If
If olMail.UnRead Then
olMail.UnRead = False
End If
Next olMail
Exit Sub
Oooops:
MsgBox Err.Description, vbExclamation, "An error occurred"
End Sub
Since you did not state the options you tried maybe you did not try
For j = olFolder.Items.count To 1 Step -1
Something like this.
Option Explicit
Sub Save_Attachments_ReverseOrder()
Dim olApp As Outlook.Application, olNameSpace As Outlook.Namespace
Dim olFolder As Outlook.MAPIFolder
Dim olMail As Object ' <-- olMail is not necessarily a mailitem
Dim olAttachment As Outlook.attachment, lngAttachmentCounter As Long
Dim j As Long
On Error GoTo Oooops
Set olApp = New Outlook.Application
Set olNameSpace = olApp.GetNamespace("MAPI")
Set olFolder = olNameSpace.GetDefaultFolder(olFolderInbox).Folders("sub_folder")
If olFolder Is Nothing Then Exit Sub
For j = olFolder.Items.count To 1 Step -1
Set olMail = olFolder.Items(j)
If TypeOf olMail Is mailitem Then
If olMail.UnRead = True Then
Debug.Print olMail.subject & " - " & olMail.ReceivedTime
'For Each olAttachment In olMail.Attachments
' lngAttachmentCounter = lngAttachmentCounter + 1
' olAttachment.SaveAsFile ThisWorkbook.Path & "\zzzzz.xls"
'Next olAttachment
olMail.UnRead = False
Else
Debug.Print vbCr & olMail.subject & " - " & olMail.ReceivedTime & " was previously read"
End If
Else
Debug.Print vbCr & "Current item is not a mailitem."
End If
Next j
Exit Sub
Oooops:
MsgBox Err.Description, vbExclamation, "An error occurred"
End Sub

Resources