How to create a table in Excel VBA to Email? - excel

I send schedules from Excel every week and I want to convert the data to a table where the week number is one merged cell at the top and the day and date are at the top of each column.
I don't know how to rewrite the mail body message as a table. The code probably has a lot of unnecessary strings but it works. I'd like to add that I am VERY new to VBA, or any coding at all for that matter, and still learning.
Dim olApp As Outlook.Application
Set olApp = CreateObject("Outlook.Application")
Dim olMail As Outlook.MailItem
Set olMail = olApp.CreateItem(olMailItem)
olMail.To = what_address
olMail.Subject = subject_line
olMail.Body = mail_body
olMail.Send
End Sub
Sub SendSchedules()
row_number = 2
Do
DoEvents
row_number = row_number + 1
Dim mail_body_message As String
Dim full_name As String
Dim replace_Monday As String
Dim replace_Tuesday As String
Dim replace_Wednesday As String
Dim replace_Thursday As String
Dim replace_Friday As String
Dim replace_Saturday As String
Dim replace_Sunday As String
mail_body_message = ActiveSheet.Range("J1") & vbNewLine & ActiveSheet.Range("C1") & " " & ActiveSheet.Range("C2") & vbNewLine & ActiveSheet.Range("D1") & " " & ActiveSheet.Range("D2") & vbNewLine & ActiveSheet.Range("E1") & " " & ActiveSheet.Range("E2") & vbNewLine & ActiveSheet.Range("F1") & " " & ActiveSheet.Range("F2") & vbNewLine & ActiveSheet.Range("G1") & " " & ActiveSheet.Range("G2") & vbNewLine & ActiveSheet.Range("H1") & " " & ActiveSheet.Range("H2") & vbNewLine & ActiveSheet.Range("I1") & " " & ActiveSheet.Range("I2")
full_name = ActiveSheet.Range("B" & row_number)
mon_day = ActiveSheet.Range("C" & row_number)
tues_day = ActiveSheet.Range("D" & row_number)
wednes_day = ActiveSheet.Range("E" & row_number)
thurs_day = ActiveSheet.Range("F" & row_number)
fri_day = ActiveSheet.Range("G" & row_number)
satur_day = ActiveSheet.Range("H" & row_number)
sun_day = ActiveSheet.Range("I" & row_number)
week_number = ActiveSheet.Range("K2")
mail_body_message = Replace(mail_body_message, "replace_name_here", full_name)
mail_body_message = Replace(mail_body_message, "replace_week_number", week_number)
mail_body_message = Replace(mail_body_message, "replace_Monday", mon_day)
mail_body_message = Replace(mail_body_message, "replace_Tuesday", tues_day)
mail_body_message = Replace(mail_body_message, "replace_Wednesday", wednes_day)
mail_body_message = Replace(mail_body_message, "replace_Thursday", thurs_day)
mail_body_message = Replace(mail_body_message, "replace_Friday", fri_day)
mail_body_message = Replace(mail_body_message, "replace_Saturday", satur_day)
mail_body_message = Replace(mail_body_message, "replace_Sunday", sun_day)
MsgBox mail_body_message
Call SendEmail(ActiveSheet.Range("A" & row_number), "Schedule Week 1", mail_body_message)
Loop Until row_number = 12
End Sub
Nothing wrong with this code, but now I want to take this information and create a table out of it. Although I'm worried I need to re-write the entire thing, I'm not sure how.

