My code is sending an e-mail through Outlook.
I want the value of two cells included in the e-mail body.
Formatting is working and the text is properly shown.
Also the cell value is shown properly in one of two cases.
For one part of the code, it is adding “ACCT:ACCT:ACCT:” in front of the cell value.
The cell value for cell (6,3) = Zeer Dringend
The cell value for cell (22,3) = 2019-0004
This is the e-mail body generated by the code
Beste Collega,
Een nieuwe retour zending registratie werd aangemaakt met urgentie: **ACCT:ACCT:ACCT:Zeer Dringend**.
Het pakket nummer is **2019-0004**.
In geval van vragen gelieve contact op te nemen.
Met vriendelijke groeten,
Where it shows ACCT:ACCT:ACCT:Zeer Dringend, it should say Zeer Dringend
This is the full code
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim WS As Worksheet
If ActiveWorkbook.Path <> "" Then
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
Set WS = Sheets("Ingave")
strbody = "<font size=""3"" face=""Calibri"">" & _
"Beste Collega,<br><br>" & _
"Een nieuwe retour zending registratie werd aangemaakt met urgentie: <B>" & WS.Cells(6, 3).Value & "</B>.<br>" & _
"Het pakket nummer is <B>" & WS.Cells(22, 3).Value & "</B>.<br><B> " & _
"</B><br><br>In geval van vragen gelieve contact op te nemen." & _
"<br><br> Met vriendelijke groeten, </font>"
On Error Resume Next
With OutMail
.to = "xxx#yyy"
.CC = ""
.BCC = ""
.Subject = "Nieuwe registratie retour pakket "
.HTMLBody = strbody
.Display 'or use .Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
Else
MsgBox "U moet de file eerst opslaan voor u verder kan gaan."
End If
The code you provided seems to work as expected, you should attempt to investigate where the ACCT:ACCT:ACCT: string is actually coming from, maybe the following helps, where I've changed the ActiveWorkbook to ThisWorkbook to eliminate the possibility of the code picking up data from a workbook that might be active, but not necessarily the intended one:
Sub Send_Email()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Ingave")
'make sure that we are looking at the this workbook and not the Active one.
If ThisWorkbook.Path <> "" Then
'make sure the workbook has been saved, so we get a Path property.
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "<font size=""3"" face=""Calibri"">" & _
"Beste Collega,<br><br>" & _
"Een nieuwe retour zending registratie werd aangemaakt met urgentie: <B>" & ws.Cells(6, 3).Value & "</B>.<br>" & _
"Het pakket nummer is <B>" & ws.Cells(22, 3).Value & "</B>.<br><B> " & _
"</B><br><br>In geval van vragen gelieve contact op te nemen." & _
"<br><br> Met vriendelijke groeten, </font>"
'On Error Resume Next
With OutMail
.to = "xxx#yyy"
.CC = ""
.BCC = ""
.Subject = "Nieuwe registratie retour pakket "
.HTMLBody = strbody
.Display 'or use .Send
End With
'On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
Else
MsgBox "U moet de file eerst opslaan voor u verder kan gaan."
End If
End Sub
Related
I am creating an email using VBA in Excel. For the body of the email I am taking the value of a TextBox in the excel sheet. I have enabled multiple lines in the TextBox and have put text on the first line and have text on the line below, but when I generate the email, it takes both lines of text and puts them on the same line in the email.
I need to know how to keep the line breaks in the TextBox.
Sub Test1()
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Dim SigString As String
Dim Signature As String
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
On Error GoTo cleanup
For Each cell In Columns("B").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "?*#?*.?*" And _
LCase(Cells(cell.Row, "C").Value) = "yes" Then
Set OutMail = OutApp.CreateItem(0)
SigString = Environ("appdata") & _
"\Microsoft\Signatures\Default.htm"
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
On Error Resume Next
With OutMail
.Display
.To = cell.Value
.Subject = "Reminder"
.HTMLBody = "<p>Dear " & Cells(cell.Row, "A").Value & ",</p>" _
& "<br><br>" & ActiveSheet.TextBox1.Value & _
.HTMLBody
.Attachments.Add ("")
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
End If
Next cell
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
Function GetBoiler(ByVal sFile As String) As String
'Dick Kusleika
Dim fso As Object
Dim ts As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)
GetBoiler = ts.readall
ts.Close
End Function
Here is the TextBox1 properties
You can replace your newlines, vbNewLine, with HTML formatted line-breaks, <br>, like so:
With outMail
.display
.To = Cell.Value
.subject = "Reminder"
.HTMLBody = "<p>Dear " & Cells(Cell.row, "A").Value & ",</p>" _
& "<br><br>" & Replace(ActiveSheet.TextBox1.Value, vbNewLine, "<br>") & _
.HTMLBody
.Attachments.Add ("")
.display
End With
You can Split your string here to sperate lines
.HTMLBody = "<p>Dear " & Cells(cell.Row, "A").Value & ",</p>" _
& "<br><br>" _
& Split(ActiveSheet.TextBox1.Value, ".")(0) &"." _
& "<br>" _
& Split(ActiveSheet.TextBox1.Value, ".")(1) & "." _
& .HTMLBody
My sheet 'Volglijst' contains a list with all packages that have been registerd for sending.
When the package is picked up by the supplier or courrier, the goods reception service registers the date and who picked up the package.
When they close the file, a pop-up appears that is asking if they want to send e-mail confirmation to the person who requested the sending.
When they select yes VBA should check all rows in sheet 'Volglijst' where there is a date in Column B and Column Q, and where column S is empty (the 3 conditions should apply at the same time, if not, no e-mail needs to be send).
I'm getting my outlook to start and create a new e-mail, but it remains empty.
The body is working for an other e-mail only the reference to the cell content is adjusted to match the rows for which the conditions apply.
Dim OutApp As Object
Dim OutMail As Object
Dim i As Long
Dim t As Range
Dim WkSht As Worksheet
Dim strbody As String
Set WkSht = Sheets("Volglijst")
For i = 1 To 999
If WkSht.Cells(i, 2).Value <> "" And WkSht.Cells(i, 17).Value <> "" And WkSht.Cells(i, 19).Value = "" Then
Dim rng As Range
With Application.Intersect(WkSht.Rows(i), WkSht.UsedRange)
Set rng = WkSht.Range(WkSht.Cells(i, 3), .Cells(.Cells.Count))
End With
If rng Is Nothing Then
Exit Sub
End If
End If
Next
On Error Resume Next
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "<font size=""3"" face=""Calibri"">" & _
"Beste Collega,<br><br>" & _
"Uw pakket met nummer <B>" & WkSht.Cells(WkSht.Rows(i), 1).Value & "</B> werd <B>" & WkSht.Cells(WkSht.Rows(i), 17).Value & "</B> opgehaald door <B>" & WkSht.Cells(WkSht.Rows(i), 16).Value & "</B>.<br>" & _
"Bijkomende opmerkingen goederenontvangst: <B>" & WS.Cells(WkSht.Rows(i), 18).Value & "</B>.<br>" & _
"<br><br>In geval van vragen gelieve contact op te nemen." & _
"<br><br> Met vriendelijke groeten, </font>"
On Error Resume Next
With OutMail
.To = WS.Cells(WkSht.Rows(i), 5).Value
.CC = ""
.BCC = ""
.Subject = "Ophaling pakket " & WS.Cells(i, 1).Value & ""
.HTMLBody = strbody
.Display 'or use .Send
End With
A separate email sould be sent for each row with column B <> ""; column Q <> "", Column S = "" , and the recepient is the e-mail adres of column E in that row. Details in the email body should also come from the applicable row.
Will attempt to compartmentalize this, but you have a couple significant issue:
You utilize i in the outlook aspect of this email OUTSIDE of the loop, so you're just using i = 999, or was this intended to be within the loop?
The references in your strbody were to different worksheets... check your references. I called out the first occurrence in the Excel_Activities subroutine when I started defining each use.
Public bdy_a as string, bdy_b as string, bdy_c as string, bdy_d as string
Public to_ as string
Public sub_ as string
'
Sub Excel_Activities()
Dim i as Long, t As Range
Dim WkSht As Worksheet
Dim strbody As String
Set WkSht = Sheets("Volglijst")
For i = 1 To 999
If WkSht.Cells(i, 2).Value <> "" And WkSht.Cells(i, 17).Value <> "" And WkSht.Cells(i, 19).Value = "" Then
Dim rng As Range
With Application.Intersect(WkSht.Rows(i), WkSht.UsedRange)
Set rng = WkSht.Range(WkSht.Cells(i, 3), .Cells(.Cells.Count))
End With
If rng Is Nothing Then
Exit Sub
Else
bdy_a = WkSht.Cells(i, 1).Value
bdy_b = WkSht.Cells(i, 17).Value
bdy_c = WkSht.Cells(i, 16).Value
bdy_d = WS.Cells(i, 18).Value 'IS THIS CORRECT SHEET?
to_ = WS.Cells(WkSht.Rows(i), 5).Value
sub_ = WS.Cells(i, 1).Value
Application.Run("Outlook_Activities")
End If
End If
Next
End Sub
Then deal with the saved values to create the desired email, which appears to occur within the Loop based on the use of i in your original post strbody.
Private Sub Outlook_Activities()
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "<font size=""3"" face=""Calibri"">" & "Beste Collega,<br><br>" & "Uw pakket met nummer <B>" & bdy_a & "</B> werd <B>" & bdy_b & "</B> opgehaald door <B>" & bdy_c & "</B>.<br>" & "Bijkomende opmerkingen goederenontvangst: <B>" & & "</B>.<br>" & "<br><br>In geval van vragen gelieve contact op te nemen." & "<br><br> Met vriendelijke groeten, </font>"
With OutMail
.To = to_
.CC = ""
.BCC = ""
.Subject = "Ophaling pakket " & sub_ & ""
.HTMLBody = strbody
.Display 'or use .Send
End With
End Sub
I believe the following is what you are looking for, this will loop from Row 1 to the last in the UsedRange, check whether Columns B & Q are not empty and Column S is empty then deal with the email per row:
Sub LoopThroughRange_SendEmail()
Dim OutApp As Object: Set OutApp = CreateObject("Outlook.Application")
Dim OutMail As Object: Set OutMail = OutApp.CreateItem(0)
Dim i As Long
Dim strbody As String
Dim WkSht As Worksheet: Set WkSht = Sheets("Volglijst")
For i = 1 To WkSht.UsedRange.Rows.Count
If WkSht.Cells(i, "B").Value <> "" And WkSht.Cells(i, "Q").Value <> "" And WkSht.Cells(i, "S").Value = "" Then
strbody = "<html><body><font size=""3"" face=""Calibri"">Beste Collega,<br><br>Uw pakket met nummer <b>" & _
WkSht.Cells(i, "A").Value & "</b> werd <b>" & WkSht.Cells(i, "Q").Value & "</b> opgehaald door <b>" & _
WkSht.Cells(i, "P").Value & "</b>.<br>Bijkomende opmerkingen goederenontvangst: <b>" & _
WkSht.Cells(i, "R").Value & "</B>.<br><br><br>In geval van vragen gelieve contact op te nemen.<br><br>" & _
"Met vriendelijke groeten, </font></body></html>"
With OutMail
.To = WkSht.Cells(i, "E").Value
.CC = ""
.BCC = ""
.Subject = "Ophaling pakket " & WkSht.Cells(i, "A").Value & ""
.HTMLBody = strbody
.Display 'or use .Send
End With
End If
Next i
End Sub
UPDATE:
To also validate the email address before attempting to send the email, the below will help, it will allow multiple email addresses in a single cells separated by a ;
Sub LoopThroughRange_SendEmail()
Dim oRegEx As Object
Set oRegEx = CreateObject("VBScript.RegExp")
Dim OutApp As Object: Set OutApp = CreateObject("Outlook.Application")
Dim OutMail As Object: Set OutMail = OutApp.CreateItem(0)
Dim i As Long
Dim strbody As String
Dim WkSht As Worksheet: Set WkSht = Sheets("Volglijst")
For i = 1 To WkSht.UsedRange.Rows.Count
If ValidEmail(WkSht.Cells(i, "E").Value, oRegEx) Then
If WkSht.Cells(i, "B").Value <> "" And WkSht.Cells(i, "Q").Value <> "" And WkSht.Cells(i, "S").Value = "" Then
strbody = "<html><body><font size=""3"" face=""Calibri"">Beste Collega,<br><br>Uw pakket met nummer <b>" & _
WkSht.Cells(i, "A").Value & "</b> werd <b>" & WkSht.Cells(i, "Q").Value & "</b> opgehaald door <b>" & _
WkSht.Cells(i, "P").Value & "</b>.<br>Bijkomende opmerkingen goederenontvangst: <b>" & _
WkSht.Cells(i, "R").Value & "</B>.<br><br><br>In geval van vragen gelieve contact op te nemen.<br><br>" & _
"Met vriendelijke groeten, </font></body></html>"
With OutMail
.To = WkSht.Cells(i, "E").Value
.CC = ""
.BCC = ""
.Subject = "Ophaling pakket " & WkSht.Cells(i, "A").Value & ""
.HTMLBody = strbody
.Display 'or use .Send
End With
End If
Else
'email address is not valid
End If
Next i
End Sub
Public Function ValidEmail(pAddress As String, ByRef oRegEx As Object) As Boolean
With oRegEx
.Pattern = "^(([a-zA-Z0-9_\-\.\']+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)(\s*;\s*|\s*$))+$" 'pattern for multiple email addresses included
ValidEmail = .test(pAddress)
End With
End Function
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
I would like to hyperlink a cell and have the value of that cell be the hyperlink in the body of the email.
So in below's code instead of "Hello" it should refer to value of a cell. Say if Range("A1") equals 100, the hyperlink in the body of the email should say 100. If I change Range("A1") to 101, the hyperlink in the email should change to 101.
Thanks for your help!
My code:
Sub SendHyperlinkEmail()
Dim outApp As Object
Dim OutMail As Object
Dim strbody As String
Set outApp = CreateObject("Outlook.Application")
Set OutMail = outApp.CreateItem(0)
strbody = "<A HREF='mailto:z#zzz.com'>Hello</A>"
On Error Resume Next
With OutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = Test
.HTMLBody = strbody
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set outApp = Nothing
End Sub
I think concatenation would work.
strbody = "<A HREF='mailto:z#zzz.com'>" & range("a1") & "</A>"
"&" is used in VBA to concatenate text and variables/ranges/etc
Actually managed to get a fairly ugly solution myself so open for improvement:
Sub SendHyperlinkEmail()
Dim outApp As Object
Dim OutMail As Object
Dim strbody As String
Set outApp = CreateObject("Outlook.Application")
Set OutMail = outApp.CreateItem(0)
strbody = "<table>" & "<tr>" & "<A
HREF='mailto:mailto:z#zzz.com?subject=Enquiry&Body=I would
like to'>" _
& range("B2") & " " & range("C2") & "</A>" & "</tr>" &
_ "<tr>" & "<A HREF='mailto:mailto:z#zzz.com
subject=Enquiry&Body=I would like to'>" _
& range("B3") & " " & range("C3") & "</A>" & "</tr>" & _
"<tr>" & "<A HREF='mailto:mailto:z#zzz.com?subject=Enquiry&Body=I would like to'>" _
& range("B4") & " " & range("C4") & "</A>" & "</tr>" & _
"</table>"On Error Resume Next
With OutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = Test
.HTMLBody = strbody
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set outApp = Nothing
End Sub
I have a slight issue with a macro. It works fine at the moment, but I need to add some code to do the following but don't know at what point to add it:
If for each cell in Column C that there is a blank cell to look for the email address on the same row but 10 columns over to the right in Column M
In the start of the body "Hi There (Column B content)
In the body of the email I would like for the macro to insert the contents from column F like this: "Please choose the following option (Column F content)
Any Ideas on how I can modify the code to include these options please.
Thank you for your time.
Sub Send_Email()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim cel As Range
Dim SigString As String
Dim Signature As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
SigString = Environ("appdata") & _
"\Microsoft\Signatures\GBS.txt"
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
For Each cel In Range(("C2"), Range("C2").End(xlDown))
strbody = "Hi there" & vbNewLine & vbNewLine & _
"My name Is William, Please choose the following option ..." & vbNewLine & _
"I work at Fair" & vbNewLine & _
"Bye" & vbNewLine & _
"WH"
On Error Resume Next
With OutMail
.To = cel.Value
.CC = cel.Offset(0, 10).Value
'.BCC = ""
.Subject = "Choose you plan"
.Body = strbody & vbNewLine & vbNewLine & Signature
.Display
'.Attachments.Add ("C:\test.txt")
'.Send
End With
On Error GoTo 0
Next cel
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Try this one:
Sub Send_Email()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim cel As Range
Dim SigString As String
Dim Signature As String
Dim lastrow As Long
Set OutApp = CreateObject("Outlook.Application")
SigString = Environ("appdata") & _
"\Microsoft\Signatures\GBS.txt"
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
lastrow = Cells(Rows.Count, 3).End(xlUp).Row
For Each cel In Range("C2:C" & lastrow)
strbody = "Hi there" & cel.Offset(, -1) & vbNewLine & vbNewLine & _
"My name Is William, Please choose the following option ..." & vbNewLine & _
cel.Offset(, 3) & _
"I work at Fair" & vbNewLine & _
"Bye" & vbNewLine & _
"WH"
On Error Resume Next
With OutApp.CreateItem(0)
If cel.Value <> "" Then
.To = cel.Value
.CC = cel.Offset(0, 10).Value
Else
.To = cel.Offset(0, 10).Value & ", " & Join(Application.Index(cel.Offset(, -2).Resize(, 4).Value, 0), ", ")
End If
'.BCC = ""
.Subject = "Choose you plan"
.Body = strbody & vbNewLine & vbNewLine & Signature
.Display
'.Attachments.Add ("C:\test.txt")
'.Send
End With
On Error GoTo 0
Next cel
Set OutApp = Nothing
End Sub