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.
Related
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.
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'm working towards improving my efficiency at my workplace. For this there is a task of sending an e-mail to a list of people.
For this I have created the following code. Would like to know if this can be improved? This code takes the information from sheet "Final_list" in a workbook and headers are in row 1.
Sub EmailToAll()
Dim outlookApp As Outlook.Application
Dim outlookMail As Outlook.MailItem
Set outlookApp = CreateObject("Outlook.Application")
Set outlookMail = outlookApp.CreateItem(olMailItem)
Dim sh As Worksheet
Dim RowCount As Integer
Worksheets("Final_List").Activate
RowCount = 2
Set sh = ActiveSheet
Do While IsEmpty(sh.Cells(RowCount, 1).Value) = False
Set outlookApp = CreateObject("Outlook.Application")
Set outlookMail = outlookApp.CreateItem(olMailItem)
With outlookMail
'MsgBox sh.Cells(RowCount, 7).Value
.To = sh.Cells(RowCount, 7).Value
.CC = sh.Cells(RowCount, 9).Value
.BCC = Empty
.Subject = "[Update]" & " " & sh.Cells(RowCount, 1).Value & "-" & sh.Cells(RowCount, 8).Value
.BodyFormat = 2
.HTMLBody = "Hello "
'.Display
'.Save
'.Close
.Send
'MsgBox "Mail saved for" & sh.Cells(RowCount, 7).Value & "!"
RowCount = RowCount + 1
End With
Loop
Set outlookMail = Nothing
Set outlookApp = Nothing
MsgBox "All mails sent!"
End Sub
You do not need to create Outlook Object twice . Set outlookApp = CreateObject("Outlook.Application") and change Dim RowCount As Integer to Dim RowCount As Long
Also avoid .Activate
Option Explicit
Sub EmailToAll()
Dim outlookApp As Outlook.Application
Dim outlookMail As Outlook.MailItem
Dim RowCount As Long
Set outlookApp = CreateObject("Outlook.Application")
RowCount = 2
With Worksheets("Final_List")
Do While IsEmpty(Cells(RowCount, 1).Value) = False
Set outlookMail = outlookApp.CreateItem(olMailItem)
With outlookMail
.To = Cells(RowCount, 7).Value
.CC = Cells(RowCount, 9).Value
.BCC = Empty
.Subject = "[Update]" & " " & Cells(RowCount, 1).Value & "-" & Cells(RowCount, 8).Value
.BodyFormat = 2
.HTMLBody = "Hello "
.Send
End With
RowCount = RowCount + 1
Loop
End With
Set outlookMail = Nothing
Set outlookApp = Nothing
MsgBox "All mails sent!"
End Sub
Not sure exactly what parts of this you would like to optimise but after looking at your example, here are a couple of things which I would look at changing;
The only things which are changing within the loop are the recipients and the subject line, the body is always the same (obviously I don't know what is stored in those cells) but maybe you could just construct the recipients string within the loop which should work fine if you separate the email addresses with semi-colons and send one email instead of multiple emails?
The other thing which I would mention is that you are stopping when you encounter a blank line which means that the loop may not pick up all recipients if someone deleted that line by mistake. There are many much more robust ways of locating the end of the data you could use.
Hope that helps.