There are many ways to create tables in excel, but I can only think of two good methods for emailing them.
You could use VBA to setup a temporary excel spreedsheet that formats the table in the correct format. At this point, then you can simple copy and paste the entire thing into an HTML email using VBA.
Or, with VBA you could simply generate your entire body of text using HTML and then send the entire HTML string to your email body.
I have used the HTML route many times, and it can save a ton of time and it is much more useful.
Edit: Here is an example of using HTML, it's pretty rough and I wrote it in my early days. Please note that this was modified from a use-case I have with it. So you might have to tweak it a bit.
Sub Dealer_Email(Sheet As String, Name As Variant, Recipient As Variant, Subject As Variant, _
Mon as Variant, Tues as Variant, Wednesday as Variant, Thurs as Variant, _
Friday as Variant, Optional Copy As String, Optional Blind_Copy As String, _
Optional Attach As String)
' Sheet = the Sheet name in which you wish to pull data from (this was designed for multiple sheets with identical layouts.
'Name = the Name in which will be entered into the generated email
'Recipient = the email address
'Subject = the subject line
'Optional Copy = If you wish to 'cc' someone on the email
'Optional Blind_copy = adds someone to 'bcc' on the email
'Optional attachment = You can define a file to be attached to the email
' Parts of this function came from https://www.rondebruin.nl/
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
Dim x, y As Variant
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(Sheet)
strbody = "<table>"
strbody = strbody & _
"<tr>" & _
"<td> | </td>" & _
"<td>" & Mon & "</td>" & _
"<td> | </td>" & _
"<td>" & Tues & "</td>" & _
"<td> | </td>" & _
"<td>" & Wednes & "</td>" & _
"<td> | </td>" & _
"<td>" & Thurs & "</td>" & _
"<td> | </td>" & _
"<td>" & Fri & "</td>" & _
"<td> | </td>" & _
"<td>" & Sat & "</td>" & _
"<td> | </td>" & _
"<td>" & Sun & "</td>" & _
"<td> | </td>" & "</tr></table>"
strbody = "<font>Good Day " & Name & ",<br><br>" & _
"Insert Message Here...<br>" & _
strbody & _
"<br>" & _
"If you have any questions, feel free to contact me.</font>"
2
On Error Resume Next
With OutMail
.Display
.To = Recipient
.CC = Copy
.BCC = Blind_Copy
.Subject = Subject
.htmlbody = strbody & .htmlbody
.Attachment = Attach
End With
OutMail.Display
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Note that this does require Microsoft Outlook to work. Part of this code did come from https://www.rondebruin.nl/.
You could easily add a loop, and have this repeat as needed for each line within the html chart.
EDIT (SECOND TIME AROUND):
Sub SendSchedules()
Dim row_number As Integer
row_number = 2
Do
DoEvents
row_number = row_number + 1
Dim mail_body_message As String
Dim full_name As String
Dim replace_Monday As String
Dim replace_Tuesday As String
Dim replace_Wednesday As String
Dim replace_Thursday As String
Dim replace_Friday As String
Dim replace_Saturday As String
Dim replace_Sunday As String
full_name = ActiveSheet.Range("B" & row_number).Value
mon_day = ActiveSheet.Range("C" & row_number).Value
tues_day = ActiveSheet.Range("D" & row_number).Value
wednes_day = ActiveSheet.Range("E" & row_number).Value
thurs_day = ActiveSheet.Range("F" & row_number).Value
fri_day = ActiveSheet.Range("G" & row_number).Value
satur_day = ActiveSheet.Range("H" & row_number).Value
sun_day = ActiveSheet.Range("I" & row_number).Value
week_number = ActiveSheet.Range("K2").Value
strbody = "<table>"
mail_body_message = strbody & _
"<tr>" & _
"<td> Full Name: </td>" & _
"<td>" & full_name & "</td></tr>" & _
"<tr><td>Week Number: </td>" & _
"<td>" & week_number & "</td></tr>" & _
"<tr><td>Monday: </td>" & _
"<td>" & mon_day & "</td></tr>" & _
"<tr><td>Tuesday: </td>" & _
"<td>" & tues_day & "</td></tr>" & _
"<tr><td>Wednesday: </td>" & _
"<td>" & wednes_day & "</td></tr>" & _
"<tr><td>Thursday: </td>" & _
"<td>" & thurs_day & "</td></tr>" & _
"<tr><td>Friday: </td>" & _
"<td>" & fri_day & "</td></tr>" & _
"<tr><td>Saturday: </td>" & _
"<td>" & satur_day & "</td></tr>" & _
"<tr><td>Sunday: </td>" & _
"<td>" & sun_day & "</td></tr>" & _
"</table>"
MsgBox mail_body_message
Loop Until row_number = 12
You will need to change another line of code from:
olMail.Body = mail_body
to the following.
olMail.htmlbody = mail_body & .htmlbody
I hope this helps out.

