How to import table and mail it using Excel? - excel

I am trying to send a table via email using Excel VBA Code. The Code is working good but it does not allow me to send data in the form of the table. The structure of the sheet is as under.
I want to send the table to start with Sr. NO. I am using the below code which is working perfectly. But it sends only data in the form of values rather than a table.
Sub Send_EmailFinal()
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("H5:L32")
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 = "Hi" & vbLf & vbLf & " body of message you want to add" & vbLf & vbLf & xEmailBody & vbNewLine
With xMailOut
.subject = "Test"
.To = ""
.CC = ""
.subject = "Productivity Report"
.body = xEmailBody
.Display
'.Send
End With
Set xMailOut = Nothing
Set xOutApp = Nothing
Application.ScreenUpdating = True
End Sub
Please check it and guide me where I am doing wrong. Thanks

Create a function to build the HTML and the code in your sub can be minimal.
Option Explicit
Sub Send_EmailFinal()
Dim xMailOut As Outlook.MailItem
Dim xOutApp As Outlook.Application
Set xOutApp = CreateObject("Outlook.Application")
Set xMailOut = xOutApp.CreateItem(olMailItem)
With xMailOut
.BodyFormat = olFormatHTML
.To = "###"
.CC = ""
.Subject = "Productivity Report"
.HTMLBody = ToHTML(ActiveSheet.Range("H5:L32"))
.Display
'.Send
End With
Set xMailOut = Nothing
Set xOutApp = Nothing
End Sub
Function ToHTML(rng As Range) As String
Dim row As Range, cell As Range
Dim n As Long, s As String
s = "<p>Good Afternoon</p><p>Please see your productivity for lastweek, " & _
"any questions or concerns please let me or Claudia know</p>"
' table header
s = s & "<table border=""1"" width=""50%"" cellspacing=""0"" cellpadding=""3"" align=""center"">" & _
"<tr align=""center"" bgcolor=""#CCCCCC"">"
Set row = rng.Rows(1)
For Each cell In row.cells
s = s & "<th>" & cell & "</th>"
Next
s = s & "</tr>" & vbCrLf
' data
For n = 2 To rng.Rows.Count
Set row = rng.Rows(n)
' skip blank lines
If Len(row.cells(1, 1)) > 0 Then
s = s & "<tr align=""center"">"
For Each cell In row.cells
s = s & "<td>" & cell & "</td>"
Next
s = s & "</tr>" & vbCrLf
End If
Next
ToHTML = s & "</table>"
End Function

For my limited applications, I am sending more basic emails that do not require the use of the Outlook object.
Try the following code that sends whatever is selected on your screen.
In a new workbook write something in several cells, select them then run the code (do not expect somebody to answer the from that email address).
Sub EmailSelectedRange()
ActiveWorkbook.EnvelopeVisible = True
With ActiveSheet.MailEnvelope
.Item.To = "ThisIsAFakeEmailAddress#ThisIsAFakeEmailAddress.com"
.Item.Subject = "This is the subject of the email"
.Introduction = "This is a text in the email"
.Item.Send
End With
End Sub

Related

Automated emails based on data in Excel sheet

