I am running a simple process that loops through a sheet and send an email based on Name, Email, Subject, CC and Country as shown in the image.
The image is only showing row 5 and 10 but the macro is running all rows from 2 to 10 and generates 9 email drafts instead of 2 email drafts.
May I know how to only run the loop on existing rows in the sheet?
Sub send_mass_email()
Dim i As Integer
Dim name, email, body, subject, copy, place, business As String
Dim OutApp As Object
Dim OutMail As Object
Dim cel As Range
body = ActiveSheet.TextBoxes("TextBox 1").Text
i = 2
'Loop down name column starting at row 2 column 1
Do While Cells(i, 1).Value <> ""
name = Split(Cells(i, 1).Value, " ")(0) 'extract first name
email = Cells(i, 2).Value
subject = Cells(i, 3).Value
copy = Cells(i, 4).Value
business = Cells(i, 5).Value
place = Cells(i, 6).Value
'replace place holders
body = Replace(body, "C1", name)
body = Replace(body, "C5", business)
body = Replace(body, "C6", place)
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.to = email
.cc = copy
.subject = subject
.body = body
'.Attachments.Add ("") 'You can add files here
.display
'.Send
End With
'reset body text
body = ActiveSheet.TextBoxes("TextBox 1").Text
i = i + 1
Loop
Set OutMail = Nothing
Set OutApp = Nothing
MsgBox "Email(s) Created!"
End Sub
Add an IF THEN in your Loop to check if the row is hidden or not. If true, do nothing:
Do While Cells(i, 1).Value <> ""
If Cells(i, 1).EntireRow.Hidden = False Then
'rest of your code
'
'
'
'
End If
i = i + 1
Loop
When filtering a range, those rows are hidden, so their property Hidden becomes True. If False it means those are the visible rows where you want to send email.
Related
can anyone explain to me the proper way to loop a certain range? I do not understand this part on how to make this work please? How do I do this only from row 2 to 4? It has a compile error, loop without for, any idea how to amend this please
Sub send_mass_email_display_only()
Dim i As Integer
Dim name As String, email As String, body As String, subject As String, copy As String, pdfadd As String
Dim OutApp As Object
Dim OutMail As Object
body = ActiveSheet.TextBoxes("TextBox 1").Text
For i = 2 To 4
'Loop down name column starting at row 2 column 1
Do While Cells(i, 1).Value <> ""
name = Split(Cells(i, 1).Value, " ")(0)
'name = Cells(i, 1).Value
email = Cells(i, 2).Value
subject = Cells(i, 3).Value
copy = Cells(i, 4).Value
pdfadd = Cells(i, 5).Value
body = Replace(body, "C1", name)
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = email
.cc = copy
.subject = subject
.body = body
.Attachments.Add (pdfadd)
.display
'.Send
End With
body = ActiveSheet.TextBoxes("TextBox 1").Text 'reset body text
Next i
Set OutMail = Nothing
Set OutApp = Nothing
'MsgBox "Email(s) Sent!"
End Sub
I tried as FaneDuru/grayProgrammerz suggested to delete the Do While line... seems that this works so far
Option Explicit
Sub send_mass_email_display_only()
Dim i As Integer
Dim name As String, email As String, body As String, subject As String, copy As String, pdfadd As String
Dim OutApp As Object
Dim OutMail As Object
body = ActiveSheet.TextBoxes("TextBox 1").Text
For i = 2 To 4
'Specific rows
name = Split(Cells(i, 1).Value, " ")(0)
'name = Cells(i, 1).Value
email = Cells(i, 2).Value
subject = Cells(i, 3).Value
copy = Cells(i, 4).Value
pdfadd = Cells(i, 5).Value
body = Replace(body, "C1", name)
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = email
.cc = copy
.subject = subject
.body = body
.Attachments.Add (pdfadd)
.display
'.Send
End With
body = ActiveSheet.TextBoxes("TextBox 1").Text 'reset body text
Next i
Set OutMail = Nothing
Set OutApp = Nothing
'MsgBox "Email(s) Sent!"
End Sub
I have an Excel sheet with data of users as shown below in table. Here I need to send the email to user their specific details containing in column A,B,C.
Using this code, I can only send the multiple row data in multiple email, but I need to send the multiple row data in single mail to respective user.
Sub BulkMail()
Application.ScreenUpdating = False ThisWorkbook.Activate Dim outMail As Outlook.MailItem
'Creating variable to hold values of different items of mail
Dim sendTo, subj, msg, Name, Company, Time As String
Dim lstRow As Long
'My data is on sheet "Exceltip.com" you can have any sheet name.
ThisWorkbook.Sheets("Sheet2").Activate
'Getting last row of containing email id in column 1.
lstRow = Cells(Rows.Count, 1).End(xlUp).Row
'Variable to hold all email ids
Dim rng As Range
Set rng = Range("A2:A" & lstRow)
'initializing outlook object to access its features
Set outApp = New Outlook.Application
On Error GoTo cleanup 'to handle any error during creation of object.
'Loop to iterate through each row, hold data in of email in variables and send
'mail to each email id.
For Each cell In rng
sendTo = Range(cell.Address).Offset(0, 0).Value2
subj = Range(cell.Address).Offset(0, 1).Value2
msg = Range(cell.Address).Offset(0, 2).Value2
Name = Range(cell.Address).Offset(0, 3).Value2
Company = Range(cell.Address).Offset(0, 4).Value2
Time = Range(cell.Address).Offset(0, 5).Value2
On Error Resume Next 'to hand any error during creation of below object
Set outMail = outApp.CreateItem(0)
'Writing and sending mail in new mail
With outMail
.To = sendTo
.Subject = subj
strbody = msg & vbNewLine & Name & " " & Company & " " & Time
.Body = strbody
.Send 'this send mail without any notification. If you want see mail
'before send, use .Display method.
End With
On Error GoTo 0 'To clean any error captured earlier
Set outMail = Nothing 'nullifying outmail object for next mail
Next cell 'loop ends
cleanup: 'freeing all objects created
Set outApp = Nothing
Application.ScreenUpdating = True
Application.ScreenUpdating = True
End Sub
I have added two columns. In column F there are the users' name (without duplicate.I have added the last user. He doesn't have messages). In column G there are how many message there are for the user in column F.
Here an example
I have got a problem with foreach cell... and then I used the for loop (classic).
In this example I used another for. The first for check the user's name and with the second for check how many messages there are for the user. I have put one or more messages in the strbody variable. When the second for is finished, I insert the number of messages for the user (COLUMN G) and then send the email.
My Code:
Sub bulkMail()
Const COLUMN_F As Byte = 6
Const COLUMN_G As Byte = 7
Application.ScreenUpdating = False
ThisWorkbook.Activate
Dim outMail As Outlook.MailItem
'Creating variable to hold values of different items of mail
Dim sendTo, subj, msg, Name, Company, Time As String
Dim lstRow As Long
'add variable
Dim numberUsers, i,j, numberMsg As Integer
'My data is on sheet "Exceltip.com" you can have any sheet name.
ThisWorkbook.Sheets("Sheet2").Activate
'Getting last row of containing email id in column 1.
lstRow = Cells(Rows.Count, 1).End(xlUp).Row
'count number users in Column F -> 6. Here there are the users without duplicate name.
numberUsers = Cells(Rows.Count, COLUMN_F).End(xlUp).Row
'Variable to hold all email ids
'i didn't use range because i had problems with foreach (i don't know why)
'Dim rng As Range
'Set rng = Range("A2:A" & lstRow)
'initializing outlook object to access its features
Set outApp = New Outlook.Application
On Error GoTo cleanup 'to handle any error during creation of object.
'Loop to iterate through each row, hold data in of email in variables and send
'mail to each email id.
For i = 2 To numberUsers
numberMsg = 0
strbody = ""
'For Each cell In rng
For j = 2 To lstRow
'Name = Range(cell.Address).Offset(0, 3).Value2
Name = Cells(j, 1) ' I get the name column A
If (Cells(i, COLUMN_F) = Name) Then
numberMsg = numberMsg + 1 ' count the number of messages
sendTo = Cells(j, 1) 'Range(cell.Address).Offset(0, 0).Value2 - COLUMN A
subj = Cells(j, 5) 'Range(cell.Address).Offset(0, 1).Value2 - COLUMN E
msg = Cells(j, 4) 'Range(cell.Address).Offset(0, 2).Value2 - COLUMN D
'Name = cells(j,1)Range(cell.Address).Offset(0, 3).Value2
Company = Cells(j, 2) 'Range(cell.Address).Offset(0, 4).Value2 - COLUMN B
Time = Cells(j, 3) 'Range(cell.Address).Offset(0, 5).Value2 - COLUMN C
strbody = strbody & msg & vbNewLine & Name & " " & Company & " " & Time & vbNewLine
'Debug.Print (strbody)
End If
Next j 'loop ends
Cells(i, COLUMN_G) = numberMsg ' get in COLUMN G the number of message for the user in COLUMN F
On Error Resume Next 'to hand any error during creation of below object
'check if there is almost a message for a user
If (numberMsg <> 0) Then
Set outMail = outApp.CreateItem(0)
'Writing and sending mail in new mail
With outMail
.To = sendTo
.Subject = subj
'strbody = msg & vbNewLine & Name & " " & Company & " " & Time
.Body = strbody
.Send 'this send mail without any notification. If you want see mail
'before send, use .Display method.
End With
On Error GoTo 0 'To clean any error captured earlier
Set outMail = Nothing 'nullifying outmail object for next mail
End If
'Next cell 'loop ends
Next i
cleanup: 'freeing all objects created
Set outApp = Nothing
Application.ScreenUpdating = True
Application.ScreenUpdating = True
End Sub
before trying my code check if my cells match yours.
I have a create a bit of dynamic email where user is able to send multiple email based on how many data in the said column. The code itself will follow the textbox word by word and generate in the email body, but I am currently trying to make Excel open an Email Meeting template instead of a normal email.
Here is the code.
Sub send_mass_email()
Dim i As Integer
Dim name, email, body, subject, copy, place, business As String
Dim OutApp As Object
Dim OutMail As Object
body = ActiveSheet.TextBoxes("TextBox 1").Text
i = 2
'Loop down name column starting at row 2 column 1
Do While Cells(i, 1).Value <> ""
name = Split(Cells(i, 1).Value, " ")(0) 'extract first name
email = Cells(i, 2).Value
subject = Cells(i, 3).Value
copy = Cells(i, 4).Value
business = Cells(i, 5).Value
place = Cells(i, 6).Value
'replace place holders
body = Replace(body, "C1", name)
body = Replace(body, "C5", business)
body = Replace(body, "C6", place)
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.to = email
.cc = copy
.subject = subject
.body = body
'.Attachments.Add ("") 'You can add files here
.display
'.Send
End With
'reset body text
body = ActiveSheet.TextBoxes("TextBox 1").Text
i = i + 1
Loop
Set OutMail = Nothing
Set OutApp = Nothing
MsgBox "Email(s) Sent!"
End Sub
I have tried to use olmeeting but an error occurs: Object doesn't support this property or method .
There are no silly questions!
Please reference the VBA documentation here.
It seems that you want to modify this part of the code:
Set OutMail = OutApp.CreateItem(0)
to
Set OutMail = OutApp.CreateItem(1)
The documentation imples that by changing the parameter of .CreateItem method to one of the listed values here, you will achieve the desired effect. Please note I did not yet test it.
Sub SendEmail()
Dim OutlookApp As Object
Dim MItem As Object
Dim cell As Range
Dim email_ As String
Dim cc_ As String
Dim subject_ As String
Dim body_ As String
Dim attach_ As String
Dim StrBody As String
'Create Outlook object
Set OutlookApp = CreateObject("Outlook.Application")
'Loop through the rows
For Each cell In Sheets("publico").Range("H2:H2000").Cells.SpecialCells(xlCellTypeConstants)
If cell.Row <> 1 Then
If cell.Value <> "" Then ' to check email address cell is empty or not
email_ = cell.Value ' email address mention in the F column
Else
email_ = cell.Offset(0, 1).Value 'alternative email address
End If
subject_ = Sheets("CAPA").Range("D1").Value 'as of now i mentioned column B as subject, change the value accordingly
' body_ = Sheets("CAPA").Range("D2").Value 'please change the offset value based on the body content cell
StrBody = Sheets("CAPA").Range("D2").Value & "<br><br>" & _
Sheets("CAPA").Range("D3").Value & "<br><br>" & _
Sheets("CAPA").Range("F7").Value & "<br><br><br>"
**Sheets("publico").Range**
' cc_ = cell.Offset(0, 3).Value ' remove comments if you are going to use the cc and also change the offset value according to cc mail address cell value.
' attach_ = cell.Offset(0, 4).Value ' remove comments "'" if you going attache any file and change the offset value based on the attachment value position.
'Create Mail Item and send it
Set MItem = OutlookApp.CreateItem(0)
With MItem
.To = email_
' .CC = cc_
.Subject = subject_
.HTMLBody = StrBody
'.Attachments.Add attach_
'.Display
End With
MItem.Send
Sheets("publico").Range("J2").Value = "enviado"
End If
Next
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
So, for branch 100, manager 15, I will send line 1 and 2 of the sheet, to the manager mail only.
In the case of no manager assigned, the email will be directed to the head (email2).
After sending an e-mail, the F column must generate a log "OK".
EDIT:
I edited the code provided and the e-mail is going to the proper recipients.
Please try the below code.
Sub SendEmail()
Dim OutlookApp As Object
Dim MItem As Object
Dim cell As Range
Dim email_ As String
Dim cc_ As String
Dim subject_ As String
Dim body_ As String
Dim attach_ As String
'Create Outlook object
Set OutlookApp = CreateObject("Outlook.Application")
'Loop through the rows
For Each cell In Columns("f").Cells.SpecialCells(xlCellTypeConstants)
If cell.Row <> 1 Then
If cell.Value <> "" Then ' to check email address cell is empty or not
email_ = cell.Value 'email address mention in the F column
Else
email_ = cell.Offset(0, 1).Value 'alternative email address
End If
subject_ = cell.Offset(0, -4).Value 'as of now i mentioned column B as subject, change the value accordingly
body_ = cell.Offset(0, 2).Value 'please change the offset value based on the body content cell
' cc_ = cell.Offset(0, 3).Value ' remove comments if you are going to use the cc and also change the offset value according to cc mail address cell value.
' attach_ = cell.Offset(0, 4).Value ' remove comments "'" if you going attache any file and change the offset value based on the attachment value position.
'Create Mail Item and send it
Set MItem = OutlookApp.CreateItem(0)
With MItem
.To = email_
' .CC = cc_
.Subject = subject_
.Body = body_
'.Attachments.Add attach_
'.Display
End With
MItem.Send
cell.Value = "ok"
End If
Next
End Sub
Thanks,
Arun
I have code to create auto email based on the values in a table created in Excel. The code attaches only 1 file from cell value. If there are more than 1 files either in same cell or next column, I am sort of lost on how to achieve this being a novice in VBA field. Appreciate if anyone can help.
Below is my code:-
Sub SendEmailWithAttachmentAndBody()
'Created by Mirat for ****.
'This code will autocreate emails along relevant attachents. User needs to create a master data file to include following fields in respective columns.
'To = Column A.
'CC = Column B.
'Bcc = Column C.
'Subject = Column D.
'Body = Column E.
'Attachment = Column F.
'Only 1 file can be attached for now.
Dim OlAPP As Outlook.Application
Dim OlMail As Outlook.MailItem
For i = 2 To Sheet1.Cells(Rows.Count, 1).End(xlUp).Row
Set OlAPP = New Outlook.Application
Set OlMail = OlAPP.CreateItem(olMailItem)
MailAttachment = Application.Cells(i, 6).Value
With OlMail
.Display
End With
Signature = OlMail.Body
With OlMail
.To = Cells(i, 1).Value
.CC = Cells(i, 2).Value
.BCC = Cells(i, 3)
.Subject = Cells(i, 4).Value
.HTMLBody = Cells(i, 5).Value & "<br>" & .HTMLBody
.Attachments.Add MailAttachment
.Display
End With
Set OlMail = Nothing
Set OlAPP = Nothing
Next
End Sub
To answer your questions, I make the assumption that the attachments in column F are stored as a comma separated string.
With that in mind I would make MailAttachment a variant variable and do the following:
MailAttachment = Split (Application.Cells(i, 6).Value, ",")
Then later in the code I would loop through this array and attach each file.
For each item in MailAttachment
.Attachments.Add item
Next
That should do the trick.