Related

VBA - Shell, Run Time Error 5 Invalid Procedure - Thunderbird Email with HTML table

I have a VBA code which allows to create an email(Thunderbird) and in email body appers HTML table based on cell values. Everythings works fine, but only until table has less then 19 rows and 24 columns. Then pops up Run Time Error 5 - line with Call Shell.
Here code for HTML Table(found in Net):
Function create_table(rng As Range) As String
Dim mbody As String
Dim mbody1 As String
Dim i As Long
Dim j As Long
mbody = "<TABLE width=""30%"" Border=""1"", Cellspacing=""0""><TR>" ' configure the table
'create Header row
For i = 1 To rng.Columns.Count
mbody = mbody & "<TD width=""100"", Bgcolor=""#000000"", Align=""Center""><Font Color=#FFFFFF><b><p style=""font-size:12px"">" & rng.Cells(1, i).Value & " </p></Font></TD>"
Next
' add data to the table
For i = 2 To rng.Rows.Count
mbody = mbody & "<TR>"
mbody1 = ""
For j = 1 To rng.Columns.Count
mbody1 = mbody1 & "<TD width=""80"", Align=""Center""><p style=""font-size:12px"">" & rng.Cells(i, j).Value & "</TD>"
Next
mbody = mbody & mbody1 & "</TR>"
Next
create_table = mbody
End Function
Code for email:
email = Worksheets("Sheet1").Range("B1").Value
subj = Worksheets("Sheet1").Range("B2").Value
body = "Hello" & "<br><br>" & _
create_table(ActiveSheet.Range("A1").CurrentRegion) & "</Table></Table>"
thund = "Thunderbird path" & _
" -compose " & """" & _
"to='" & email & "'," & _
"cc='" & cc & "'," & _
"bcc='" & bcc & "'," & _
"subject='" & subj & "'," & _
"body='" & body & "'" & """"
Call Shell(thund, vbNormalNoFocus)
Application.Wait (Now + TimeValue("0:00:03"))
Is there any limition? Is it possible to change it?
Thunderbird allows using a file for the body with the message parameter, use that instead of the body parameter
Dim FSO As New FileSystemObject
Set FSO = CreateObject("Scripting.FileSystemObject")
fname = FSO.GetTempName & ".html"
Set FileToCreate = FSO.CreateTextFile(fname)
FileToCreate.Write body
FileToCreate.Close
Email = Worksheets("Sheet1").Range("B1").Value
subj = Worksheets("Sheet1").Range("B2").Value
body = "Hello" & "<br><br>" & _
create_table(ActiveSheet.Range("A1").CurrentRegion) & "</Table></Table>"
thund = "Thunderbird path" & _
" -compose " & """" & _
"to='" & Email & "'," & _
"cc='" & cc & "'," & _
"bcc='" & bcc & "'," & _
"subject='" & subj & "'," & _
"message='" & fname & "'" & """"
Call Shell(thund, vbNormalNoFocus)
Kill fname
Application.Wait (Now + TimeValue("0:00:03"))

Change the format in text pasted to Outlook