I need to send and email based on the expiry date of different machines.
I want to include all the expired machines in one email, as opposed to multiple emails.
The Excel sheet includes expiration date in column "I", the name of the machine in column "B", and has a function that calculates if my machines are "calibrated", "expired", or "near expiration", in column "P".
Private Sub Workbook_Open()
Dim Instrument As String
Dim Status As String
Status = Range("P6").Value
If IsNull(Status) = True Then Exit Sub
If Status = "Expiring Soon" Then
Instrument = Range("B6").Value
Mail_Expiring_Soon_Outlook Instrument
End If
If Status = "Expired" Then
Instrument = Range("B6").Value
Mail_Expired_Outlook Instrument
End If
End Sub
Sub Mail_Expiring_Soon_Outlook(Instrument As String)
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Attention" & vbNewLine & vbNewLine & _
"The " & Instrument & " calibration is due within 30 days." & vbNewLine & vbNewLine & _
"Please arrange calibration."
On Error Resume Next
With xOutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = "Calibration Due within 30 days"
.Body = xMailBody
.Display
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
Sub Mail_Expired_Outlook(Instrument As String)
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Warning!" & vbNewLine & vbNewLine & _
"The " & Instrument & " calibration is expired." & vbNewLine & vbNewLine & _
"Please arrange calibration."
On Error Resume Next
With xOutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = "Warning! Calibration is Expired"
.Body = xMailBody
.Display
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
If I've understood what you're aiming for, you could simply loop through all the rows adding machine names to one of two variables depending on the status.
You could use something like the following...
Private Sub Workbook_Open()
Dim ExpiringSoon As String
Dim Expired As String
Dim Subject As String
Dim Body As String
Dim Row As Long
' Loop through rows, from row 2 until the last used row in column B
For Row = 2 To Cells(Rows.Count, "B").End(xlUp).Row
Select Case Cells(Row, "P")
Case "Expiring Soon"
ExpiringSoon = ExpiringSoon & Cells(Row, "B") & vbNewLine
Case "Expired"
Expired = Expired & Cells(Row, "B") & vbNewLine
End Select
Next
If ExpiringSoon <> "" Then
Subject = "Calibration Due within 30 days"
Body = "Attention" & vbNewLine & vbNewLine & _
"Calibration is due within 30 days for the following machines:" & vbNewLine & _
ExpiringSoon & vbNewLine & _
"Please arrange calibration."
Send_Mail Subject, Body
End If
If Expired <> "" Then
Subject = "Warning! Calibration is Expired"
Body = "Warning!" & vbNewLine & vbNewLine & _
"Calibration is expired for the following machines:" & vbNewLine & _
Expired & vbNewLine & _
"Please arrange calibration."
Send_Mail Subject, Body
End If
End Sub
Sub Send_Mail(Subject As String, Body As String)
On Error Resume Next
With CreateObject("Outlook.Application").CreateItem(0)
.Subject = Subject
.BodyFormat = 1
.Body = Body
.Display
End With
End Sub
Private Sub Workbook_Open()
Dim Instrument1 As String
Dim Instrument2 As String
Dim ws As Worksheet
Dim Status As String
Set ws = Sheets("DAQ Fault Log")
lr = ws.Range("A" & Rows.Count).End(xlUp).Row
' MsgBox "This code ran at Excel start!"
' On Error Resume Next
' If Target.Cells.Count > 1 Then Exit Sub
counter1 = 0
counter2 = 0
On Error Resume Next
For i = 2 To lr
Status = ws.Range("P" & i).Value
If Status = "Expiring Soon" Then
Instrument1 = Instrument1 & ws.Range("B" & i).Value & ", "
counter1 = counter1 + 1
End If
If Status = "Expired" Then
Instrument2 = Instrument2 & ws.Range("B" & i).Value & ", "
counter2 = counter2 + 1
End If
Next i
If counter1 > 0 And counter1 = 1 Then Mail_Expiring_Soon_Outlook Left(Instrument1, Len(Instrument1) - 2)
If counter1 > 0 And counter1 > 1 Then Mail_Expiring_Soon_Outlook Left(Instrument1, Len(Instrument1) - 1)
If counter2 > 0 And counter2 = 1 Then Mail_Expired_Outlook Left(Instrument2, Len(Instrument2) - 2)
If counter2 > 0 And counter2 > 1 Then Mail_Expired_Outlook Left(Instrument2, Len(Instrument2) - 1)
End Sub
Sub Mail_Expiring_Soon_Outlook(Instrument1 As String)
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Attention" & vbNewLine & vbNewLine & _
"The " & Instrument1 & " calibration is due within 30 days." & vbNewLine & vbNewLine & _
"Please arrange calibration."
On Error Resume Next
With xOutMail
.to = ""
.CC = ""
.BCC = ""
.Subject = "Calibration Due within 30 days"
.Body = xMailBody
.Display 'or use .Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
Sub Mail_Expired_Outlook(Instrument2 As String)
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Warning!" & vbNewLine & vbNewLine & _
"The " & Instrument2 & " calibration is expired." & vbNewLine & vbNewLine & _
"Please arrange calibration."
On Error Resume Next
With xOutMail
.to = ""
.CC = ""
.BCC = ""
.Subject = "Warning! Calibration is Expired"
.Body = xMailBody
.Display 'or use .Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub

