I am using the already known Subroutine to send a warning email to outlook whenever a condition is met.
In the routine I define an string array under the name DatePassed in which I store some dynamical values and I intent to return it's content in the Subject of the email.
The problem is that I don't know how exactly to handle DatePassed so to return me the whole array not just the first element.
How would I do this?
Sub Mail_workbook_Outlook_1()
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
Dim DatePassed(100) As Variant
Dim i As Integer
For i = 6 To 13
If Cells(i, 1) < Date Then
DatePassed(i - 6) = Cells(i, 2)
End If
Next i
With OutMail
.To = "Joerge#Johnson.com"
.CC = "James#Johnson.com"
.BCC = ""
.Subject = "Unmanaged Clients"
.Body = DataPassed
.Attachments.Add ActiveWorkbook.FullName
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Try this.
I have just added a Loop to run through the Array and stored it as a string which then gets assigned to the .Body
Sub Mail_workbook_Outlook_1()
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
Dim DatePassed(100) As Variant
Dim i As Integer
For i = 6 To 13
If Cells(i, 1) < Date Then
DatePassed(i - 6) = Cells(i, 2)
End If
Next i
'=================================================
'New Section
Dim DataPassedElementReference As Long
Dim DataPassedString As String
DataPassedString = ""
'Using 100 as this is waht you used to define the array
For DataPassedElementReference = 1 To 100
DataPassedString = DataPassedString & DataPassed(DataPassedElementReference) & " "
Next DataPassedElementReference
'=================================================
With OutMail
.To = "Joerge#Johnson.com"
.CC = "James#Johnson.com"
.BCC = ""
.Subject = "Unmanaged Clients"
'Note the difference here
'.Body = DataPassed
.Body = DataPassedString
.Attachments.Add ActiveWorkbook.FullName
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Related
I am trying to use the standard code to email a workbook to multiple recipients but build in some error handling that is likely to arise in my model.
If the email address is not available the cell where the email address would be found would read "Pending Search...".
If that is the case the loop simply needs to skip that cell and move on the the next email address.
Below is my code. The issue is coming from the IF/Then/Next line. I am getting a Next without For error. Any input would be greatly appreciated.
Sub Mail_workbook_Outlook_1()
Dim OutApp As Object
Dim OutMail As Object
Dim Position_In_Loop As Long
Dim Total_Emails As Long
Dim Email_Address As String
Dim Dashboard As Worksheet
Set Dashboard = ActiveWorkbook.Worksheets("Dashboard")
Dim Body As Range
Set Body = Dashboard.Range("F13")
Dim Attachment As Range
Set Attachment = Dashboard.Range("F24")
With Dashboard
Total_Emails = Dashboard.Range("G3")
End With
For Position_In_Loop = 1 To Total_Emails
Email_Address = Dashboard.Range("C3").Offset(Position_In_Loop, 0)
If Email_Address = "Pending Search..." Then Next Position_In_Loop
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "Email_Address"
.CC = ""
.BCC = ""
.Subject = "Open Job Violations"
.Body = "Body"
.Attachments.Add (Attachment)
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
Next Position_In_Loop
End Sub
You shouldn't increment the loop like that. You are going to skip emails. Wrap the whole the Outlook mail code in an If statement.
Option Explicit
Sub Mail_workbook_Outlook_1()
Dim OutApp As Object
Dim OutMail As Object
Dim Position_In_Loop As Long
Dim Total_Emails As Long
Dim Email_Address As String
Dim Dashboard As Worksheet
Set Dashboard = ActiveWorkbook.Worksheets("Dashboard")
Dim Body As Range
Set Body = Dashboard.Range("F13")
Dim Attachment As Range
Set Attachment = Dashboard.Range("F24")
With Dashboard
Total_Emails = Dashboard.Range("G3")
End With
For Position_In_Loop = 1 To Total_Emails
Email_Address = Dashboard.Range("C3").Offset(Position_In_Loop, 0)
If Email_Address <> "Pending Search..." Then
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "Email_Address"
.CC = ""
.BCC = ""
.Subject = "Open Job Violations"
.Body = "Body"
.Attachments.Add Attachment
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End If
Next Position_In_Loop
End Sub
change this line
If Email_Address = "Pending Search..." Then Next Position_In_Loop
to
If Email_Address = "Pending Search..." Then
Position_In_Loop=Position_In_Loop+1
end if
I can send a single Outlook message using Excel VBA. However, I want to loop through my rows and send an email for each row that meets a certain condition.
Unfortunately, when I put the email code in a for loop only one email gets sent or none at all (depending on how I structure the code).
Is there something about calling Outlook multiple times that I should know?
Private Sub CommandButton1_Click()
Dim OutApp As Object
Dim OutMail As Object
Dim myValue As Variant
Dim contactRange As Range
Dim cell As Range
Dim toAddy As String, nextAddy As String
Dim i As Integer
Set contactRange = Me.Range("ContactYesNo")
myValue = InputBox("Enter body of email message.")
For Each cell In contactRange
If Range(Cells(cell.Row, cell.Column).Address).Value = "Yes" Then
nextAddy = Range(Cells(cell.Row, cell.Column).Address).Offset(0, 5).Value
toAddy = nextAddy & ", " & toAddy
End If
Next cell
If Len(toAddy) > 0 Then
toAddy = Left(toAddy, Len(toAddy) - 2)
End If
For i = 0 To 1 'short loop for testing purposes
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = toAddy
.CC = ""
.BCC = ""
.Subject = "test email"
.Body = myValue
.Send
End With
Set OutMail = Nothing
Set OutApp = Nothing
Next i
End Sub
Take the CreateObject line out of the loop:
Set OutApp = CreateObject("Outlook.Application")
For i = 0 To 1 'short loop for testing purposes
Set OutMail = OutApp.CreateItem(0)
...
I've tried to clean up your logic stream but there are many unanswered questions due to the lack of sample data, explicit error messages and output.
Private Sub CommandButton1_Click()
Dim outApp As Object
Dim outMail As Object
Dim myValue As Variant
Dim contactRange As Range
Dim cell As Range
Dim toAddy As String, nextAddy As String
Dim i As Integer
Set outApp = CreateObject("Outlook.Application")
Set contactRange = Me.Range("ContactYesNo")
myValue = InputBox("Enter body of email message.")
With Worksheets(contactRange.Parent.Name) '<~~ surely you know what worksheet you are on..!?!
For Each cell In contactRange
If cell.Value = "Yes" Then 'no need to define a range by the range's address
nextAddy = cell.Offset(0, 5).Value 'again, no need to define a range by the range's address
toAddy = nextAddy & ";" & toAddy 'use a semi-colon to concatenate email addresses
End If
Next cell
End With
If Len(toAddy) > 0 Then
toAddy = Left(toAddy, Len(toAddy) - 2) 'I have no idea why you need to shorten the toAddy by 2
'only send mail where one or more addresses exist
For i = 0 To 1 'short loop for testing purposes
Set outMail = outApp.CreateItem(0)
With outMail
.To = toAddy
.CC = ""
.BCC = ""
.Subject = "test email"
.Body = myValue
.Send
End With
Set outMail = Nothing
Next i
End If
Set outApp = Nothing
End Sub
OK, so I re-wrote the code based on the feedback. I used a loop to send emails one at a time instead of concatenating the addresses together as I wanted to personalize each email. I also needed to create a form to handle the input as inputbox only accepts 256 characters.
A form was pretty much required as I needed to capture the subject line, message body, salutation, path the to the attachment etc.:
Private Sub CommandButton1_Click()
Dim subject As String, msg As String, path As String
subject = TextBox1.Value
msg = TextBox2.Value & vbCrLf & vbCrLf & "Sincerely," & vbCrLf & TextBox4.Value & vbCrLf & TextBox5
path = TextBox3.Value
UserForm1.Hide
Module1.sendEmail subject, msg, path
End Sub
I placed the email code in Module1. Note, be sure to set the .sentOnBehalfOfName attribute or Outlook will simply pick an account which may not be the one you want if you have multiple accounts registered:
Public Sub sendEmail(subject As String, msg As String, path As String)
Dim outApp As Object
Dim outMail As Object
Dim contactRange As Range, cell As Range
Dim toAddy As String, emailMsg As String
Dim count As Integer
Set outApp = CreateObject("Outlook.Application")
Set contactRange = Range("ContactYesNo")
With Worksheets("IT consulting")
For Each cell In contactRange
If cell.Value = "Yes" Then
count = count + 1
toAddy = cell.Offset(0, 6).Value
emailMsg = "Dear " & cell.Offset(0, 2).Value & "," & vbCrLf & vbCrLf & msg
Set outMail = outApp.CreateItem(0)
With outMail
.SentOnBehalfOfName = "me#someemail.com"
.To = toAddy
.CC = ""
.BCC = ""
.subject = subject
.Body = emailMsg
.Attachments.Add path
'.Display
.Send
End With
'log the action
cell.Offset(0, 1).Value = Now & vbCrLf & cell.Offset(0, 1).Value
End If
Set outMail = Nothing
Next cell
End With
Set outApp = Nothing
MsgBox "total emails sent: " & count
End Sub
I need to send selection range from excell by email and add signature from htm file. I have next code to send selection and it works well:
Sub Send_Selection()
'Working in Excel 2002-2013
Dim Sendrng As Range
Dim strbody As Range
On Error GoTo StopMacro
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Note: if the selection is one cell it will send the whole worksheet
Set Sendrng = Selection
'Create the mail and send it
With Sendrng
ActiveWorkbook.EnvelopeVisible = True
With .Parent.MailEnvelope
' Set the optional introduction field thats adds
' some header text to the email body.
.Introduction = ""
With .Item
.To = "dg#siz66.ru"
.CC = ""
.BCC = ""
.Subject = "My subject"
.send
End With
End With
End With
StopMacro:
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
ActiveWorkbook.EnvelopeVisible = False
End Sub
Next I have code to generate mail with signature from html file:
Sub Mail_Outlook_With_Signature_Html_2()
' Don't forget to copy the function GetBoiler in the module.
' Working in Office 2000-2013
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim SigString As String
Dim Signature As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
'Change only Mysig.htm to the name of your signature
SigString = "C:\Users\d.gazdovsky\Downloads\sign.htm"
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
On Error Resume Next
With OutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.HTMLBody = strbody & "<br>" & Signature
.display 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Function GetBoiler(ByVal sFile As String) As String
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
Now I need only to combine this macros to solve my problem. Please help me with it. Thanks in advance
UPD 1: I try thi code, but it give error..
Sub Mail_Outlook_With_Signature_Html_2()
' Don't forget to copy the function GetBoiler in the module.
' Working in Office 2000-2013
Dim OutApp As Object
Dim OutMail As Object
Dim Sendrng As Range
Dim strbody As Range
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Note: if the selection is one cell it will send the whole worksheet
Set Sendrng = Selection & Signature
'Create the mail and send it
With Sendrng
ActiveWorkbook.EnvelopeVisible = True
With .Parent.MailEnvelope
' Set the optional introduction field thats adds
' some header text to the email body.
.Introduction = ""
With .Item
.To = "dg#siz66.ru"
.CC = ""
.BCC = ""
.Subject = "My subject"
.send
End With
End With
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
'Change only Mysig.htm to the name of your signature
SigString = "C:\Users\d.gazdovsky\Downloads\sign.htm"
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
On Error Resume Next
With OutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
'.HTMLBody = Sendrng & "<br>" & Signature
.display 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Function GetBoiler(ByVal sFile As String) As String
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
I tried the following code (I changed the real e-mail address), and it does work on the first cell in range, but after the first one, it gives me an error says: "run time error, the item has been moved or deleted", and then, it does not sending the others.... what should I need to fix in code ?
Sub sendMailWithLoop()
Dim missmatchCell As Range
Dim Missmatches_Rng As Range
Dim entityForRepeatedValues_Rng As Range
Dim OutMail As Object
Dim OutApp As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
If Range("D1000").End(xlUp).Value <> "Name" Then
Set Missmatches_Rng = Range(Range("D1000").End(xlUp), Range("D1000").End(xlUp).End(xlUp).Offset(1, 0))
Missmatches_Rng.Select
For Each missmatchCell In Selection
With OutMail
.To = "mymail#servername.com"
.Subject = "Attention !! missmatch found"
.Body = "The missmatch name is: " & missmatchCell.Offset(0, 1) & ", on: " & missmatchCell
.Send
End With
Next
End If
End Sub
thx !!
Move your Set OutMail = OutApp.CreateItem(0) inside the For as:
Sub sendMailWithLoop()
Dim missmatchCell As Range
Dim Missmatches_Rng As Range
Dim entityForRepeatedValues_Rng As Range
Dim OutMail As Object
Dim OutApp As Object
Set OutApp = CreateObject("Outlook.Application")
If Range("D1000").End(xlUp).Value <> "Name" Then
Set Missmatches_Rng = Range(Range("D1000").End(xlUp), Range("D1000").End(xlUp).End(xlUp).Offset(1, 0))
Missmatches_Rng.Select
For Each missmatchCell In Selection
Set OutMail = OutApp.CreateItem(olMailItem)
With OutMail
.To = "mymail#servername.com"
.Subject = "Attention !! missmatch found"
.Body = "The missmatch name is: " & missmatchCell.Offset(0, 1) & ", on: " & missmatchCell
.Send
End With
Next
End If
End Sub
I am writing macro that will set a signature after choosing the From field or for example clicking reply. My problem is that I don't know how to get the From field value. I know how to set this field.
Function GetBoiler(ByVal sFile As String) As String
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
Function GetSignature(Mailbox As String) As String
Dim Signature As String
Dim SigStringPL As String
Dim SigStringUK As String
SigStringPL = Environ("appdata") & _
"\Microsoft\Signatures\Poland.htm"
SigStringUK = Environ("appdata") & _
"\Microsoft\Signatures\United Kingdom.htm"
If Mailbox = "poland#poland.pl" Then
If Dir(SigStringPL) <> "" Then
GetSignature = GetBoiler(SigStringPL)
Else
GetSignature = ""
End If
Else
If Dir(SigStringUK) <> "" Then
GetSignature = GetBoiler(SigStringUK)
Else
GetSignature = ""
End If
End If
End Function
Sub Mail_Outlook_With_Signature_Plain()
' Don't forget to copy the function GetBoiler in the module.
' Working in Office 2000-2010
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim Signature As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "content"
Signature = GetSignature("erni#erni.pl")
MsgBox (OutMail.SentOnBehalfOfName)
On Error Resume Next
With OutMail
.To = ""
.CC = ""
.BCC = ""
.subject = "This is the Subject line"
.HTMLBody = strbody & "<br><br>" & Signature
'You can add files also like this
'.Attachments.Add ("C:\test.txt")
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Regards,
erni
SenderName is the field name for 'From' field.
From is SentOnBehalfOfName. In normal use, it is empty until the item has been sent.
Do not choose the From manually.
Sub replySentOnBehalf()
Dim objMsg As mailitem
Set objMsg = ActiveInspector.currentItem.reply
objMsg.SentOnBehalfOfName = "someone#somewhere.com"
' Now that objMsg.SentOnBehalfOfName is available run your code
objMsg.Display
Set objMsg = Nothing
End Sub