I am trying to change the text so certain values from cells are either bold, underlined, red, or otherwise stand out from the surrounding text in the body of the email.
How can I do that?
For i = 10 To 18
If Not Cells(i, "A").Text = vbNullString Then
'Add to growing string
concatString = concatString + Cells(i, "A").Text & ", " & _
Cells(i, "B").Text & vbCr
concatString = concatString + "Assignment/Zone: " & _
Cells(i, "C").Text & vbNewLine & vbCr
End If
Next i
myMail.Body = Range("B2") & " Shift" & " - " & Format(Date, "mmmm dd, yyyy") _
& vbNewLine & vbNewLine & "Sergeant: " & Range("A6") & ", " & Range("B6") & _
vbNewLine & " Status: " & Range("C6") _
& vbNewLine & vbNewLine & "Corporal: " & Range("A8") & ", " & Range("B8") & _
vbNewLine & " Status: " & Range("C8") _
& vbNewLine & vbNewLine & "Assigned Deputies" & vbNewLine & vbNewLine & concatString
You need to look into using HTML-formatted content to apply the colors etc you want:
Dim oApp As Object, oMail As Object
Set oApp = CreateObject("outlook.application")
Set oMail = oApp.createitem(0)
oMail.Display
oMail.htmlBody = "<h1>This is a heading</h1>" & _
"<p style='color:#F00'>Some red text</p>" & _
"<p><u>Underlined</u></p>" & _
"<p><b>Bold</b></p>" & _
"<p><i>Italic</i></p>"
I needed to use <br> to put the resultant answer in the email body. <p> creates a new PARAGRAPH, while <br> just puts it on the next line.
& "<br><b><u>Status:</u></b>"
gives:
& "Status:" &
Instead of:
& "<p><b><u>Status:</u></b>"
Which gives:
& "Status:"
Thank you for your help!

Excel VBA to loop data into email body