Create Outlook Email Body with rows having a particular value using Excel VBA

I've used an example to create code to send emails from Excel (with Outlook), using a "Button" (red in my file).
The code works. There is a pre-selected range of rows [B1:K20], that can be manually modified thanks to the Application.InputBox function.
Sub MAIL()
Dim rng As Range
Dim OutApp As Object
Dim OutMail As Object
Dim StrBodyIn, StrBodyEnd As String
StrBodyIn = "Bonjour," & "<br>" & _
" " & "<br>" & _
"Buongiorno," & "<br>"
StrBodyEnd = " " & "<br>" & _
"Cordialement" & "<br>" & _
" " & "<br>" & _
Range("M2") & "<br>"
Set rng = Nothing
On Error Resume Next
Set rng = Sheets("TEST").Application.InputBox("Range", xTitleId, "B1:K20", Type:=8)
On Error GoTo 0
If rng Is Nothing Then
MsgBox "ATTENZIONE!!!" & _
vbNewLine & "Seleziona un range di celle valido.", vbOKOnly
Exit Sub
End If
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "email#gmail.com"
.CC = ""
.BCC = ""
.Subject = "SITUATION"
.HTMLBody = "<p style='font-family:calibri;font-size:16'>" & StrBodyIn & RangetoHTML(rng) & "<p style='font-family:calibri;font-size:16'>" & StrBodyEnd
.Display 'or use .Send
End With
On Error GoTo 0
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
I want to add a condition.
The selected range of rows should be copied to the body of the email if the "X" symbol is written in the column "A".
In my example, rows n° 1, 2 and n° 5 should be copied.
The two tasks here are separate so I would code them as such. Here would be my approach. Separate your sub into two logical procedures.
Determine the body range
Send the email with the range
Determine the body range
Link your button to this macro. The macro will take an input and convert it into a single column range (Column B). We will then loop through the selected range and look at Column A to determine if there is an x or not. If an x is present, we will resize the range back to it's original size and add it to a collection of cells (Final).
Once the loop is complete, the macro will then do one of the following:
If the range is empty, it will prompt your message box and end the sub (your email macro is never initiated)
If the range is not empty, we will call your EMAIL macro and pass the range along to it.
Sub EmailRange()
Dim Initial As Range, Final As Range, nCell As Range
On Error Resume Next
Set Initial = Sheets("TEST").Application.InputBox("Range", xTitleId, "B1:K20", Type:=8)
On Error GoTo 0
For Each nCell In Initial.Resize(Initial.Rows.Count, 1)
If nCell.Offset(, -1) = "X" Then
If Not Final Is Nothing Then
Set Final = Union(Final, nCell.Resize(1, Initial.Columns.Count))
Else
Set Final = nCell.Resize(1, Initial.Columns.Count)
End If
End If
Next nCell
If Not Final Is Nothing Then
MAIL Final
Else
MsgBox "ATTENZIONE!!!" & vbNewLine & "Seleziona un range di celle valido.", vbOKOnly
End If
End Sub
Send the email with the range
Notice that the macro now has an input (On first line). If the sub is called, you no longer need to validate anything since this was all done in the original sub!
Sub MAIL(Final as Range)
Dim OutApp As Object, OutMail As Object
Dim StrBodyIn As String, StrBodyEnd As String
StrBodyIn = "Bonjour," & "<br>" & " " & "<br>" & "Buongiorno," & "<br>"
StrBodyEnd = " " & "<br>" & "Cordialement" & "<br>" & " " & "<br>" & Range("M2") & "<br>"
Application.EnableEvents = False
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "email#gmail.com"
.CC = ""
.BCC = ""
.Subject = "SITUATION"
.HTMLBody = "<p style='font-family:calibri;font-size:16'>" & StrBodyIn & RangetoHTML(Final) & "<p style='font-family:calibri;font-size:16'>" & StrBodyEnd
.Display 'or use .Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub

