How to loop rows in a range? - excel

I have an Excel sheet with information to send to specific people.
I read a table and when the third column changes value send an email to the first value as a contact in the last column with the table information according to the values in the third column.
An example of the table:
How do I continue the loop and send email to each contact with their personal information.
This code only sends the first information to the first e-mail.
Sub Enviar_Correo()
Dim OutlookApp As Outlook.Application
Dim MItem As Outlook.MailItem
Dim Ultimo As Integer
Dim R As Range
Dim C As Range
Dim inicio As Integer
Dim fin As Integer
Dim contar As Integer
Dim i As Integer
Dim Correo As String
Dim Asunto As String
Set OutlookApp = New Outlook.Application
Ultimo = Cells(Rows.Count, "C").End(xlUp).Row
inicio = 2
contar = 1
For Each R In Range("C2", "C" & Ultimo)
If R.Value = Cells(inicio + 1, 3).Value Then
contar = contar + 1
Else
fin = contar + inicio
Exit For
End If
Next
Dim xRg As Range
Dim xCell As Range
Dim xStr As String
Dim xRow As Long
Dim xCol As Long
Set xRg = Range("D" & inicio, "I" & fin - inicio)
For xRow = 1 To xRg.Rows.Count
For xCol = 1 To xRg.Columns.Count
xStr = xStr & xRg.Cells(xRow, xCol).Value & vbTab
Next
xStr = xStr & vbCrLf
Next
Correo = R.Offset(0, 7)
Asunto = "Envio Cotas"
Set MItem = OutlookApp.CreateItem(olMailItem)
With MItem
.To = Correo
.Subject = Asunto
.Body = "Estimado Proveedor," & vbNewLine & "Hago envío de sus cotas para los próximos días" & vbNewLine & xStr & vbNewLine & "Saludos!"
.Send
'
End With
End Sub

Related

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

Formatting a table using VBA that is being copied to an email

