Loop stops after reaching Email.send line without any error - excel

I made a code, to send multiple emails based on a manual selection.
My problem is that when I'm reaching the .send email, the code does not go to the next "For" value. It sends the email, the loop stops, and the code starts from the beginning without following my For instruction anymore.
Here is my code:
Sub MailTenders()
' add ref - tool -> references - > Microsoft Outlook XX.X Object Library
Dim olApp As Outlook.Application
Dim Email As Outlook.MailItem
' add ref - tool -> references - > Microsoft Word XX.X Object Library
Dim wdDoc As Word.Document '<=========
Dim tempWB As Workbook
Set tempWB = ActiveWorkbook
Dim sht As Excel.Worksheet
Set sht = tempWB.Sheets("Email")
Dim rng As Range
Set rng = sht.Range("A1:N22").SpecialCells(xlCellTypeVisible)
'rng.Copy
Dim reg As Excel.Worksheet
Dim com As Excel.Worksheet
Dim edata As Excel.Worksheet
Dim lstrow As Range
Dim lastr_nr As Long
Dim lastc_nr As Long
Set reg = tempWB.Sheets("Register")
Set com = tempWB.Sheets("Companies")
Set edata = tempWB.Sheets("Email Data")
Dim iCounter As Integer
Dim usermail As String
Dim compny As String
Dim atchm As String
Dim emailrng As Range, cl As Range
Dim sto As String
Dim lc As Integer
com.Activate
lc = Application.CountA(com.Range("A:A"))
For iCounter = 2 To lc 'WorksheetFunction.CountA(Columns(1))
If Cells(iCounter, 6).Value = "x" Then
Set olApp = New Outlook.Application
Set Email = olApp.CreateItem(0)
Set wdDoc = Email.GetInspector.WordEditor
usermail = Cells(iCounter, 5).Value
compny = Cells(iCounter, 2).Value
atchm = Cells(iCounter, 4).Value
reg.Activate
Range("A1").Select
Selection.End(xlDown).Select
Set lstrow = ActiveCell
lastr_nr = ActiveCell.Row
Range("a" & lastr_nr + 1).Value = Range("a" & lastr_nr) + 1
Range("b" & lastr_nr + 1).Select
ActiveCell.FormulaR1C1 = "=NOW()"
ActiveCell.Copy
ActiveCell.PasteSpecial (xlPasteValues)
Range("c" & lastr_nr + 1).Value = compny
Range("d" & lastr_nr + 1).Value = atchm
edata.Activate
Range("B9").Select
Set emailrng = Range(Selection, Selection.End(xlToRight))
lastc_nr = ActiveCell.Column
sto = ""
For Each cl In emailrng
sto = sto & ";" & cl.Value
Next
sto = Mid(sto, 2)
com.Activate
rng.Copy
With Email
.To = usermail
.CC = sto
.Subject = "Cerere oferta pentru proiectul " & edata.Range("B1").Value
wdDoc.Range.PasteAndFormat Type:=wdFormatOriginalFormatting
' .Display
.Attachments.Add "c:\Users\HorbaniucVla\OneDrive - Strabag BRVZ GmbH\BL 2019\CJV Vintu - Simeria\14. Tenders\02. CP\Atasamente\" & atchm & ".zip"
.SaveAs "c:\Users\HorbaniucVla\OneDrive - Strabag BRVZ GmbH\BL 2019\CJV Vintu - Simeria\14. Tenders\02. CP\Offers Sent\" & edata.Range("b10") & ".msg", OlSaveAsType.olMsg
.send '!!!Here the code stops after sending the first email !!!
End With
reg.Activate
Range("e" & lastr_nr + 1).Select
Range("e" & lastr_nr + 1).Hyperlinks.Add Anchor:=Selection, Address:="c:\Users\HorbaniucVla\OneDrive - Strabag BRVZ GmbH\BL 2019\CJV Vintu - Simeria\14. Tenders\02. CP\Offers Sent\" & edata.Range("b10") & ".msg", TextToDisplay:="draft email link"
Range("f" & lastr_nr + 1).Select
Range("e" & lastr_nr + 1).Hyperlinks.Add Anchor:=Selection, Address:="c:\Users\HorbaniucVla\OneDrive - Strabag BRVZ GmbH\BL 2019\CJV Vintu - Simeria\14. Tenders\02. CP\Atasamente\" & atchm & ".zip", TextToDisplay:="attachement link"
End If
Next iCounter
End Sub
For a better understanding, I also made a GIF with the code step into which unfortunately it is bigger than 2mb and I will share via dropbox.
The GIF is animated, but I noticed is not working without download.

Related

How to extract email data based on Date & subject using VBA?