Excel VBA - How to run the same macro at the same time on all the sheets - generating one email

I continue my work starting from the 1st question here:
Excel VBA - Outlook Email - Body created with rows having a particular value
Now i have another problem.
I want to repeat the below MACROs on all the SHEETS of my file.
In particular, how can I repeat this function on different SHEETS by only clicking in 1 button present in all the sheets?
All the sheets have the same structure.
I mean, the table resulting in the email must be implemented by adding the datas in all the sheets.
The data should be copied starting from the 1st sheet, for ex. TEST(1) to the last sheet, TEST(9).
The email generated after this process must be ONLY one.
Determine the body range
Sub EmailRange()
Dim Initial As Range, Final As Range, nCell As Range
On Error Resume Next
Set Initial = Sheets("TEST").Application.InputBox("Range", xTitleId, "B1:K20", Type:=8)
On Error GoTo 0
For Each nCell In Initial.Resize(Initial.Rows.Count, 1)
If nCell.Offset(, -1) = "X" Then
If Not Final Is Nothing Then
Set Final = Union(Final, nCell.Resize(1, Initial.Columns.Count))
Else
Set Final = nCell.Resize(1, Initial.Columns.Count)
End If
End If
Next nCell
If Not Final Is Nothing Then
MAIL Final
Else
MsgBox "ATTENZIONE!!!" & vbNewLine & "Seleziona un range di celle valido.", vbOKOnly
End If
End Sub
Send the email with the range
Sub MAIL(Final as Range)
Dim OutApp As Object, OutMail As Object
Dim StrBodyIn As String, StrBodyEnd As String
StrBodyIn = "Bonjour," & "<br>" & " " & "<br>" & "Buongiorno," & "<br>"
StrBodyEnd = " " & "<br>" & "Cordialement" & "<br>" & " " & "<br>" & Range("M2") & "<br>"
Application.EnableEvents = False
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "email#gmail.com"
.CC = ""
.BCC = ""
.Subject = "SITUATION"
.HTMLBody = "<p style='font-family:calibri;font-size:16'>" & StrBodyIn & RangetoHTML(Final) & "<p style='font-family:calibri;font-size:16'>" & StrBodyEnd
.Display 'or use .Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
I've tried with something like this, but it does not work:
For I = 1 To Worksheets.Count
Sheets(I).Select
***[...]CODE OF "Determine the body range"***
Next I
Sheets("TEST(I)").Select

Hide screen updating when sending mail with Outlook