I have been struggling with this issue for awhile now and I would be very grateful for any help offered. So I have the code that is generating an email from an excel file that I have. The issue is that when the email is pasted over the table does not format correctly. I have attached a screenshot of what the output looks like and the code is below.
Sub Send_Email()
'Updated by Extendoffice 20200119
Dim xRg As Range
Dim I, J As Long
Dim xAddress As String
Dim xEmailBody As String
Dim xMailOut As Outlook.MailItem
Dim xOutApp As Outlook.Application
On Error Resume Next
xAddress = ActiveWindow.RangeSelection.Address
Set xRg = Range("A9:E32")
If xRg Is Nothing Then Exit Sub
Application.ScreenUpdating = False
Set xOutApp = CreateObject("Outlook.Application")
Set xMailOut = xOutApp.CreateItem(olMailItem)
For I = 1 To xRg.Rows.Count
For J = 1 To xRg.Columns.Count
xEmailBody = xEmailBody & " " & xRg.Cells(I, J).Value
Next
xEmailBody = xEmailBody & vbNewLine
Next
xEmailBody = "" & vbLf & vbLf & "" & vbLf & vbLf & xEmailBody & vbNewLine
With xMailOut
.Subject = Worksheets("TDN Generator").Range("A6").Value
.To = ""
.Body = xEmailBody
.Display
'.Send
End With
Set xMailOut = Nothing
Set xOutApp = Nothing
Application.ScreenUpdating = True
End Sub
THIS IS HOW IT PASTES INTO THE EMAIL:
Hello,
Check it out:
Trade 2
Trade Type Grant Number Security Type Shares Sold Shares Exercised
Sell To Cover 12345 Restricted Stock 200
Sell To Cover 12346 Restricted Stock 220
Sell To Cover 12347 Restricted Stock 240
Sell To Cover 12348 Restricted Stock 260
Sell To Cover 12349 Restricted Stock 280
I would like them to all be properly aligned in their said columns.
You can use the Space function to left- or right-pad the values as required.
Option Explicit
Public Sub Test()
Dim colwidth(1 To 5) As Integer
Dim rg As Range
Dim row As Range
Dim col As Integer
Dim val As String
Dim strout As String
' adjust the column widths as required
' you will get an error if the value is
' wider than the column width
colwidth(1) = 13
colwidth(2) = 12
colwidth(3) = 16
colwidth(4) = 12
colwidth(5) = 16
' function is in the worksheet module for convenience
With Me
Set rg = .Range("A1:E6")
For Each row In rg.Rows
' pad left
col = 1
val = row.Cells(1, col)
strout = val & Space(colwidth(col) - Len(val) + 1)
' pad right
col = 2
val = row.Cells(1, col)
strout = strout & Space(colwidth(col) - Len(val)) & val & Space(1)
' pad left
col = 3
val = row.Cells(1, col)
strout = strout & val & Space(colwidth(col) - Len(val) + 1)
' pad right
col = 4
val = row.Cells(1, col)
strout = strout & Space(colwidth(col) - Len(val)) & val & Space(1)
' pad left
col = 5
val = row.Cells(1, col)
strout = strout & val & Space(colwidth(col) - Len(val) + 1)
Debug.Print strout
Next row
End With
End Sub
Data range
Output
Trade Type Grant Number Security Type Shares Sold Shares Exercised
Sell To Cover 12345 Restricted Stock 200
Sell To Cover 12346 Restricted Stock 220
Sell To Cover 12347 Restricted Stock 240
Sell To Cover 12348 Restricted Stock 260
Sell To Cover 12349 Restricted Stock 280
Of course, this will only work with a fixed pitch typeface. Much better to write the data as an html table if the mail client supports that.
Using HTML format:
Sub Send_Email()
Dim xRg As Range
Dim I, J As Long
Dim xAddress As String
Dim xEmailBody As String
Dim xMailOut As Outlook.MailItem
Dim xOutApp As Outlook.Application
On Error Resume Next
Set xRg = Range("A9:E32")
xEmailBody = "Take a look:<br><br>" & HtmlTable(xRg)
Set xOutApp = CreateObject("Outlook.Application")
Set xMailOut = xOutApp.CreateItem(olMailItem)
With xMailOut
.Subject = Worksheets("TDN Generator").Range("A6").Value
.To = ""
.HTMLBody = xEmailBody
.Display
'.Send
End With
Set xMailOut = Nothing
Set xOutApp = Nothing
Application.ScreenUpdating = True
End Sub
Function HtmlTable(rng As Range) As String
Dim s As String, rw As Range, c As Range
s = "<table border=1>"
For Each rw In rng.Rows
s = s & "<tr>"
For Each c In rw.Cells
s = s & "<td>" & c.Value & "</td>"
Next c
s = s & "</tr>"
Next rw
HtmlTable = s & "</table>"
End Function
Have you tried the paste special command?
It's usually CTRL+ALT+V or ALT+E+S to open the paste special dialog.

Loop stops after reaching Email.send line without any error

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.

Choose different email body based on cell value