I am trying to create a loop within VBA to have multiple selections from userform1's listbox2 when I hit the command button to draft an email with each selection in the following format. However, I can't figure out how to get more than just one selection into the body of the email. I tried to separate it into a "midbody" and add the code again, but it just adds the same entry twice. How can I make this loop work?
Private Sub CommandButton3_Click()
Dim objOutlook As Object
Dim objMail As Object
Dim midBody As String
Dim wksheet As String
Dim i As Integer
Set objOutlook = CreateObject("Outlook.Application")
Set objMail = objOutlook.CreateItem(0)
For i = 0 To ListBox2.ListCount - 1
If ListBox2.Selected(i) = True Then
wksheet = ListBox2.List(i)
Sheets(wksheet).Activate
End If
If wksheet = "" Then
MsgBox "Nothing is Selected"
objMail.To = "myemail#me.com"
'objMail.CC =
objMail.Subject = ""
Else
midBody = activesheet.Range("C" & Rows.Count).End(xlUp).Value & vbNewLine & _
activesheet.Range("D" & Rows.Count).End(xlUp).Value & " through " & activesheet.Range("E" & Rows.Count).End(xlUp).Value & " phase" & vbNewLine & _
"Phase ECD: " & activesheet.Range("F" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Baseline Finish: " & activesheet.Range("G" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Previous Finish: " & activesheet.Range("H" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Current Finish: " & activesheet.Range("I" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Weekly Schedule Variance: " & activesheet.Range("J" & Rows.Count).End(xlUp).Value & vbNewLine & _
"CUM VAR to Baseline: " & activesheet.Range("K" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Slip Reason: " & vbNewLine & _
"Critical Path: " & vbNewLine & vbNewLine
objMail.body = midBody & Sheets.Range("C" & Rows.Count).End(xlUp).Value & vbNewLine & _
Sheets.Range("D" & Rows.Count).End(xlUp).Value & " through " & Sheets.Range("E" & Rows.Count).End(xlUp).Value & " phase" & vbNewLine & _
"Phase ECD: " & Sheets.Range("F" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Baseline Finish: " & Sheets.Range("G" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Previous Finish: " & Sheets.Range("H" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Current Finish: " & Sheets.Range("I" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Weekly Schedule Variance: " & Sheets.Range("J" & Rows.Count).End(xlUp).Value & vbNewLine & _
"CUM VAR to Baseline: " & Sheets.Range("K" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Slip Reason: " & vbNewLine & _
"Critical Path: " & vbNewLine & vbNewLine
End If
i = i + 1
Next i
objMail.Save
'Close the object
Set objMail = Nothing
MsgBox "Done", vbInformation
End Sub
I have made some changes in your code .Shifted Next of For towards later part of the code to include processing of loop. Removed redundant midBody.
Try This:
Private Sub CommandButton3_Click()
Dim ws As Worksheet
Dim i As Integer
Dim Agent As String
Dim EmailID As String
Dim wksheet As String
Dim objOutlook As Object
Dim objMail As Object
With Me.ListBox2
For i = 0 To .ListCount - 1
If .Selected(i) Then
wksheet = .List(i)
Exit For
End If
End With
If wksheet = "" Then
MsgBox "Nothing is Selected", vbExclamation
Exit Sub
End If
'r = Application.Match(wksheet, mySheet.Columns(1), 0)'choose one as per your data structure
r = Application.Match(Agent, mySheet.Columns(1), 0) 'choose one as per your data structure
Set ws = ThisWorkbook.ActiveSheet
'EmailID = mySheet.Range("D" & r).Value 'Uncomment it if this is required
Set objOutlook = CreateObject("Outlook.Application")
Set objMail = objOutlook.CreateItem(0)
With objMail
.To = "myemail#me.com" ' Or EmailID
' .CC =
.subject = ""
.Body = ActiveSheet.Range("C" & Rows.Count).End(xlUp).Value & vbNewLine & _
ActiveSheet.Range("D" & Rows.Count).End(xlUp).Value & " through " & ActiveSheet.Range("E" & Rows.Count).End(xlUp).Value & " phase" & vbNewLine & _
"Phase ECD: " & ActiveSheet.Range("F" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Baseline Finish: " & ActiveSheet.Range("G" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Previous Finish: " & ActiveSheet.Range("H" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Current Finish: " & ActiveSheet.Range("I" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Weekly Schedule Variance: " & ActiveSheet.Range("J" & Rows.Count).End(xlUp).Value & vbNewLine & _
"CUM VAR to Baseline: " & ActiveSheet.Range("K" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Slip Reason: " & vbNewLine & _
"Critical Path: " & vbNewLine & vbNewLine
'.Display
'.Send
.Save
End With
Next i
Set objMail = Nothing
Set objOutlook = Nothing
MsgBox "Done", vbInformation
End Sub
EDIT: Another version of code which works at my end. I have not created a listbox but simulated its working. This program loops correctly and send emails multiple times. Please remove k variable as per your listbox code . It is only for checking correct looping of the ptogram. Earlier version of program can be adjusted to your requirements if you provide sample data as what is the structure of listbox, from where it is picking emailid of the recipient, sample data of your worksheet etc.
Private Sub Command3_Click()
Dim subject As String, Body As String
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim ws As Worksheet
Dim k As Integer
On Error Resume Next
Set ws = ThisWorkbook.ActiveSheet
Set OutApp = GetObject(, "Outlook.Application")
If OutApp Is Nothing Then
Set OutApp = CreateObject("Outlook.Application")
End If
On Error GoTo 0
k = 4 ' remove it only for checking correct loop
For intCurrentRow = 0 To k - 1 'List2.ListCount change k to List2.ListCount
Set OutMail = OutApp.CreateItem(olMailItem)
With OutMail
' List2.Selected(intCurrentRow) = True ' This is to be commented out after trials for looping
.To = "abc#gmail.com"
.subject = "Test 2nd time Email"
.Body = ActiveSheet.Range("C" & Rows.Count).End(xlUp).Value & vbNewLine & _
ActiveSheet.Range("D" & Rows.Count).End(xlUp).Value & " through " & ActiveSheet.Range("E" & Rows.Count).End(xlUp).Value & " phase" & vbNewLine & _
"Phase ECD: " & ActiveSheet.Range("F" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Baseline Finish: " & ActiveSheet.Range("G" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Previous Finish: " & ActiveSheet.Range("H" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Current Finish: " & ActiveSheet.Range("I" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Weekly Schedule Variance: " & ActiveSheet.Range("J" & Rows.Count).End(xlUp).Value & vbNewLine & _
"CUM VAR to Baseline: " & ActiveSheet.Range("K" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Slip Reason: " & vbNewLine & _
"Critical Path: " & vbNewLine & vbNewLine
.Send
End With
Next intCurrentRow
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Outlook snapshot shows it is looping properly which was your main problem.
EDIT2: Earlier version of program simulated at my end on sample basis is running correctly and sending multiple mails. I do not have idea of your data setup so simulated for looping which was your main problem. Please try the program as it is , retain a copy and then make suitable adjustments for your data specific situation.
Private Sub CommandButton3_Click()
Dim ws As Worksheet
Dim i As Integer
Dim Agent As String
Dim EmailID As String
Dim wksheet As String
Dim objOutlook As Object
Dim objMail As Object
' With Me.ListBox2
For i = 1 To 3
'For i = 0 To .ListCount - 1
' If .Selected(i) Then
' wksheet = .List(i)
' Exit For
' End If
'End With
If wksheet = "hello" Then
MsgBox "Nothing is Selected", vbExclamation
Exit Sub
End If
'r = Application.Match(wksheet, mySheet.Columns(1), 0)'choose one as per your data structure
' r = Application.Match(Agent, mySheet.Columns(1), 0) 'choose one as per your data structure
Set ws = ThisWorkbook.ActiveSheet
'EmailID = mySheet.Range("D" & r).Value 'Uncomment it if this is required
Set objOutlook = CreateObject("Outlook.Application")
Set objMail = objOutlook.CreateItem(0)
With objMail
.To = "abc#gmail.com" ' Or EmailID
' .CC =
.subject = "original test"
.Body = ActiveSheet.Range("C" & Rows.Count).End(xlUp).Value & vbNewLine & _
ActiveSheet.Range("D" & Rows.Count).End(xlUp).Value & " through " & ActiveSheet.Range("E" & Rows.Count).End(xlUp).Value & " phase" & vbNewLine & _
"Phase ECD: " & ActiveSheet.Range("F" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Baseline Finish: " & ActiveSheet.Range("G" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Previous Finish: " & ActiveSheet.Range("H" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Current Finish: " & ActiveSheet.Range("I" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Weekly Schedule Variance: " & ActiveSheet.Range("J" & Rows.Count).End(xlUp).Value & vbNewLine & _
"CUM VAR to Baseline: " & ActiveSheet.Range("K" & Rows.Count).End(xlUp).Value & vbNewLine & _
"Slip Reason: " & vbNewLine & _
"Critical Path: " & vbNewLine & vbNewLine
'.Display
.Send
'.Save
End With
Next i
Set objMail = Nothing
Set objOutlook = Nothing
MsgBox "Done", vbInformation
End Sub

How to convert a generated HTML table to an Excel sheet for emailing?

I inherited a database with a VBA module that inserts a data table into an Outlook email. I'd like to change that so that it attaches an Excel sheet of that same data to the email instead of inserting a table within the email body. I'm not sure how to alter the code to do that.
Can someone help with how to update this?
Here is the code:
Sub DCMEmailReviewVBA()
Dim rst As DAO.Recordset
Dim olApp As Outlook.Application
Dim objMail As Outlook.MailItem
Dim rst2 As DAO.Recordset
Dim strTableBeg As String
Dim strTableBody As String
Dim strTableEnd As String
Dim strFntNormal As String
Dim strTableHeader As String
Dim strFntEnd As String
Set rst2 = CurrentDb.OpenRecordset("select distinct DCM_Email from tDCMEmailList")
rst2.MoveFirst
'Create e-mail item
Set olApp = Outlook.Application
Set objMail = olApp.CreateItem(olMailItem)
'Do Until rst2.EOF
Set olApp = Outlook.Application
Set objMail = olApp.CreateItem(olMailItem)
'Define format for output
strTableBeg = "<table border=1 cellpadding=3 cellspacing=0>"
strTableEnd = "</table>"
strTableHeader = "<font size=3 face=" & Chr(34) & "Calibri" & Chr(34) & "><b>" & _
"<tr bgcolor=lightblue>" & _
"<TD align = 'left'>Card Type</TD>" & _
"<TD align = 'left'>Cardholder</TD>" & _
"<TD align = 'left'>ER or Doc No</TD>" & _
"<TD align = 'center'>Trans Date</TD>" & _
"<TD align = 'left'>Vendor</TD>" & _
"<TD align = 'right'>Trans Amt</TD>" & _
"<TD align = 'left'>TEM Activity Name or P-Card Log No</TD>" & _
"<TD align = 'left'>Status</TD>" & _
"<TD align = 'right'>Aging</TD>" & _
"</tr></b></font>"
strFntNormal = "<font color=black face=" & Chr(34) & "Calibri" & Chr(34) & " size=3>"
strFntEnd = "</font>"
Set rst = CurrentDb.OpenRecordset("SELECT * FROM tEmailData where DCM_email='" & rst2!DCM_Email & "' Order by Cardholder, Card_Type asc")
rst.MoveFirst
'Build HTML Output for the DataSet
strTableBody = strTableBeg & strFntNormal & strTableHeader
Do Until rst.EOF
strTableBody = strTableBody & _
"<tr>" & _
"<TD align = 'left'>" & rst!Card_Type & "</TD>" & _
"<TD align = 'left'>" & rst!Cardholder & "</TD>" & _
"<TD align = 'left'>" & rst!ERNumber_DocNumber & "</TD>" & _
"<TD align = 'center'>" & rst!Trans_Date & "</TD>" & _
"<TD align = 'left'>" & rst!Vendor & "</TD>" & _
"<TD align = 'right'>" & Format(rst!Trans_Amt, "currency") & "</TD>" & _
"<TD align = 'left'>" & rst!ACTIVITY_Log_No & "</TD>" & _
"<TD align = 'left'>" & rst!Status & "</TD>" & _
"<TD align = 'right'>" & rst!Aging & "</TD>" & _
"</tr>"
rst.MoveNext
Loop
'rst.MoveFirst
strTableBody = strTableBody & strFntEnd & strTableEnd
'rst.Close
'Set rst2 = CurrentDb.OpenRecordset("select distinct ch_email from t_TCard_CH_Email")
'rst2.MoveFirst
Call CaptureDCMBodyText
With objMail
'Set body format to HTML
.To = rst2!DCM_Email
.BCC = gDCMEmailBCC
.Subject = gDCMEmailSubject
.BodyFormat = olFormatHTML
.HTMLBody = .HTMLBody & gDCMBodyText
.HTMLBody = .HTMLBody & "<HTML><BODY>" & strFntNormal & strTableBody & " </BODY></HTML>"
.HTMLBody = .HTMLBody & gDCMBodySig
.SentOnBehalfOfName = "xxxx"
.Display
'.Send
End With
rst2.MoveNext
'Loop
Clean_Up:
rst.Close
rst2.Close
Set rst = Nothing
Set rst2 = Nothing
'Set dbs = Nothing
End Sub
Since it looks like you have no desire to play with the table editing portion of the code, this may work for your needs.
Within your With objMail section, something like this would work (changing the origin and filename):
sOrigin = "C:\Users\Desktop\"
sFilename = "MyExcelSheet.xlsx"
.Attachments.Add (sOrigin & sFilename)
Its unclear what your specific needs are, but this would suffice for a general way to attach an Excel Sheet to an email.
NOTE: I would highly suggest removing the portion of the code related to the creation of the output sheet to accomplish your final desired goal.
So sending the results as an attachment is actually much easier than sending as a table within the email, as long as you have a saved query with the data you need to send.
Basically, you can use the Docmd.SendObject function to send a saved query. As noted, however, this doesn't have the ability to specify the SendOnBehalfOf property. Take a look at the following code:
Sub DCMEmailReviewVBA()
' assuming you have a saved query called qData
' that contains SQL like the following:
' select SELECT *
' FROM tEmailData
' where DCM_email=(select top 1 DCM_Email from tDCMEmailList)
' order by Cardholder, Card_Type asc
Dim strTO as string
' there are better ways to do this, but this will quickly
' get us what we want
strTO = Dlookup("DCM_Email", "tDCMEmailList")
' the only thing this doesn't handle is the SendOnBehalfOfName
' if this is necessary to your process, you might want to stick with #Jiggles32
docmd.SendObject _
objecttype:=acSendQuery, _
objectname:="qData", _
outputformat:=acFormatXLSX , _
to:=strTO, _
cc:="", _
bcc:=gDCMEmailBCC, _
subject:=gDCMEmailSubject, _
messagetext:="anything you want to put in your email message", _
editmessage:=true
End Sub

Automatic e-mail with changes in the body - VBA

I have to create a VBA to send automatic e-mails (the body of the e-mail links the recipient to a specific project that he is responsible for). The problem that I encountered is the fact that a certain recipient (i.e. placed in "TO") can be responsible for more tasks. The VBA that I am using sends emails to each task (even if the person is responsible for more). What can I do to count through recipients, if it's greater than 1 to send the e-mail which includes all of the tasks. I really need your help.
<PRE>Sub SendEMail()
Dim OutApp As Object
Dim OutMail As Object
Dim lastRow As Long
Dim Ebody As String
lastRow = ThisWorkbook.Worksheets("Sheet1").Cells(Rows.Count, "B").End(xlUp).Row
For i = 2 To lastRow
Ebody = "<FONT SIZE = 4 name = Arial>" & "Dear " & Cells(i, "A").Value
& "<br>" _
& "<br>" _
& "Please note that the below mentioned projectd are in scope for reporting." & "<br>" _
& "<br>" _
& Cells(i, "C").Value & " - " & Cells(i, "E").Value & "<br>" _
& "xxxxx will investigate and action your notification according to priority and to ensure public safety." & "<br>" _
& "For further information, please phone xxxxx on 6111 and quote reference number:" & "<br>" _
& "Your original report can be seen below:" & "</Font>" & "<br>" _
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = Cells(i, "B").Value
.Cc = Cells(i, "D").Value
.Subject = "Your Registration Code"
.HtmlBody = Ebody
.Attachments.Add "C:\Test\Document.docx"
.Attachments.Add "C:\Test\Document1.docx"
.SentOnBehalfOfName = "Financial#yahoo.com"
.Display
End With
Next
End Sub </pre>
Sub Emailer()
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range, y, sbody
Dim eml As Worksheet, bd As Worksheet
Dim underlyingary, ISINarray, Accountarray, i
Set eml = Sheets("Emailer"): Set bd = Sheets("Body"): Set OutApp = CreateObject("Outlook.Application")
For Each y In eml.Range("A2:A" & eml.Range("A1000000").End(xlUp).Row)
If eml.Range("F" & y.Row) <> "" Then
underlyingary = Split(eml.Range("F" & y.Row), ",")
Accountarray = Split(eml.Range("G" & y.Row), ",")
ISINarray = Split(eml.Range("H" & y.Row), ",")
For i = 0 To UBound(underlyingary)
sbody = sbody & vbNewLine & "Underlying: " & WorksheetFunction.Proper(Trim(underlyingary(i))) & " Account Number: " & WorksheetFunction.Proper(Trim(Accountarray(i))) & " ISIN: " & WorksheetFunction.Proper(Trim(ISINarray(i))) & "<br>" & "<br>"
Next i
Else
sbody = sbody & vbNewLine & "Underlying: " & WorksheetFunction.Proper(Trim(eml.Range("C" & y.Row))) & " Account Number: " & WorksheetFunction.Proper(Trim(eml.Range("D" & y.Row))) & " ISIN: " & WorksheetFunction.Proper(Trim(eml.Range("E" & y.Row))) & "<br>"
End If
On Error GoTo cleanup
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = eml.Range("A" & y.Row)
.Subject = bd.Range("B2")
.cc = eml.Range("I" & y.Row)
.htmlBody = bd.Range("A2") _
& "<br>" & "<br>" & _
bd.Range("A3") & _
Trim(eml.Range("B" & y.Row)) & _
bd.Range("A4") _
& "<br>" & "<br>" & _
sbody _
& "<br>" & _
bd.Range("A5") _
& "<br>" & "<br>" & "<li>" & _
bd.Range("A6").Text & "</li>" & _
"<br>" & "<br>" & "<li>" & _
bd.Range("A7").Text & "</li>" & _
"<br>" & "<br>" & "<li>" & _
bd.Range("A8").Text & "</li>" & _
"<br>" & "<br>" & _
bd.Range("A9") _
& "<br>" & bd.Range("A10")
.display
End With
On Error GoTo 0
Set OutMail = Nothing
Next y
cleanup:
Set OutApp = Nothing
End Sub

Resources