I have to send reports to over 400 email addresses (on column B). The filepaths for each report are on columns C, D and E.
With this post: How to add default signature in Outlook the signature is added when the .display method is used.
The signature I want to show is for user number 1. I've selected the corresponding signature as a default signature for new messages.
This signature contains a picture, but this doesn't seem to cause any problems.
I wouldn't want the macro to show the mail every time it sends the mail, because I want to avoid the constant blinking on the screen.
I tried to look for something like "hide" method from here but didn't find anything useful (.display would run in the background, and it would stay hidden from the user). Other idea was to add application.screenupdating = false and correspondingly true in the end, but this didn't have any impact.
How could I display the email in the background without showing it every time to the user?
Sub sendFiles_weeklyReports()
Dim OutApp As Object
Dim OutMail As Object
Dim sh As Worksheet
Dim EmailCell As Range
Dim FileCell As Range
Dim rng As Range
Dim lastRow As Long
Dim timestampColumn As Long
Dim fileLogColumn As Long
Dim i As Long
Dim strbody As String
Dim receiverName As String
Dim myMessage As String
Dim reportNameRange As String
Dim answerConfirmation As Variant
Application.ScreenUpdating = False
Set sh = Sheets("Report sender")
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.createitem(0)
lastRow = sh.Cells(Rows.Count, "B").End(xlUp).Row
i = 0
reportNameRange = "C1:E1"
timestampColumn = 17 'based on offset on EmailCell (column B)!
fileLogColumn = 18 'based on offset on EmailCell (column B)!
myMessage = "Are you sure you want to send weekly reports?" & vbNewLine & "'" & _
sh.Range("C2").Value & "', " & vbNewLine & "'" & sh.Range("D2").Value & "' and " & vbNewLine & _
"'" & sh.Range("E2").Value & "'?"
answerConfirmation = MsgBox(myMessage, vbYesNo, "Send emails")
If answerConfirmation = vbYes Then
GoTo Start
End If
If answerConfirmation = vbNo Then
GoTo Quit
End If
Start:
For Each EmailCell In sh.Range("B3:B" & lastRow)
EmailCell.Offset(0, fileLogColumn).ClearContents
EmailCell.Offset(0, timestampColumn).ClearContents
Set rng = sh.Cells(EmailCell.Row, 1).Range(reportNameRange)
If EmailCell.Value Like "?*#?*.?*" And Application.WorksheetFunction.CountA(rng) > 0 Then
With OutMail
For Each FileCell In rng
If Trim(FileCell) <> "" Then
If Dir(FileCell.Value) <> "" Then 'checks if there's a file path in the cell
.Attachments.Add FileCell.Value
EmailCell.Offset(0, fileLogColumn).Value = EmailCell.Offset(0, fileLogColumn).Value & ", " & _
Dir(FileCell.Value)
i = i + 1
End If
End If
Next FileCell
receiverName = EmailCell.Offset(0, -1).Value
strbody = "<BODY style=font-size:11pt;font-family:Calibri><p>Dear " & receiverName & ",</p>" & _
"<p>Please find attached the weekly reports.</p>" & _
"<p>Kind regards,</p></BODY>"
.SendUsingAccount = OutApp.Session.Accounts.Item(1)
.To = EmailCell.Value
.Subject = "Weekly Reporting – " & UCase("w") & "eek " & Format(Date, "ww") _
& " " & UCase(Left(Format(Date, "mmmm"), 1)) & Right(Format(Date, "mmmm"), _
Len(Format(Date, "mmmm")) - 1) & " " & Year(Now)
.display
.HTMLBody = strbody & .HTMLBody
.Send
EmailCell.Offset(0, timestampColumn).Value = Now
SkipEmail:
End With
Set OutMail = Nothing
End If
Next EmailCell
Set OutApp = Nothing
Application.ScreenUpdating = True
Call MsgBox("Weekly reports have been sent.", vbInformation, "Emails sent")
Quit:
End Sub
Appears .GetInspector has the same functionality of .Display except the "display".
Sub generateDefaultSignature_WithoutDisplay()
Dim OutApp As Object ' If initiated outside of Outlook
Dim OutMail As Object
Dim strbody As String
Dim receiverName As String
receiverName = const_meFirstLast ' My name
strbody = "<BODY style=font-size:11pt;font-family:Calibri><p>Dear " & receiverName & ",</p>" & _
"<p>Please find attached the weekly reports.</p>" & _
"<p>Kind regards,</p></BODY>"
Set OutApp = CreateObject("Outlook.Application") ' If initiated outside of Outlook
Set OutMail = OutApp.CreateItem(0)
With OutMail
.SendUsingAccount = OutApp.Session.Accounts.Item(1)
.To = const_emAddress ' My email address
.Subject = "Weekly Reporting – " & UCase("w") & "eek " & Format(Date, "ww") _
& " " & UCase(Left(Format(Date, "mmmm"), 1)) & Right(Format(Date, "mmmm"), _
Len(Format(Date, "mmmm")) - 1) & " " & Year(Now)
' Default Signature
' Outlook 2013
' There is a report that .GetInspector is insufficient
' to generate the signature in Outlook 2016
'.GetInspector ' rather than .Display
' Appears mailitem.GetInspector was not supposed to be valid as is
' .GetInspector is described here
' https://learn.microsoft.com/en-us/office/vba/api/outlook.mailitem.getinspector
Dim objInspector As Inspector
Set objInspector = .GetInspector
.HTMLBody = strbody & .HTMLBody
.Send
End With
ExitRoutine:
Set OutApp = Nothing
Set OutMail = Nothing
End Sub