There are 3 body contents to be picked based on the value in D column.
1) if "D" column value is "High" then bodycontent1 should be selected
2) if "D" column value is "Medium" then bodycontent2 should be selected
3) if "D" column value is "Low" then bodycontent3 should be selected
The below code just picks the bodycontent1 for any criteria.
Code:
Option Explicit
Public Sub Example()
Dim olApp As Outlook.Application
Dim olNs As Outlook.Namespace
Dim Inbox As Outlook.MAPIFolder
Dim Item As Variant
Dim MsgFwd As MailItem
Dim Items As Outlook.Items
Dim Email As String
Dim Email1 As String
Dim ItemSubject As String
Dim lngCount As Long
Dim i As Long
Dim RecipTo As Recipient
Dim RecipCC As Recipient
Dim RecipBCC As Recipient
Dim onbehalf As Variant
Dim EmailBody As String
Dim BodyName As String
Dim Bodycontent1 As String
Dim Bodycontent2 As String
Dim Bodycontent3 As String
Dim Criteria1 As String
Set olApp = CreateObject("Outlook.Application")
Set olNs = olApp.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items
i = 2 ' i = Row 2
With Worksheets("Sheet1") ' Sheet Name
Do Until IsEmpty(.Cells(i, 1))
ItemSubject = .Cells(i, 1).Value '(i, 1) = (Row 2,Column 1)
Email = .Cells(i, 16).Value '(i, 2) = (Row 2,Column 2)
Email1 = .Cells(i, 2).Value
Criteria1 = .Cells(i, 4).Value
Bodycontent1 = "Hello this is for testing purpose1" & "<BR>" & _
"Regards," & "<BR>" & _
"Kelvin"
Bodycontent2 = "Hello this is for testing purpose2" & "<BR>" & _
"Regards," & "<BR>" & _
"Kelvin"
Bodycontent3 = "Hello this is for testing purpose3" & "<BR>" & _
"Regards," & "<BR>" & _
"Kelvin"
'// Loop through Inbox Items backwards
For lngCount = Items.Count To 1 Step -1
Set Item = Items.Item(lngCount)
If Item.Subject = ItemSubject Then ' if Subject found then
Set MsgFwd = Item.Forward
Set RecipTo = MsgFwd.Recipients.Add(Email1)
Set RecipTo = MsgFwd.Recipients.Add("secnww#hp.com")
Set RecipBCC = MsgFwd.Recipients.Add(Email)
MsgFwd.SentOnBehalfOfName = "doc#hp.com"
BodyName = .Cells(i, 3).Value
RecipTo.Type = olTo
RecipBCC.Type = olBCC
Debug.Print Item.Body
If Criteria1 = "high" Then
MsgFwd.HTMLBody = Bodycontent1 & Item.HTMLBody
ElseIf Criteria1 = "medium" Then
MsgFwd.HTMLBody = Bodycontent2 & Item.HTMLBody
Else 'If Criteria1 = "Low" Then
MsgFwd.HTMLBody = Bodycontent3 & Item.HTMLBody
MsgFwd.Display
End If
End If
Next ' exit loop
i = i + 1 ' = Row 2 + 1 = Row 3
Loop
End With
Set olApp = Nothing
Set olNs = Nothing
Set Inbox = Nothing
Set Item = Nothing
Set MsgFwd = Nothing
Set Items = Nothing
MsgBox "Mail sent"
End Sub
You should use Select Case rather than If/ElseIf
See the part about LastRow which is clear than Loop+i=i+1
I've added an Exit For (commented), in case you want to gain time, and only forward the 1st message with the subject you're looking for!
Final code :
Option Explicit
Public Sub Example()
Dim olApp As Outlook.Application
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Dim Item As Variant
Dim MsgFwd As MailItem
Dim wS As Worksheet
Dim Items As Outlook.Items
Dim Email As String
Dim Email1 As String
Dim ItemSubject As String
Dim lngCount As Long
Dim LastRow As Long
Dim i As Long
Dim BodyName As String
Dim Bodycontent1 As String
Dim Bodycontent2 As String
Dim Bodycontent3 As String
Dim Criteria1 As String
Set olApp = CreateObject("Outlook.Application")
Set olNs = olApp.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items
Bodycontent1 = "Hello this is for testing purpose1" & "<BR>" & _
"Regards," & "<BR>" & _
"Kelvin"
Bodycontent2 = "Hello this is for testing purpose2" & "<BR>" & _
"Regards," & "<BR>" & _
"Kelvin"
Bodycontent3 = "Hello this is for testing purpose3" & "<BR>" & _
"Regards," & "<BR>" & _
"Kelvin"
Set wS = thisworkbook.Worksheets("Sheet1") ' Sheet Name
With wS
LastRow = .Range("A" & .rows.Count).End(xlup).Row
For i = 2 To LastRow
ItemSubject = .Cells(i, 1).value
Email = .Cells(i, 16).value
Email1 = .Cells(i, 2).value
Criteria1 = .Cells(i, 4).value
BodyName = .Cells(i, 3).value
'// Loop through Inbox Items backwards
For lngCount = Items.Count To 1 Step -1
Set Item = Items.Item(lngCount)
If Item.Subject <> ItemSubject Then
Else
'If Subject found then
Set MsgFwd = Item.Forward
With MsgFwd
.To = Email1 & " ; secnww#hp.com"
.BCC = Email
.SentOnBehalfOfName = "doc#hp.com"
Select Case LCase(Criteria1)
Case Is = "high"
.HTMLBody = Bodycontent1 & Item.HTMLBody
Case Is = "medium"
.HTMLBody = Bodycontent2 & Item.HTMLBody
Case Is = "low"
.HTMLBody = Bodycontent3 & Item.HTMLBody
Case Else
MsgBox "Criteria : " & Criteria1 & " not recognised!", _
vbCritical + vbOKOnly, "Case not handled"
End Select
.Display
'Exit For
End With 'MsgFwd
End If
Next lngCount
Next i
End With 'wS
Set olApp = Nothing
Set olNs = Nothing
Set Inbox = Nothing
Set Item = Nothing
Set MsgFwd = Nothing
Set Items = Nothing
MsgBox "Mail sent"
End Sub

