I am trying to create an Outlook email for multiple recipients.
I have two sheets 1 and 2.
I want the code in sheet 1 column B to look into Sheet 2 column A and pick up all the email addresses matched the codes and create an email with list recipients in tostring and do repeat task for second code till its empty.
Also attach files corresponding to that code in column c in sheet 1.
Its in the Sheet 2 column B
I have clients' names in sheet 1 column B and there is corresponding names in sheet 2 Column A and email addresses in Column B.
I created below code. How do I create a to string in VBA?
Sub GenerateEmail()
i = 2 ' selects row 2 ,since row 1 ,i am keeping for titles
Dim wbBook As Excel.Workbook
Dim doText As DataObject
Dim wsSheet As Excel.Worksheet
Dim x As Variant
Dim myemail As String
Dim myrange As Range
Dim n As Range
Dim sm2 As Range
Set wbBook = ThisWorkbook
Set sm2 = ThisWorkbook.Sheets("Sheet 2").Range("A2:A1000")
Set sm1 = ThisWorkbook.Sheets("Sheet 1").Range("B2:B1000")
Do Until ThisWorkbook.Sheets("Sheet 1").Cells(i, "B").Value = ""
EmailTo = tostring
BCC = ThisWorkbook.Sheets("Sheet 1").Range("J3").Value
Subj = ThisWorkbook.Sheets("Sheet 1").Range("J4").Value
Path = "N:\Folder 1\Folder 2\Folder 3\Folder 3\Result\"
FileName = ThisWorkbook.Sheets("Sheet 1").Cells(i, 3)
SM = ThisWorkbook.Sheets("Sheet 1").Cells(i, 2)
x = Replace(Range("Content1").Value, "<PROJECTION DATE1>", Format(Range("GenerationMonth").Value, "mmmm"))
x = x & Replace(Range("Content2").Value, "<PROJECTION DATE2>", Format(Range("GenerationMonth").Value, "mmmm-yyyy"))
x = x & ThisWorkbook.Sheets("Sheet 3").Range("Content3").Value
Msg = x
Application.ScreenUpdating = False
Application.StatusBar = "Preparing email..."
Application.DisplayAlerts = False
'Variables for MS Outlook.
'Variables for MS Outlook.
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.SentOnBehalfOfName = "Cleint1#Hotmail.com"
.To = EmailTo
.BCC = "Cleint1#Hotmail.com"
.Subject = "This is my subject" & Format(DateAdd("m", -1, Date), "mmmm yyyy")
.Attachments.Add Path & FileName
.Display
.BodyFormat = olFormatPlain
.Body = Msg
'send
End With
i = i + 1
Set doText = Nothing
Application.CutCopyMode = False
Loop
Cells(7, "J").Value = "Outlook msg count =" & i - 1
Set OutMail = Nothing
Set OutApp = Nothing
Application.DisplayAlerts = False
Application.ScreenUpdating = False
'Workbooks(MyFile).Close
End Sub
This is one way to start your loop and get the "To:" variable.
I comment out most of the code because I don't have your workbook and the code would not work in my situation.
Sub DoItEmail()
'Dim doText As DataObject
Dim x As Variant
Dim myemail As String
Dim myrange As Range
Dim n As Range
Dim sm2 As Range
Dim OutApp As Object
Dim OutMail As Object
'==================================================================
Dim sh As Worksheet, ws As Worksheet, wb As Workbook
Dim Rws As Long, Rng As Range, c As Range
Dim Rws2 As Long, Rng2 As Range, b As Range, SndTo As String
Set sh = Sheets("Sheet1")
Set ws = Sheets("Sheet2")
Application.ScreenUpdating = 0
With sh
Rws = .Cells(.Rows.Count, "A").End(xlUp).Row
Set Rng = .Range("A2:A" & Rws)
End With
With ws
Rws2 = .Cells(.Rows.Count, "C").End(xlUp).Row
Set Rng2 = .Range("C2:C" & Rws2)
End With
For Each c In Rng.Cells
For Each b In Rng2.Cells
If b = c Then
SndTo = b.Offset(0, 1) 'this would be your "to:" variable
'MsgBox SndTo & " is the To: variable"
'EmailTo = tostring
BCC = sh.Range("J3").Value
Subj = sh.Range("J4").Value
'Path = "N:\Folder 1\Folder 2\Folder 3\Folder 3\Result\"
'FileName = sh.Cells(i, 3)
'SM = sh.Cells(i, 2)
' x = Replace(Range("Content1").Value, "<PROJECTION DATE1>", Format(Range("GenerationMonth").Value, "mmmm"))
' x = x & Replace(Range("Content2").Value, "<PROJECTION DATE2>", Format(Range("GenerationMonth").Value, "mmmm-yyyy"))
' x = x & ThisWorkbook.Sheets("Sheet 3").Range("Content3").Value
' Msg = x
Application.ScreenUpdating = False
'Application.StatusBar = "Preparing email..."
Application.DisplayAlerts = False
'Variables for MS Outlook.
'Variables for MS Outlook.
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.SentOnBehalfOfName = "Cleint1#Hotmail.com"
.To = SndTo
.BCC = "Cleint1#Hotmail.com"
.Subject = "This is my subject: " & Format(DateAdd("m", -1, Date), "mmmm yyyy")
'.Attachments.Add Path & FileName
.Display
.BodyFormat = olFormatPlain
.Body = Msg
'send
End With
i = i + 1
Set doText = Nothing
Application.CutCopyMode = False
Cells(7, "J").Value = "Outlook msg count =" & i
Set OutMail = Nothing
Set OutApp = Nothing
Application.DisplayAlerts = False
Application.ScreenUpdating = False
'Workbooks(MyFile).Close
End If
Next b
Next c
Application.StatusBar = False
End Sub
Related
I'm currently working on a vba excel macro that filters particular rows (based on values in one column), then copies particular columns from the filtered rows & paste them as a table into the outlook email body.
I'd like the table to be pasted after the text in the email body. However, it seems that the table is the only thing that is in the mail body & I can't put the text before the table.
Would much appreciate your advice on how to display the text in the email body before the pasted table. My current: "OutMail.Body = "The body text I want to put before the table" does not work.
EDIT 1 = adjusted according to CDP1802 + added moving rows to archive feature
Code:
Option Explicit Public ws As Worksheet
Public ol As ListObject
Public olRng As Range
Sub CopyTableToEmail()
Dim olCol As Integer, datCol As Integer
Set ws = Sheets("Test1")
Set ol = ws.ListObjects("TbClient")
Set olRng = ol.Range
'remove table filters
ol.ShowAutoFilter = False
'get Valid column
olCol = ol.ListColumns("Valid").Index
'filter table
ol.Range.AutoFilter field:=olCol, Criteria1:="<0", Operator:=xlOr
'select table to copy
Set olRng = ol.Range
'create mail
Call CreateMail
'Change values on Deactivation e-mail sent column
datCol = ol.ListColumns("Deactivation e-mail sent").Index
ol.ListColumns(datCol).DataBodyRange.SpecialCells(xlCellTypeVisible).Value = Range("H1")
'clear table filters
ol.AutoFilter.ShowAllData
'Move rows to the Archive
Call MoveRows
End Sub
Sub CreateMail()
On Error GoTo errHandler
Dim olCol As Integer, rCell As Range, addRng As Range
Dim mailBcc As String, mailCC As String
'Outlook
Dim OutApp As Object, OutInsp As Object, OutMail As Object
'Declare Word Variables
Dim oWrdDoc As Word.Document, oWdEditor As Word.Editors
Dim sText As String
'Range of mail adresses
olCol = ol.ListColumns("Requestor (email)").Index
Set addRng = ol.ListColumns(olCol).DataBodyRange.SpecialCells(xlCellTypeVisible)
'get the mail addresses
For Each rCell In addRng
mailBcc = mailBcc & rCell.Value & ";"
mailCC = mailCC & rCell.Offset(0, 1).Value & ";"
Next rCell
' copy table colmns B,J,L
ws.Columns.Hidden = False
ws.Range("A:A,C:I,K:K,M:Z").EntireColumn.Hidden = True
olRng.Copy
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
Dim signature As String
With OutMail
.display ' or send
signature = .body
.cc = mailCC
.Bcc = mailBcc
.Subject = "Openings Tracker"
End With
' Text
sText = "Ladies and gentlemen," & vbCrLf & vbCrLf
'Get the Active Inspector
'Get the document within the inspector
Set OutInsp = OutMail.GetInspector
Set oWrdDoc = OutInsp.WordEditor
With oWrdDoc
.Content.Delete
.Paragraphs.Add.Range.Text = sText
.Paragraphs.Add.Range.Paste
.Paragraphs.Add.Range.Text = signature
End With
ws.Columns.Hidden = False
Application.CutCopyMode = False
exitRoutine:
'clear
Set OutMail = Nothing
Set OutApp = Nothing
Set ws = Nothing
Exit Sub
errHandler:
'Open immediate window to see the error
Debug.Print Err.Number, Err.Description
Resume exitRoutine
End Sub
Sub MoveRows()
Dim xRg As Range
Dim xCell As Range
Dim A As Long
Dim B As Long
Dim O As Long
A = Worksheets("Test1").UsedRange.Rows.Count
B = Worksheets("Archive").UsedRange.Rows.Count
If B = 1 Then
If Application.WorksheetFunction.CountA(Worksheets("Archive").UsedRange) = 0 Then B = 0
End If
Set xRg = Worksheets("Test1").Range("O1:O" & A)
On Error Resume Next
Application.ScreenUpdating = False
For O = 1 To xRg.Count
If CStr(xRg(O).Value) = "OK" Then
xRg(O).EntireRow.Copy Destination:=Worksheets("Archive").Range("A" & B + 1)
xRg(O).EntireRow.Delete
If CStr(xRg(O).Value) = "OK" Then
O = O - 1
End If
B = B + 1
End If
Next
Application.ScreenUpdating = True
End Sub
Add a paragraph to the word document.
update1 - Filter table, add signature to the end.
update2 - Show only columns B J L
update3 - Added AchiveRows()
Option Explicit
Public ws As Worksheet
Public ol As ListObject
Public olRng As Range
Sub CopyTableToEmail()
Dim olCol As Integer, datCol As Integer
Set ws = Sheets("Test1")
Set ol = ws.ListObjects("tbClient")
Set olRng = ol.Range
'remove table filters
ol.ShowAutoFilter = False
'get Valid column
olCol = ol.ListColumns("Valid").Index
'filter table
ol.Range.AutoFilter field:=olCol, Criteria1:="<0", Operator:=xlOr
'select table to copy
Set olRng = ol.Range
'create mail
Call CreateMail
'clear table filters
ol.AutoFilter.ShowAllData
End Sub
Sub CreateMail()
On Error GoTo errHandler
Dim olCol As Integer, rCell As Range, addRng As Range
Dim mailBcc As String, mailCC As String
' Outlook
Dim OutApp As Object, OutInsp As Object, OutMail As Object
'Declare Word Variables
Dim oWrdDoc As Word.Document, oWdEditor As Word.Editors
Dim sText As String
'Range of mail adresses
olCol = ol.ListColumns("Requestor email").Index
Set addRng = ol.ListColumns(olCol).DataBodyRange.SpecialCells(xlCellTypeVisible)
'get the mail addresses
For Each rCell In addRng
mailBcc = mailBcc & rCell.Value & ";"
mailCC = mailCC & rCell.Offset(0, 1).Value & ";"
Next rCell
' copy table colmns B,J,L
ws.Columns.Hidden = False
ws.Range("A:A,C:I,K:K,M:Z").EntireColumn.Hidden = True
olRng.Copy
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
Dim signature As String
With OutMail
.display ' or send
signature = .body
.cc = mailCC
.Bcc = mailBcc
.Subject = "Generic Subject"
End With
' Text
sText = "The body text I want to put before the table" & vbCrLf & vbCrLf
'Get the Active Inspector
'Get the document within the inspector
Set OutInsp = OutMail.GetInspector
Set oWrdDoc = OutInsp.WordEditor
With oWrdDoc
.Content.Delete
.Paragraphs.Add.Range.Text = sText
.Paragraphs.Add.Range.Paste
.Paragraphs.Add.Range.Text = signature
End With
ws.Columns.Hidden = False
Application.CutCopyMode = False
exitRoutine:
'clear
Set OutMail = Nothing
Set OutApp = Nothing
Set ws = Nothing
Exit Sub
errHandler:
'Open immediate window to see the error
Debug.Print Err.Number, Err.Description
Resume exitRoutine
End Sub
Sub ArchiveRows()
Dim ol As ListObject, rng As Range
Dim r As Long, olCol As Long, n As Long
Set ol = Sheets("Test1").ListObjects("tbClient")
olCol = ol.ListColumns("Valid").Index
With ol.DataBodyRange
For r = 1 To .Rows.Count
If UCase(Trim(.Cells(r, olCol).Value)) = "OK" Then
If rng Is Nothing Then
Set rng = .Rows(r)
Else
Set rng = Union(rng, .Rows(r))
End If
End If
Next
End With
If rng Is Nothing Then
n = 0
Else
n = rng.Rows.Count
With Sheets("Archive")
rng.Copy
With .Cells(.Rows.Count, 1).End(xlUp).Offset(1)
.PasteSpecial xlPasteValues
End With
End With
rng.Rows.Delete
Application.CutCopyMode = False
End If
MsgBox n & " rows moved to Archive and deleted"
End Sub
I am attempting to loop through a column (n=96) in my worksheet, when it comes across a value <10 I would like the macro to open outlook and email offset values (four columns across) from the values it found.
I've generated a working example though it seems to be limited to only one example I've tested. I think I am approaching it from the wrong angle.
Sub SendReminderMail()
Dim p As Long
Dim OutLookApp As Object
Dim OutLookMailItem As Object
Dim iCounter As Integer
Dim MailDest As String
'If MsgBox("Are you sure?", vbYesNo) = vbNo Then Exit Sub
Set OutLookApp = CreateObject("Outlook.application")
Set OutLookMailItem = OutLookApp.CreateItem(0)
p = 2
Do Until Trim$(Cells(p, 1).Value) = ""
If Cells(p, 1).Value <= 10 Then
Set OutLookMailItem = OutLookApp.CreateItem(0)
With OutLookMailItem
.To = "Emailaddress etc"
.Subject = "Reminder: " & Cells(1, 7).Value
.Body = Cells(p, 1).Offset(0, 4).Value
.Display
End With
End If
p = p + 1
Loop
End Sub
How do I set it up to loop through all the <10 values and tell it to paste the offset values into the body of the email?
I think that you need to split this into two blocks of code.
First block would iterate through rows, check criteria and, if needed, call the second one, so the mail sending Sub, passing by necessary parameters.
Someting similar to the below code:
Sub SendReminderMail(ByVal MailSubject As String, mailBody As String)
Dim p As Long
Dim OutLookApp As Object
Dim OutLookMailItem As Object
Dim iCounter As Integer
Dim MailDest As String
'If MsgBox("Are you sure?", vbYesNo) = vbNo Then Exit Sub
Set OutLookApp = CreateObject("Outlook.application")
Set OutLookMailItem = OutLookApp.CreateItem(0)
Set OutLookMailItem = OutLookApp.CreateItem(0)
With OutLookMailItem
.To = "Emailaddress etc"
.Subject = MailSubject
.Body = mailBody
.Display
End With
End Sub
Sub IterateThroughRows()
Dim p As Integer
Dim Sht As Worksheet
Dim MailSubject As String
Dim mailBody As String
Set Sht = ThisWorkbook.Sheets("SheetName")
p = 2
Do Until Sht.Cells(p, 1).Value = ""
If Cells(p, 1).Value <= 10 Then
mailBody = mailBody + " | " + Sht.Cells(p, 1).Offset(0, 4).Value
End If
p = p + 1
Loop
Call SendReminderMail(MailSubject, mailBody)
MailSubject = "Reminder: " & Sht.Cells(1, 7).Value
End Sub
I am trying find e-mail that matches body text and sender.
Each day I check if 300/400 emails were already sent.
I need to iterate through more than 4500 emails.
Sub Check()
Application.Calculation = xlManual
Dim OutApp As Object
Dim OutNameSpace As Object
Dim OutFolder As Object
Dim OutItms As Object
Dim OutMail As Object
Dim Last As Long
Last = ThisWorkbook.Worksheets(2).Cells(Rows.Count, 2).End(xlUp).Row
Set OutApp = CreateObject("Outlook.Application")
Set OutNameSpace = OutApp.GetNamespace("MAPI")
Set OutFolder = OutNameSpace.GetDefaultFolder(6).Folders("Inne")
Set OutItms = OutFolder.Items
Set numbers = ThisWorkbook().Sheets(2).Range(Cells(2, 2), Cells(Last, 2))
Dim numer As Range
For Each number In numbers
Z = 1
If numer = "" Then GoTo nastepny
For Each OutMail In OutFolder.Items
If InStr(1, OutMail.Body, number, vbTextCompare) <> 0 Then
If InStr(1, OutMail.Sender, "Sender Name", vbTextCompare) <> 0 Then
number.Offset(0, 7) = "Yes"
GoTo nastepny
End If
Else
number.Offset(0, 7) = "No"
End If
nastepny:
Next OutMail, number
Application.Calculation = xlAutomatic
End Sub
This code runs through all e-mails and checks if there is e-mail with correct number in body and correct sender. For more then 4500 e-mails it takes a lot of time to do it one by one.
With Restrict determine whether any item contains applicable text.
https://learn.microsoft.com/en-us/office/client-developer/outlook/pia/how-to-search-for-a-phrase-in-the-body-of-items-in-a-folder
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
' If desperate declare as Variant
Sub Check()
Application.Calculation = xlManual
' Late binding.
' Reference to Microsoft Outlook XX.X Object Library not required.
Dim OutApp As Object
Dim OutNameSpace As Object
Dim OutFolder As Object
Dim OutItms As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutNameSpace = OutApp.GetNamespace("MAPI")
' Assumptions:
' 1 - Inne is the sender
' 2 - Applicable items from Inne in subfolder Inne
Set OutFolder = OutNameSpace.GetDefaultFolder(6).Folders("Inne")
Set OutItms = OutFolder.Items
Debug.Print " OutItms.Count.....: " & OutItms.Count
Dim wB As Workbook
Set wB = ThisWorkbook
Dim wS As Worksheet
Set wS = wB.Worksheets(2)
Dim Last As Long
Dim numbers As Range
With wS
'Entries in column 2
Last = .Cells(.Rows.Count, 2).End(xlUp).Row
Set numbers = .Range(.Cells(2, 2), .Cells(Last, 2))
End With
Dim numBer As Range
For Each numBer In numbers
If numBer <> "" Then
Dim strFilter As String
' https://learn.microsoft.com/en-us/office/client-developer/outlook/pia/how-to-search-for-a-phrase-in-the-body-of-items-in-a-folder
strFilter = "#SQL=" & Chr(34) & "urn:schemas:httpmail:textdescription" & Chr(34) & " like '%" & numBer & "%'"
Debug.Print strFilter
Dim numBerResults As Object
Set numBerResults = OutFolder.Items.Restrict(strFilter)
Debug.Print " numBerResults.Count.....: " & numBerResults.Count
If numBerResults.Count > 0 Then
numBer.Offset(0, 7) = "Yes"
Else
numBer.Offset(0, 7) = "No"
End If
End If
Next numBer
Application.Calculation = xlAutomatic
Debug.Print "Done."
End Sub
While running this code i get run-time error 1004, "Application-defined object defined error". This error is showing up on the line starting with "NumRows = Worksheets("Data")" in the first function. Can someone just check on this code and let me know what's wrong here, i am new to VBA macros with limited knowledge.
Public Sub loopCheck()
Dim NumRows As Integer
Dim eID As String
Dim eName As String
Dim eEmail As String
Dim supportGroup As String
Dim managerEmail As String
Dim acName As String
Dim x As Integer
Application.ScreenUpdating = False
NumRows = Worksheets("Data").Range("A5", Range("A5").End(xlDown)).Rows.Count ' Set numrows = number of rows of data.
Worksheets("Data").Range("A5").Select ' Select first record.
For x = 1 To NumRows ' Establish "For" loop to loop "numrows" number of times.
eID = Worksheets("Data").Range("A" & x + 4).Value
eName = Worksheets("Data").Range("B" & x + 4).Value
eEmail = Worksheets("Data").Range("C" & x + 4).Value
supportGroup = Worksheets("Data").Range("F" & x + 4).Value
managerEmail = Worksheets("Data").Range("G" & x + 4).Value
acName = Worksheets("Data").Range("I" & x + 4).Value
'Prepare table to be sent locally.
Worksheets("Data").Range("AA5").Value = eID
Worksheets("Data").Range("AB5").Value = eName
Worksheets("Data").Range("AC5").Value = eEmail
Worksheets("Data").Range("AF5").Value = supportGroup
managerEmail = managerEmail + ";" + Worksheets("Data").Range("AA1").Value
'Call Emails function.
Call Emails(acName, eEmail, managerEmail)
ActiveCell.Offset(1, 0).Select
Next
Application.ScreenUpdating = True
End Sub
Public Sub Emails(x As String, y As String, z As String)
Dim outlook As Object
Dim newEmail As Object
Dim xInspect As Object
Dim pageEditor As Object
Dim a As String
Dim b As String
Dim c As String
a = y
b = z
c = x
Set outlook = CreateObject("Outlook.Application")
Set newEmail = outlook.CreateItem(0)
With newEmail
.To = a
.CC = b
.BCC = ""
.Subject = Worksheets("MF").Range("A1") & c
.Body = ""
.display
Set xInspect = newEmail.getInspector
Set pageEditor = xInspect.WordEditor
Worksheets("MF").Range("A9").Copy
pageEditor.Application.Selection.PasteAndFormat (wdFormatPlainText)
Worksheets("MF").Range("A3").Copy
pageEditor.Application.Selection.PasteAndFormat (wdFormatPlainText)
Worksheets("Data").Range("AA4:AF5").Copy
pageEditor.Application.Selection.PasteAndFormat (wdFormatPlainText)
Worksheets("MF").Range("A5").Copy
pageEditor.Application.Selection.PasteAndFormat (wdFormatPlainText)
Worksheets("MF").Range("A7").Copy
pageEditor.Application.Selection.PasteAndFormat (wdFormatPlainText)
.send
Set pageEditor = Nothing
Set xInspect = Nothing
End With
Set newEmail = Nothing
Set outlook = Nothing
End Sub
I have made some corrections in your code and it works at my end . Please try this. Mainly it relates to setting workbook and worksheets references properly otherwise your code seems to be okay:
Public Sub loopCheck()
Dim NumRows As Integer
Dim eID As String
Dim eName As String
Dim eEmail As String
Dim supportGroup As String
Dim managerEmail As String
Dim acName As String
Dim wb1 As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim x As Integer
Set ws1 = ThisWorkbook.Worksheets("Data") ' Set workbook & worksheet reference
Set ws2 = ThisWorkbook.Worksheets("MF") '' Set workbook & worksheet reference
NumRows = ws1.Range("A5", Range("A5").End(xlDown)).Rows.Count ' Set numrows = number of rows of data.
ws1.Range("A5").Select ' Select first record.
For x = 1 To NumRows ' Establish "For" loop to loop "numrows" number of times.
eID = ws1.Range("A" & x + 4).Value
eName = ws1.Range("B" & x + 4).Value
eEmail = ws1.Range("C" & x + 4).Value
supportGroup = ws1.Range("F" & x + 4).Value
managerEmail = ws1.Range("G" & x + 4).Value
acName = ws1.Range("I" & x + 4).Value
'Prepare table to be sent locally.
With ws1
.Range("AA5").Value = eID
.Range("AB5").Value = eName
.Range("AC5").Value = eEmail
.Range("AF5").Value = supportGroup
managerEmail = managerEmail + ";" + ws1.Range("AA1").Value
'Call Emails function.
Call Emails(acName, eEmail, managerEmail)
ActiveCell.Offset(1, 0).Select
End With
Next
Application.ScreenUpdating = True
End Sub
Public Sub Emails(x As String, y As String, z As String)
Dim outlook As Object
Dim newEmail As Object
Dim xInspect As Object
Dim pageEditor As Object
Dim a As String
Dim b As String
Dim c As String
Dim str As String
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
a = y
b = z
c = x
Set outlook = CreateObject("Outlook.Application")
Set newEmail = outlook.CreateItem(0)
Set ws2 = ThisWorkbook.Worksheets("MF")
str = ws2.Range("A1").Value & c
With newEmail
.To = a
.CC = b
.BCC = ""
.Subject = str
.Body = ""
.Display
Set xInspect = newEmail.GetInspector
Set pageEditor = xInspect.WordEditor
Set ws1 = ThisWorkbook.Worksheets("Data")
ws2.Range("A9").Copy
pageEditor.Application.Selection.PasteAndFormat (wdFormatPlainText)
ws2.Range("A3").Copy
pageEditor.Application.Selection.Paste xlValuesAndFormat (wdFormatPlainText)
ws1.Range("AA4:AF5").Copy
pageEditor.Application.Selection.Paste xlValuesAndFormat (wdFormatPlainText)
ws2.Range("A5").Copy
pageEditor.Application.Selection.Paste xlValuesAndFormat (wdFormatPlainText)
ws2.Range("A7").Copy
pageEditor.Application.Selection.PasteAndFormat (wdFormatPlainText)
.Send
Set pageEditor = Nothing
Set xInspect = Nothing
End With
Set newEmail = Nothing
Set outlook = Nothing
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
Either your worksheet must be active or you have to address your range like this:
NumRows = Worksheets("Data").Range("A5", Worksheets("Data").Range("A5").End(xlDown)).Rows.Count
I have a folder with 50 files and I have a list of 50 email addresses. Each file goes to a different email address. Is there a way to write a macro that performs this task?
The problem with the set of code below is two-fold:
1) I have 3 COLUMNS of data in an Excel file: One for subject, one for email address to send to, and the third for the FILE PATH of where the attachment to be attached is stored.
The code below does not allow for a pre-determined set of subject arguments. It also uses ROWS?? for the filepath field instead of a column like it does for send to? So confusing.
Sub Send_Files()
Dim OutApp As Object
Dim OutMail As Object
Dim sh As Worksheet
Dim cell As Range
Dim FileCell As Range
Dim rng As Range
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set sh = Sheets("Sheet1")
Set OutApp = CreateObject("Outlook.Application")
For Each cell In sh.Columns("B").Cells.SpecialCells(xlCellTypeConstants)
'Enter the path/file names in the C:Z column in each row
Set rng = sh.Cells(cell.Row, 1).Range("C1:Z1")
If cell.Value Like "?*#?*.?*" And _
Application.WorksheetFunction.CountA(rng) > 0 Then
Set OutMail = OutApp.CreateItem(0)
With OutMail
.to = cell.Value
.Subject = "Testfile"
.Body = "Hi " & cell.Offset(0, -1).Value
For Each FileCell In rng.SpecialCells(xlCellTypeConstants)
If Trim(FileCell) <> "" Then
If Dir(FileCell.Value) <> "" Then
.Attachments.Add FileCell.Value
End If
End If
Next FileCell
.Send 'Or use .Display
End With
Set OutMail = Nothing
End If
Next cell
Set OutApp = Nothing
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
Here is quick example, assuming col A = Email, Col B = Subject & Col C = Path
Option Explicit
Public Sub Example()
Dim olApp As Object
Dim olMail As Object
Dim olRecip As Object
Dim olAtmt As Object
Dim iRow As Long
Dim Recip As String
Dim Subject As String
Dim Atmt As String
iRow = 2
Set olApp = CreateObject("Outlook.Application")
Dim Sht As Worksheet
Set Sht = ThisWorkbook.Worksheets("Sheet1")
Do Until IsEmpty(Sht.Cells(iRow, 1))
Recip = Sht.Cells(iRow, 1).Value
Subject = Sht.Cells(iRow, 2).Value
Atmt = Sht.Cells(iRow, 3).Value ' Attachment Path
Set olMail = olApp.CreateItem(0)
With olMail
Set olRecip = .Recipients.Add(Recip)
.Subject = Subject
.Body = "Hi "
.Display
Set olAtmt = .Attachments.Add(Atmt)
olRecip.Resolve
End With
iRow = iRow + 1
Loop
Set olApp = Nothing
End Sub