I have a code that is extracting the emails based on subject. But I wanted to extract the mails based on date as well. So it should be the intersection of Date & subject, only if both condition satisfies I should get the extracted data. Just with the subject condition the code works fine, but when I am adding the date condition, it's not picking up correctly.
For eg: I want to extract yesterday's email with subject line as "Volume data". what am I doing wrong in the code? Can someone help please?
Option Explicit
Sub FinalMacro()
Application.DisplayAlerts = False
Dim wkb As Workbook
Set wkb = ThisWorkbook
Sheets("Sheet1").Cells.Clear
' point to the desired email
Const strMail As String = "emailaddress"
Dim oApp As Outlook.Application
Dim oMapi As Outlook.MAPIFolder
Dim oItem As Object
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") 'Folders("Others")
For Each oItem In oMapi.Items
If oItem.Subject = "Volume data" & oItem.ReceivedTime = Date Then
'If oItem.ReceivedTime = Date Then
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
Dim t As Long, r As Long, c As Long
Dim eRow As Long
For t = 0 To tables.Length - 1
eRow = Sheets(1).Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
For r = 0 To (tables(t).Rows.Length - 1)
For c = 0 To (tables(t).Rows(r).Cells.Length - 1)
Range("A" & eRow).Offset(r, c).Value = tables(t).Rows(r).Cells(c).innerText
Next c
Next r
eRow = Sheets(1).Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Next t
Cells(eRow, 1) = "Date & Time of Receipt:" & " " & oItem.ReceivedTime
Cells(eRow, 1).Interior.Color = vbRed
Cells(eRow, 1).Font.Color = vbWhite
Cells(eRow, 1).Columns.AutoFit
Set oApp = Nothing
Set oMapi = Nothing
Set HTMLdoc = Nothing
Set tables = Nothing
'End If
End If
Next oItem
wkb.Save
Application.DisplayAlerts = True
End Sub
Please, test the next adapted code:
Sub FinalMacro()
Dim wkb As Workbook: Set wkb = ThisWorkbook
'Sheets("Sheet1").cells.Clear 'uncomment if you need to start from the first row...
' point to the desired email
Const strMail As String = "emailaddress"
Dim oApp As Outlook.Application, oMapi As Outlook.MAPIFolder, oItem As Outlook.MailItem
Dim destCell As Range, i As Long
With ActiveSheet
Set destCell = .cells(rows.count, "A").End(xlUp) 'last cell where from to extract the last date
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
Dim HTMLdoc As MSHTML.HTMLDocument, tables As MSHTML.IHTMLElementCollection
Dim table As MSHTML.HTMLTable
Dim t As Long, r As Long, c As Long, eRow As Long
Set oMapi = oApp.GetNamespace("MAPI").Folders(strMail).Folders("inbox") 'Folders("Others")
'the necessary elements to extract only the necessary mails:_______________________________________________
Dim startDate As String, endDate As String, flt As String
startDate = CStr(Date) & " " & "00:00" 'Date can be replaced with any string Date
endDate = CStr(Date + 1) & " " & "00:00" 'the same, it should be the previous Date +1
flt = "[Subject] = 'Volume data' and [ReceivedTime] >= '" & startDate & "' and [ReceivedTime] < '" & endDate & "'"
Dim myItems As Outlook.items
Set myItems = oMapi.items.Restrict(flt) '____________________________________________________________
Application.DisplayAlerts = False
For Each oItem In myItems
Set HTMLdoc = New MSHTML.HTMLDocument
With HTMLdoc
.body.innerHTML = oItem.HtmlBody
Set tables = .getElementsByTagName("table")
End With
For t = 0 To tables.Length - 1
eRow = ActiveSheet.cells(rows.count, 1).End(xlUp).row + 1
For r = 0 To (tables(t).rows.Length - 1)
For c = 0 To (tables(t).rows(r).cells.Length - 1)
Range("A" & eRow).Offset(r, c).value = tables(t).rows(r).cells(c).innerText
Next c
Next r
eRow = ActiveSheet.cells(rows.count, 1).End(xlUp).Offset(1, 0).row
Next t
cells(eRow, 1) = "Date & Time of Receipt:" & " " & oItem.ReceivedTime
cells(eRow, 1).Interior.color = vbRed
cells(eRow, 1).Font.color = vbWhite
cells(eRow, 1).Columns.AutoFit
Next oItem
wkb.Save
Application.DisplayAlerts = True
End Sub
endDate is necessary only if you choose for filtering a Date in the past.
Not tested, of course, I do not have the necessary data, but this should be the idea. I tested only the filtering part and it worked as needed.
Edited:
Now, there are some variants in order to build the necessary start/end date, in order to fulfill different cases:
To process mails received from 12th of October 2021 till the end of the month, use the next definitions:
startDate = CStr(DateSerial(2021, 10, 12)) & " " & "00:00"
endDate = CStr(DateSerial(2021, 11, 1)) & " " & "00:00"
To process mails received today after 12 o'clock, use the next definitions:
startDate = CStr(Date) & " " & "12:00"
endDate = CStr(Date + 1) & " " & "00:00"
In such a case the filter (flt) string definition may miss the endDate part, which does not matter too much in such a context...
Since your code records oItem.ReceivedTime as cells(eRow, 1) = "Date & Time of Receipt:" & " " & oItem.ReceivedTime, the last recorded time can be extracted and process all mails received after that specific time:
'1. comment the next existing code line:
'Sheets("Sheet1").Cells.Clear
`2. declare the next new (necessary) variables:
Dim destCell As Range, lastOne As String, arrD, arrS
Set DestCell = ActiveSheet.cells(rows.count, "A").End(xlUp)
arrD = Split(destCell.value, " "): arrS = Split(arrD(6), ":")
lastOne = arrD(5) & " " & arrS(0) & ":" & arrS(1)
`3. Change the filter string:
flt = "[Subject] = 'Volume data' and [ReceivedTime] > '" & lastOne & "'"
If something not clear enough, do not hesitate to ask for clarifications. But after you tried understanding how it works and deduce where a mistake could appear and why...
Our mission here is not to supply free code samples, it is to make as many as possible users LEARN...