Outlook Email Macro

I have the mention code and it works all well with unique records, but the only problem is it sends multiple emails to 1 email id.
Email ID's are n column W (1st record is w6) and body of the mail is in column x6
have merge the body with code "wsht.cells(i, 25) = sbody"
any idea as who will this work were it wil send 1 email
for eg:- in w7 email id is xxx#gmail.com and in w10 email id is xxx#gmail.com
currently the code# send 2 mails, but it should send only 1 email to xxx#gmail.com
Any idea or update.
Private Sub CommandButton3_Click()
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Dim wSht As Worksheet
Dim LastRow As Long, lCuenta As Long
Dim i As Integer, k As Integer
Dim sTo As String, sSbject As String, sBody As String
Set wSht = ActiveSheet
LastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 6 To LastRow
lCuenta = Application.WorksheetFunction.CountIf(Range("W6:W" & i), Range("W" & i))
If lCuenta = 1 Then
ssubject = "PD Call Back"
sTo = wSht.Cells(i, 1)
sBody = wSht.Cells(i, 24)
For k = i To LastRow
If wSht.Cells(i, 1).Value = wSht.Cells(k + 1, 1).Value Then
sBody = sBody & vbNewLine & wSht.Cells(k + 1, 24).Value
End If
wSht.Cells(i, 25) = sBody
Next k
End If
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = sTo
.Subject = ssubject
.body = sBody
.Send
End With
Next i
End Sub
Your problem is occurring because you are testing whether or not this is the first time that the email id has been used and, if it isn't, you are resending the last email you set up.
The End If for your test needs to be moved after the section which sends the email:
Private Sub CommandButton3_Click()
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Dim wSht As Worksheet
Dim LastRow As Long, lCuenta As Long
Dim i As Integer, k As Integer
Dim sTo As String, sSbject As String, sBody As String
Set wSht = ActiveSheet
LastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 6 To LastRow
lCuenta = Application.WorksheetFunction.CountIf(Range("W6:W" & i), Range("W" & i))
If lCuenta = 1 Then
ssubject = "PD Call Back"
sTo = wSht.Cells(i, 1)
sBody = wSht.Cells(i, 24)
For k = i To LastRow
If wSht.Cells(i, 1).Value = wSht.Cells(k + 1, 1).Value Then
sBody = sBody & vbNewLine & wSht.Cells(k + 1, 24).Value
End If
wSht.Cells(i, 25) = sBody
Next k
'End If '<-- Move this
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = sTo
.Subject = ssubject
.body = sBody
.Send
End With
End If '<-- To here
Next i
End Sub

Resources