vba to automatically email select sheet in spreadsheet if condition is met

I am trying out a couple different ways to automatically email using VBA and having trouble with the 2 items listed below. The VB does run as is but I would like to try to incorporate these two items if possible. Thank you :).
only attach sheet2(attachment). The file is located in bold in the code below.
only send the attachment if comment 2 is checked (cell D2)
VB
Private Sub CommandButton1_Click()
Dim WS As Worksheet, Rng As Range, c As Range
Dim OutApp As Object, OutMail As Object
Dim Msg As String, Addr As String, FName As String, i As Long
Dim obj As Object
Dim MyFile As String
**MyFile = "L:\NGS\HLA LAB\total quality management\QC & QA\DOSE reports\DOSE reporting form.xlsm"**
If Dir(MyFile) = "" Then
MsgBox "The file to attach was not found here:" & vbLf & vbLf & MyFile, vbExclamation, "Exiting"
GoTo Abort
End If
On Error Resume Next
Set obj = GetObject(, "Outlook.Application")
On Error GoTo 0
If obj Is Nothing Then
Set obj = CreateObject("Outlook.Application")
End If
Set OutApp = CreateObject("Outlook.Application")
Set WS = ThisWorkbook.Sheets("Email")
Set Rng = WS.Range("A2", WS.Range("A" & Rows.Count).End(xlUp))
For Each c In Rng
Msg = Msg & "For " & c.Offset(, 1) & Chr(14) & Chr(14)
For i = 3 To 14
If WS.Cells(c.Row, i) = "x" Then
Msg = Msg & " -" & WS.Cells(1, i) & Chr(14)
End If
Next
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = c.Offset(, 0)
.CC = ""
.BCC = ""
.Subject = "Daily Operational Safety Briefing"
.Body = Msg
.Attachments.Add MyFile, 1
.Send
End With
MsgBox "The data has been emailed sucessfully.", vbInformation
Next c
Set OutMail = Nothing
Abort: Application.Quit
Set OutApp = Nothing
End Sub
Update
Dim MyFile As String, MyFileCopy As String
MyFileCopy = "L:\NGS\HLA LAB\total quality management\QC & QA\DOSE reports\DOSE reporting form Sheet2.xlsm"
' no need to look for MyFile because you are working within it ...
'MyFile = "L:\NGS\HLA LAB\total quality management\QC & QA\DOSE reports\DOSE reporting form.xlsm"
' If Dir(MyFile) = "" Then
'
' MsgBox "The file to attach was not found here:" & vbLf & vbLf & MyFile, vbExclamation, "Exiting"
' GoTo Abort
'
' End If
'create a separate sheet2 to mail out
Sheets(2).Copy
Set wkb = ActiveWorkbook
With wkb
.SaveAs MyFileCopy
.Close True
End With
'this is not needed, since you set the outlook app below
' On Error Resume Next
' Set obj = GetObject(, "Outlook.Application")
' On Error GoTo 0
' If obj Is Nothing Then
' Set obj = CreateObject("Outlook.Application")
' End If
Set OutApp = CreateObject("Outlook.Application")
Set WS = ThisWorkbook.Sheets("Email")
Set Rng = WS.Range("A2", WS.Range("A" & Rows.Count).End(xlUp))
For Each c In Rng
If c.Offset(, 3) = "x" Then 'Not sure how you have Comment2 "checked" in column D
Msg = Msg & "For " & c.Offset(, 1) & Chr(14) & Chr(14)
For i = 3 To 14
If WS.Cells(c.Row, i) = "x" Then
Msg = Msg & " -" & WS.Cells(1, i) & Chr(14)
End If
Next
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = c.Offset(, 0)
.CC = ""
.BCC = ""
.Subject = "Daily Operational Safety Briefing"
.Body = Msg
.Attachments.Add MyFileCopy, 1
.Send
End With
End If
Next c
MsgBox "The data has been emailed sucessfully.", vbInformation
Set OutMail = Nothing
Set OutApp = Nothing
Abort:
Application.Quit 'This will kill the Excel application, is this really what you want?
End Sub
See the below code. I placed a section to make a copy workbook with sheet2 to send as an attachment as well as added in the condition for D2 (assume column for each row) to check for the condition. See my comments, as I took some liberties without knowing how your exact data works. I also cleaned up some of the stuff that looked superfluous.
Private Sub CommandButton1_Click()
Dim WS As Worksheet, Rng As Range, c As Range
Dim OutApp As Object, OutMail As Object
Dim Msg As String, Addr As String, FName As String, i As Long
Dim obj As Object
Dim MyFile As String, MyFileCopy As String
MyFileCopy = "L:\NGS\HLA LAB\total quality management\QC & QA\DOSE reports\DOSE reporting form Attachment.xlsm"
' no need to look for MyFile because you are working within it ...
'MyFile = "L:\NGS\HLA LAB\total quality management\QC & QA\DOSE reports\DOSE reporting form.xlsm"
' If Dir(MyFile) = "" Then
'
' MsgBox "The file to attach was not found here:" & vbLf & vbLf & MyFile, vbExclamation, "Exiting"
' GoTo Abort
'
' End If
'create a separate sheet2 to mail out
Sheets(2).Copy
Set wkb = ActiveWorkbook
With wkb
.SaveAs MyFileCopy
.Close True
End With
'this is not needed, since you set the outlook app below
' On Error Resume Next
' Set obj = GetObject(, "Outlook.Application")
' On Error GoTo 0
' If obj Is Nothing Then
' Set obj = CreateObject("Outlook.Application")
' End If
Set OutApp = CreateObject("Outlook.Application")
Set WS = ThisWorkbook.Sheets("Email")
Set Rng = WS.Range("A2", WS.Range("A" & Rows.Count).End(xlUp))
For Each c In Rng
If c.Offset(, 3) = "Checked" Then 'Not sure how you have Comment2 "checked" in column D
Msg = Msg & "For " & c.Offset(, 1) & Chr(14) & Chr(14)
For i = 3 To 14
If WS.Cells(c.Row, i) = "x" Then
Msg = Msg & " -" & WS.Cells(1, i) & Chr(14)
End If
Next
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = c.Offset(, 0)
.CC = ""
.BCC = ""
.Subject = "Daily Operational Safety Briefing"
.Body = Msg
.Attachments.Add MyFileCopy, 1
.Send
End With
End If
Next c
MsgBox "The data has been emailed sucessfully.", vbInformation
Set OutMail = Nothing
Set OutApp = Nothing
Abort:
Application.Quit 'This will kill the Excel application, is this really what you want?
End Sub

Resources