Search Inbox by Subject, Sender and Date for each email address in Excel range

I search the inbox folder for given subject, sender from column 1 and date.
Based on the result it should populate rows in column 2 with Yes or No. But it populates all rows as No. I'm sure I should see at least one Yes.
The value of variable i is always nothing. Looks like it is a problem with filterstring variable.
Sub searchemailsreceived()
Application.ScreenUpdating = False
ThisWorkbook.Activate
Dim ol As outlook.Application
Dim ns As outlook.Namespace
Dim fol As outlook.Folder
Dim i As Object
Dim mi As outlook.MailItem
Dim filterstring As String
Dim dmi As outlook.MailItem
Dim lstRow As Long
Dim rng As Range
ThisWorkbook.Sheets("Sheet1").Activate
lstRow = Cells(Rows.Count, 2).End(xlUp).Row
Set rng = Range("A2:A" & lstRow)
Set ol = New outlook.Application
Set ns = ol.GetNamespace("MAPI")
Set fol = ns.GetDefaultFolder(olFolderInbox)
Set dmi = ol.CreateItem(olMailItem)
For Each cell In rng
filterstring = "#SQL=(""urn:schemas:httpmail:fromemail"" LIKE '%" & Range(cell.Address).Offset(0, 0).Value2 & "%' AND ""urn:schemas:httpmail:subject"" LIKE '%This is my subject%' AND ""urn:schemas:httpmail:datereceived"" >= '4/1/2021 12:00 AM')"
For Each i In fol.Items.Restrict(filterstring)
If i.Class = olMail Then
Range(cell.Address).Offset(0, 1).Value2 = "Yes"
GoTo landhere
End If
Next i
Range(cell.Address).Offset(0, 1).Value2 = "No"
landhere:
Next cell
Set mi = Nothing
Set dmi = Nothing
Set ol = Nothing
Application.ScreenUpdating = False
End Sub
Try the following cleaned function (untested):
Sub SearchEmailsReceived()
Application.ScreenUpdating = False
Dim ol As Outlook.Application: Set ol = New Outlook.Application
Dim fol As Outlook.MAPIFolder: Set fol = ol.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
Dim lstRow As Long: lstRow = ws.Cells(Rows.Count, 2).End(xlUp).Row
Dim rng As Range: Set rng = ws.Range("A2:A" & lstRow)
Dim i As Object, filterstring As String, Cell As Range
Dim dmi As Outlook.MailItem: Set dmi = ol.CreateItem(olMailItem)
For Each Cell In rng
filterstring = "#SQL=urn:schemas:httpmail:fromemail LIKE '%" & Cell.Value2 & "%' AND urn:schemas:httpmail:subject LIKE '%This is my subject%' AND urn:schemas:httpmail:datereceived >= '4/1/2021 12:00 AM'"
Cell.Offset(0, 1) = "No"
For Each i In fol.Items.Restrict(filterstring)
If i.Class = olMail Then Cell.Offset(0, 1) = "Yes"
Next i
Next Cell
Set dmi = Nothing
Set ol = Nothing
Application.ScreenUpdating = False
End Sub
The answer linked by #niton shows the SQL=urn... doesn't contain quote marks so they have been removed. You may want to cut down the filterstring and test whether each additional AND statement causes issues though. Maybe comment out subject and date to test whether it finds any e-mails from the recipients first then work them back in the further requirements once you know the base works ok
the fromemail schema didn't work for me. what worked for me is ""http://schemas.microsoft.com/mapi/proptag/0x0065001f"" CI_STARTSWITH '%" & Cell.Value2 & "%'
Thank you for helping.
Demonstration with "urn:schemas:httpmail:fromemail" and "proptag/0x0065001f".
Option Explicit
Sub searchemailsreceived_Demo()
'Application.ScreenUpdating = False
Dim ol As Outlook.Application
Dim ns As Outlook.Namespace
Dim fol As Outlook.Folder
Dim folItems As Outlook.Items
Dim folItemsSQL As Outlook.Items
Dim folItems1SQL As Outlook.Items
Dim folItems2SQL As Outlook.Items
Dim folItems3SQL As Outlook.Items
Dim i As Long
Dim filterString1 As String
Dim filterString2 As String
Dim filterString3 As String
Dim filterStringSQL As String
Dim filterString1SQL As String
Dim filterString2SQL As String
Dim filterString3SQL As String
Dim lastRowColA As Long
Dim rng As Range
Dim cell As Object
Dim foundFlag As Boolean
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
lastRowColA = Cells(Rows.Count, 1).End(xlUp).Row
Set rng = Range("A2:A" & lastRowColA)
Set ol = New Outlook.Application
Set ns = ol.GetNamespace("MAPI")
Set fol = ns.GetDefaultFolder(olFolderInbox)
Set folItems = fol.Items
Debug.Print "folItems.Count..: " & folItems.Count
For Each cell In rng
'filterString1 = """http://schemas.microsoft.com/mapi/proptag/0x0065001f"" CI_STARTSWITH '%" & cell.Value2 & "%'"
' or
' Based on sample data, a filter without wildcards may be preferable.
' Col A = email addresses starting in row 2
Debug.Print
filterString1 = """urn:schemas:httpmail:fromemail"" LIKE '" & cell.Value2 & "'"
Debug.Print "filterString1 ..: " & filterString1
filterString1SQL = "#SQL=(" & filterString1 & ")"
Debug.Print "filterString1SQL: " & filterString1SQL
Set folItems1SQL = folItems.Restrict(filterString1SQL)
Debug.Print "folItems1SQL.Count.: " & folItems1SQL.Count
' Condition 1
foundFlag = False
For i = 1 To folItems1SQL.Count
If folItems1SQL(i).Class = olMail Then
Debug.Print "i = " & i
Debug.Print " - folItems1SQL(i).SenderEmailAddress: " & folItems1SQL(i).SenderEmailAddress
cell.Offset(0, 2).Value2 = "Yes"
foundFlag = True
Exit For
End If
Next
If foundFlag = False Then
cell.Offset(0, 2).Value2 = "No"
End If
' Condition 2
Dim strSubject As String
strSubject = "test"
Debug.Print
filterString2 = """urn:schemas:httpmail:subject"" LIKE '%" & strSubject & "%'"
Debug.Print "filterString2 ..: " & filterString2
filterString2SQL = "#SQL=(" & filterString2 & ")"
Debug.Print "filterString2SQL: " & filterString2SQL
Set folItems2SQL = folItems.Restrict(filterString2SQL)
Debug.Print "folItems2SQL.Count.: " & folItems2SQL.Count
foundFlag = False
For i = 1 To folItems2SQL.Count
If folItems2SQL(i).Class = olMail Then
Debug.Print "i = " & i
Debug.Print " - folItems2SQL(i).Subject: " & folItems2SQL(i).Subject
cell.Offset(0, 3).Value2 = "Yes"
foundFlag = True
Exit For
End If
Next
If foundFlag = False Then
cell.Offset(0, 3).Value2 = "No"
End If
' Condition 3
Dim strDate As String
strDate = "2021/04/01 12:00 AM"
Debug.Print
filterString3 = """urn:schemas:httpmail:datereceived"" >= '" & strDate & "'"
Debug.Print "filterString3: " & filterString3
filterString3SQL = "#SQL=(" & filterString3 & ")"
Debug.Print "filterString3SQL: " & filterString3SQL
Set folItems3SQL = folItems.Restrict(filterString3SQL)
Debug.Print "folItems3SQL.Count : " & folItems3SQL.Count
foundFlag = False
For i = 1 To folItems3SQL.Count
If folItems3SQL(i).Class = olMail Then
Debug.Print "i = " & i
Debug.Print " - folItems3SQL(i).ReceivedTime: " & folItems3SQL(i).ReceivedTime
cell.Offset(0, 4).Value2 = "Yes"
foundFlag = True
Exit For
End If
Next
If foundFlag = False Then
cell.Offset(0, 4).Value2 = "No"
End If
' Condition 1 AND Condition 2 AND Condition 3
Debug.Print
Debug.Print filterString1
Debug.Print filterString2
Debug.Print filterString3
filterStringSQL = "#SQL=(" & filterString1 & " AND " & filterString2 & " AND " & filterString3 & ")"
Debug.Print "filterStringSQL: " & filterStringSQL
Set folItemsSQL = folItems.Restrict(filterStringSQL)
Debug.Print "folItemsSQL.Count : " & folItemsSQL.Count
foundFlag = False
For i = 1 To folItemsSQL.Count
If folItemsSQL(i).Class = olMail Then
Debug.Print "i = " & i
Debug.Print " - folItemsSQL(i).SenderEmailAddress: " & folItemsSQL(i).SenderEmailAddress
Debug.Print " - folItemsSQL(i).Subject...........: " & folItemsSQL(i).Subject
Debug.Print " - folItemsSQL(i).ReceivedTime......: " & folItemsSQL(i).ReceivedTime
Debug.Print
cell.Offset(0, 1).Value2 = "Yes"
foundFlag = True
Exit For
End If
Next
If foundFlag = False Then
cell.Offset(0, 1).Value2 = "No"
End If
Next cell
Application.ScreenUpdating = True
End Sub
Actually I tried a smaller and it worked but thank you.
Sub searchemailsreceived()
Application.ScreenUpdating = False
ThisWorkbook.Activate
Dim ol As Outlook.Application: Set ol = New Outlook.Application
Dim ns As Outlook.Namespace: Set ns = ol.GetNamespace("MAPI")
Dim fol As Outlook.Folder: Set fol = ns.GetDefaultFolder(olFolderInbox)
Dim filterstring As String
Dim lstRow As Long: lstRow = Cells(Rows.Count, 2).End(xlUp).Row
Dim rng As Range: Set rng = Range("A2:A" & lstRow)
ThisWorkbook.Sheets("Sheet1").Activate
For Each Cell In rng
filterstring = "#SQL=(""http://schemas.microsoft.com/mapi/proptag/0x0065001f"" CI_STARTSWITH '%" & Cell.Value2 & "%' AND ""urn:schemas:httpmail:subject"" LIKE '%This is a subject%' AND ""urn:schemas:httpmail:datereceived"" >= '1/1/2000 12:00 AM')"
Range(Cell.Address).Offset(0, 2).Value2 = fol.Items.Restrict(filterstring).Count
filterstring = ""
Next Cell
Set ol = Nothing
Application.ScreenUpdating = False
End Sub

How to resolve vba runtime error 91, when trying to close a PPT

I wrote code to send automated birthday emails using Outlook and PPT. My code was working fine for a while and was getting the result as expected. All of the sudden, I started getting error 91 and debugging tool points to the line, where the PPT closes.
myDOBPPT.Close
I have declared the PPT and assigned a destination path for my template.
Any clues or solution on why this is occurring all of a sudden?
Option Explicit
Private Sub Btn_SendEmail_Click()
'Declaring Outlook
Dim OutlookApp As Outlook.Application
Dim OutlookMail As Outlook.MailItem
'Declaring Sender Outlook
Dim SenderOutlookApp As Outlook.Application
Dim SenderOutlookMail As Outlook.MailItem
'Declaring PPT
Dim objPPT As PowerPoint.Application
Dim myDOBPPT As PowerPoint.Presentation
Dim DestinationPPT As String
'Assigning Path of files
DestinationPPT = "C:\Users\charles.hill\Desktop\BirthdayAutomation\Birthday_Automation.pptx"
'Declaring and assigning values for varibales
Dim i As Long
i = 2
Dim randomslidenumber As Integer
Dim FirstSlide As Double
Dim LastSlide As Double
Dim Mydate As Date
Mydate = Date
'Declaring the Logo Image
Dim LogoImage As String
'Assigning Path of files
LogoImage = "C:\Users\charles.hill\Pictures\Saved Pictures\TIGA Logo.jpg"
'Worksheets("Emp_Details").Range("A2:A" & Range("A2").End(xlDown).Row).ClearContents
Application.ScreenUpdating = False
For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
Set objPPT = CreateObject("PowerPoint.Application")
objPPT.Visible = True
Set myDOBPPT = objPPT.Presentations.Open(DestinationPPT) 'PPT with birthday images opens
If Mydate = DateSerial(Year(Date), Month(Cells(i, 4).Value), Day(Cells(i, 4).Value)) Then
'Jump to Random Slide
With myDOBPPT
FirstSlide = 1
LastSlide = myDOBPPT.Slides.Count
Randomize
randomslidenumber = Int(((LastSlide - FirstSlide) * Rnd() + FirstSlide))
End With
With myDOBPPT.Slides(randomslidenumber)
.Shapes("NameOval").TextEffect.Text = WorksheetFunction.Proper(Sheet1.Cells(i, "B").Value) 'Employee's Name
.Shapes("DOB").TextEffect.Text = VBA.Format(Sheet1.Cells(i, "D").Value, "DD Mmm") 'Employee's DOB
.Export (ActiveWorkbook.Path & "\slide") & ".gif", "gif"
End With
Set OutlookApp = New Outlook.Application
Set OutlookMail = OutlookApp.CreateItem(olMailItem)
OutlookMail.To = Cells(i, 5).Value
OutlookMail.CC = Cells(i, 6).Value
OutlookMail.BCC = ""
OutlookMail.Subject = "Happy Birthday " & Cells(i, 2).Value & "!!"
OutlookMail.Attachments.Add (ActiveWorkbook.Path & "\slide.gif")
OutlookMail.HTMLBody = "Good Morning All" & "<br> <br>" & _
"Please join TIGA in wishing " & Cells(i, 2).Value & " " & Cells(i, 3).Value & " a Happy Birthday! Hope you have a fantastic day" & "<br> <br>" & _
"<center><img src='cid:slide.gif' height='576' width='768'/></center>" & "<br> <br>" & _
"Best Wishes and Regards," & "<br>" & "HR Team" & "<br> <br>" & _
"<img src='C:\Users\charles.hill\Pictures\Saved Pictures\TIGA Logo.jpg'/>"
OutlookMail.Display
OutlookMail.Send
'Updates Email Sent column to Yes
With Worksheets("Emp_Details").Cells(i, 7)
.Value = "Yes"
End With
End If
Next i
myDOBPPT.Close
Set myDOBPPT = Nothing
objPPT.Quit
Set objPPT = Nothing
Set OutlookMail = Nothing
Set OutlookApp = Nothing
On Error Resume Next
VBA.Kill (ActiveWorkbook.Path & "\slide.gif")
ActiveWorkbook.Save
MsgBox "Processing Done", vbInformation
MsgBox "Records Updated and Workbook saved", vbInformation
'Declaring variables for updating Email sent column and send birthday wishes log.
Dim RowNum As Integer
RowNum = 2
Dim CurrentDate As Date
CurrentDate = Date
Dim Last_Row
Dim xInspect As Object
Dim PageEditor As Object
Const wdFormatPlainText = 0
'Worksheets("Sheet1").Range("G2:G500").ClearContents
'For RowNum = 2 To Cells(Rows.Count, 1).End(xlUp).Row
' If Worksheets("Sheet1").Cells(RowNum, 4).Value = CurrentDate Then
' Worksheets("Sheet1").Cells(RowNum, 7).Value = "Yes"
'End If
'Next RowNum
'ActiveWorkbook.Save
'MsgBox "Records Updated and Workbook saved", vbInformation
Set SenderOutlookApp = New Outlook.Application
Set SenderOutlookMail = SenderOutlookApp.CreateItem(olMailItem)
Set xInspect = SenderOutlookMail.GetInspector
Set PageEditor = xInspect.WordEditor
Last_Row = Worksheets("Emp_Details").Range("A" & Rows.Count).End(xlUp).Row
Worksheets("Log").Range("A2:I500").ClearContents
For RowNum = 2 To Last_Row
If Worksheets("Emp_Details").Cells(RowNum, "G").Value = "Yes" Then
Worksheets("Emp_Details").Rows(RowNum).Copy Destination:=Sheets("Log").Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
End If
Next RowNum
Worksheets("Log").UsedRange.Copy
With SenderOutlookMail
.To = "sreenandini.jayaram#tiga.us"
.CC = ""
.BCC = ""
.Subject = "Birthday Wishes Log" & " " & Date
.Body = "Birthday wishes were sent out to the following Employees" & vbCrLf
.Display
PageEditor.Application.Selection.Start = Len(.Body)
PageEditor.Application.Selection.End = PageEditor.Application.Selection.Start
PageEditor.Application.Selection.PasteAndFormat Type:=wdFormatPlainText
.Display
.Send
Set PageEditor = Nothing
Set xInspect = Nothing
End With
Set SenderOutlookMail = Nothing
Set SenderOutlookApp = Nothing
Application.ScreenUpdating = True
End Sub 'Ending Button Click Sub-routine
You are getting that error because you are initializing the object inside the loop and trying to close it outside the loop. If the code doesn't enter the loop then myDOBPPT will be Nothing
For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
'
'
'
Set myDOBPPT = objPPT.Presentations.Open(DestinationPPT)
'
'
'
Next i
myDOBPPT.Close
You can also test it by changing myDOBPPT.Close to the below.
For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
'
'
'
Set myDOBPPT = objPPT.Presentations.Open(DestinationPPT)
'
'
'
Next i
If myDOBPPT Is Nothing Then
MsgBox "myDOBPPT is nothing"
End If
Move it inside the loop
For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
'
'
'
Set myDOBPPT = objPPT.Presentations.Open(DestinationPPT)
'
'
'
myDOBPPT.Close
Next i

Need to send email to multiple reciepent from filter data

I wanted to send email to multiple recipient as per their fund code. for eg. in given image I want email for QR fund in column A to be sent out to B2,B3 and B4 in same email and subject line should be "C2" for next I want email for RTIO fund in column A to be sent out to B5, B7 and B8 in same email and subject line should be "C5" and so on
Sub SendMultipleEmails()
Dim Mail_Object, OutApp As Variant
With ActiveSheet
lastrow = .Cells(.Rows.Count, "b").End(xlUp).Row
End With
For i = 2 To lastrow
Set Mail_Object = CreateObject("Outlook.Application")
Set OutApp = Mail_Object.CreateItem(0)
With OutApp
.Subject = "Your subject here"
.Body = "Your message here"
.To = Cells(i, 2).Value
.dISPLAY
End With
I am not able to apply filter condition and get multiple email recipient in one email
Try this code:
Sub SendMultipleEmailsaa()
Dim Mail_Object, OutApp As Object
Dim ws As Worksheet: Set ws = ActiveSheet
Dim arr() As Variant
LastRow = ws.Cells(ws.Rows.Count, "b").End(xlUp).row
arr = ws.Range("A2:A" & LastRow)
Set Mail_Object = CreateObject("Outlook.Application")
first = 2
For i = LBound(arr) To UBound(arr)
If i = UBound(arr) Then GoTo YO
If arr(i + 1, 1) = arr(i, 1) Then
first = WorksheetFunction.Min(first, i + 1)
Else
YO:
Set OutApp = Mail_Object.CreateItem(0)
With OutApp
.Subject = ws.Range("C" & i + 1).Value
.Body = "Your message here"
.Display
.To = ws.Range("A" & i + 1).Value
For j = first To i
.Recipients.Add ws.Range("A" & j).Value
Next
first = i + 2
End With
End If
Next
End Sub
To automatically sort add this code below the calculation on LastRow in above code:
ws.Sort.SortFields.Clear
ws.Sort.SortFields.Add2 Key:=ws.Range("A2:A" & LastRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ws.Sort
.SetRange ws.UsedRange
.Header = False
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Another Update:
Dim bc As String
With OutApp
.Subject = ws.Range("C" & i + 1).Value
.Body = "Your message here"
.Display
bc = ws.Range("A" & i + 1).Value
For j = first To i
bc = bc & ";" & ws.Range("A" & j).Value
Next
.BCC = bc
first = i + 2
End With
Here is my solution:
Option Explicit
Public Sub Main()
Dim rngSource As Range: Set rngSource = ExpandRange(ThisWorkbook.Worksheets("Sheet1").Range("A2"))
ReadDataAndSendAllMail rngSource
End Sub
Public Function ExpandRange(rngTopLeftCell As Range) As Range
With rngTopLeftCell.Worksheet
Set ExpandRange = rngTopLeftCell.Resize( _
.Cells(.Rows.Count, rngTopLeftCell.Column).End(xlUp).Row - rngTopLeftCell.Row + 1, _
.Cells(rngTopLeftCell.Row, .Columns.Count).End(xlToLeft).Column - rngTopLeftCell.Column + 1)
End With
End Function
Public Sub ReadDataAndSendAllMail(rngSource As Range)
Dim dctData As Dictionary: Set dctData = ReadData(rngSource)
SendAllMail dctData
End Sub
Public Function ReadData(rngSource As Range) As Dictionary
Dim dctResult As Dictionary: Set dctResult = New Dictionary
Dim rngRecord As Range: For Each rngRecord In rngSource.Rows
Dim dctRecord As Dictionary: Set dctRecord = New Dictionary
dctRecord.Add "Fund", rngRecord.Cells(1, 1).Value
dctRecord.Add "Email", rngRecord.Cells(1, 2).Value
dctRecord.Add "Subject", rngRecord.Cells(1, 3).Value
dctRecord.Add "Attachment", rngRecord.Cells(1, 4).Value
If Not dctResult.Exists(dctRecord("Fund")) Then
dctResult.Add dctRecord("Fund"), New Collection
End If
dctResult(dctRecord("Fund")).Add dctRecord
Next rngRecord
Set ReadData = dctResult
End Function
Public Sub SendAllMail(dctData As Dictionary)
Const cstrEmailDelimiter As String = "; " ' Note: Observe which delimiter your local version of Outlook uses and replace this value with it
Dim moaOutlook As Outlook.Application: Set moaOutlook = New Outlook.Application
Dim varFund As Variant: For Each varFund In dctData.Keys
Dim strFund As String: strFund = vbNullString
Dim strTo As String: strTo = vbNullString
Dim strSubject As String: strSubject = vbNullString
Dim strBody As String: strBody = vbNullString
Dim strAttachmentPath As String: strAttachmentPath = vbNullString
Dim dctRecord As Dictionary: For Each dctRecord In dctData(varFund)
strFund = dctRecord("Fund")
strTo = strTo & cstrEmailDelimiter & dctRecord("Email")
strSubject = dctRecord("Subject")
strBody = vbNullString ' Note: Replace vbNullString with some text for the message body
strAttachmentPath = dctRecord("Attachment")
Next dctRecord
strTo = Mid(strTo, Len(cstrEmailDelimiter) + 1)
SendMail moaOutlook, strTo, strSubject, vbNullString, strAttachmentPath
Next varFund
moaOutlook.Quit
End Sub
Public Sub SendMail(moaOutlook As Outlook.Application, strTo As String, strSubject As String, strBody As String, strAttachmentPath As String)
Dim omiMailItem As Outlook.MailItem: Set omiMailItem = moaOutlook.CreateItem(olMailItem)
With omiMailItem
.To = strTo
.Subject = strSubject
.Body = strBody ' Note use .HTMLBody if you want to send an HTML email
.Attachments.Add strAttachmentPath
.display ' Note: If you want to manually press the send button, otherwise comment out this line
' .send ' Note: If you want to automatically send it, uncomment this line
End With
End Sub
I hope the function names make it easier to understand and reuse. I tested it, and worked for me.

While pasting data into an Outlook mail body - I get error 4506 "application locked for editing "

I have to compose a mail body that contains text from multiple sources .
However the line editor.Application.Selection.Paste gives an error "4505" application locked while editing
I paste multiple times from 3 sources to create many mails
Dim Outapp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim wd, cmmtrs, ftnt As Object
Dim editor As Object
Dim savePath As String
Dim filePath As String
Dim lastRow As Integer: lastRow = Sheet2.Range("D20000").End(xlUp).Row
filePath = Application.ActiveWorkbook.Path
savePath = filePath & "\" & Format(Now(), "yyyy-mm-dd")
Set wd = CreateObject("Word.Application")
Set cmmtrs = wd.Documents.Open(savePath & "\ABC.docx", ReadOnly:=True)
'create multiple emails
For i = 2 To lastRow
Set Outapp = CreateObject("Outlook.Application")
Set OutMail = Outapp.CreateItem(olMailItem)
Set vInspector = OutMail.GetInspector
Set editor = vInspector.WordEditor
With OutMail
.To = Sheet2.Range("B" & i).Value
.CC = Sheet2.Range("C" & i).Value
.Subject = Sheet2.Range("D" & i).Value
.Body = Sheet2.Range("E" & i).Value & vbCrLf & vbNewLine
Dim lst As Integer: lst = Sheet3.Cells(1000, Sheet3.Range("A3:XAA3").Find(i - 1).Column).End(xlUp).Row
Dim col1, col2 As Integer: col1 = Sheet3.Range("A3:XAA3").Find(i - 1).Column
.Display
End With
With OutMail
If Sheet3.Range("A3:XAA3").Find(i) Is Nothing Then
col2 = Sheet3.Cells.Find(What:="*", After:=Sheet3.Cells(1, 1), LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False).Column
Else
col2 = Sheet3.Range("A3:XAA3").Find(i).Column - 1
End If
Sheet3.Range(Sheet3.Cells(4, col1), Sheet3.Cells(lst + 1, col2)).Copy
editor.Application.Selection.Start = Len(.Body)
editor.Application.Selection.End = editor.Application.Selection.Start
Application.Wait (Now + 0.0001)
editor.Application.Selection.Paste
End With
If Sheet2.Range("G" & i) = "Yes" Then
cmmtrs.Content.Copy
With OutMail
editor.Application.Selection.Start = Len(.Body)
editor.Application.Selection.End = editor.Application.Selection.Start
Application.Wait (Now + 0.00005)
editor.Application.Selection.Paste
End With
End If

Resources