How can I use the command "Paste Special - As Picture" that you access in Excel from the right-click menu?
I have viewed various posts, but they seem to be outdated when using Excel 2016. It seems it has to be in this section,
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
How do I alter to allow copy and paste as picture?
When using the original code below, I lose all column and row sizing in the email body.
Dim rng As Range
Dim OutApp As Object
Dim outMail As Object
Set rng = Nothing
' Only send the visible cells in the selection.
Set rng = Sheets("Dashboard").Range("B4:L17").SpecialCells(xlCellTypeVisible)
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set outMail = OutApp.CreateItem(0)
With outMail
.To = ""
.CC = ""
.BCC = ""
.Subject = ""
.HTMLBody = RangetoHTML(rng)
.Display
End With
On Error GoTo 0
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set outMail = Nothing
Set OutApp = Nothing
End Sub
Function RangetoHTML(rng As Range)
' By Ron de Bruin.
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "/" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.ReadAll
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
To get better picture on Outlook, work with Word object model with MailItem.GetInspector Property (Outlook)
Example
Option Explicit
Public Sub Example()
Dim rng As Range
Dim olApp As Object
Dim Email As Object
Dim Sht As Excel.Worksheet
Dim wdDoc As Word.Document
Set Sht = ActiveWorkbook.Sheets("Dashboard")
Set rng = Sht.Range("B4:L17")
rng.CopyPicture Appearance:=xlScreen, Format:=xlPicture
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set olApp = CreateObject("Outlook.Application")
Set Email = olApp.CreateItem(0)
Set wdDoc = Email.GetInspector.WordEditor
With Email
.To = ""
.CC = ""
.BCC = ""
.Subject = ""
.Attachments.Add ActiveWorkbook.FullName
wdDoc.Range.PasteAndFormat Type:=wdChartPicture
' if need setup inlineshapes hight & width
With wdDoc
.InlineShapes(1).Height = 130
End With
.Display
End With
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set Email = Nothing
Set olApp = Nothing
End Sub
Something like this should work:
Dim ol As Object 'Outlook.Application
Dim olEmail As Object 'Outlook.MailItem
Dim olInsp As Object 'Outlook.Inspector
Dim wd As Object 'Word.Document
Sheets("Dashboard").Range("B4:L17").SpecialCells(xlCellTypeVisible).Copy
Set ol = GetObject(, "Outlook.Application") '/* if outlook is running, create otherwise */
Set olEmail = ol.CreateItem(0) 'olMailItem
With olEmail
Set olInsp = .GetInspector
If olInsp.EditorType = 4 Then 'olEditorWord
Set wd = olInsp.WordEditor
wd.Range.PasteAndFormat 13 'wdChartPicture
End If
.Display
End With
If sure that your version of Outlook uses Word Editor, you can do it like:
With olEmail
.GetInspector.WordEditor.Range.PasteAndFormat 13
.Display
End With
If you want to add Text, use this code.
Dim ol As Object 'Outlook.Application
Dim olEmail As Object 'Outlook.MailItem
Dim olInsp As Object 'Outlook.Inspector
Dim wd As Object 'Word.Document
Sheets("Dashboard").Range("B4:L17").SpecialCells(xlCellTypeVisible).Copy
Set ol = GetObject(, "Outlook.Application") '/* if outlook is running, create otherwise */
Set olEmail = ol.CreateItem(0) 'olMailItem
With olEmail
Set olInsp = .GetInspector
If olInsp.EditorType = 4 Then 'olEditorWord
Set wd = olInsp.WordEditor
wd.Range.PasteAndFormat 13 'wdChartPicture
End If
wd.Paragraphs(1).Range.InsertAfter "Hi, There" & Chr(10)
Sheets("chart").Range("B4:L17").SpecialCells(xlCellTypeVisible).Copy
wd.Paragraphs(wd.Paragraphs.Count).Range.Characters.First.PasteAndFormat 13
wd.Paragraphs.Add
Sheets("chart").Range("B4:L17").SpecialCells(xlCellTypeVisible).Copy
wd.Paragraphs(wd.Paragraphs.Count).Range.Characters.First.PasteAndFormat 13
wd.Paragraphs.Add
wd.Paragraphs(wd.Paragraphs.Count).Range.InsertAfter Chr(10) & Chr(10) & "BR"
.Display
End With
Related
I'm trying to retrieve data from archieved outlook emails from Enterprise Vault using excel vba. but it searching through only 1005 mail. but actually mail should be more than 10000. but actually looping through only 1005 mail. but should go to more than 10000 mail. I think problem happening due Enterprise Vault archived mail. because this emails are not showing in outlook but showing while going through below wesite
http://arlev4cls.india.eclerx.com/EnterpriseVault/search/shell.aspx?server=ARLMSEXCH07&mbx=SMTP:Pravin.Angane#eclerx.com#
Sub OnlineJapan_Email()
Dim outlookApp
Dim olNs As Outlook.Namespace
Dim Fldr As Outlook.MAPIFolder
Dim olMail As Variant 'Outlook.MailItem
Dim olFMail As Outlook.MailItem
Dim myTasks
Dim sir() As String
Dim rng As Range
'Set outlookApp = New Outlook.Application
Set outlookApp = CreateObject("Outlook.Application")
Set olNs = outlookApp.GetNamespace("MAPI")
Set Fldr = olNs.GetDefaultFolder(olFolderInbox)
Set myTasks = Fldr.Items
Dim wb As Workbook
Dim obwb As Workbook
For Each wb In Workbooks
If wb.Name Like "Consolidated observation file*.xlsb" Then
Set obwb = wb
obwb.Activate
Exit For
End If
Next
lastrow = obwb.Sheets("Daily Observation").Range("bm50000").End(xlUp).Row
Set rng = obwb.Sheets("Daily Observation").Range(Cells(8, 60), Cells(lastrow, 65)).SpecialCells(xlCellTypeVisible)
'
'Set olMail = myTasks.Find("[Subject] = ""123456""")
'
For Each olMail In myTasks
'
If TypeName(olMail) = "MailItem" Then
If (InStr(1, olMail.Subject, "Japan Observations for ", vbTextCompare) > 0) Then
Set olFMail = olMail.Forward
With olFMail
.To = "Pravin.Angane#eclerx.com;Jaysing.Pardeshi#eclerx.com;Suhas.Bhange#eclerx.com;Dadasaheb.Kamble#eclerx.com"
.CC = "Jaysing.Pardeshi#eclerx.com;Suhas.Bhange#eclerx.com"
.HTMLBody = "<HTML><BODY>" & obwb.Sheets("AutoMail").Range("a40") & "<br><br>" & obwb.Sheets("AutoMail").Range("a41") & "</BODY></HTML>" & RangetoHTML(rng) & olFMail.HTMLBody
.Subject = obwb.Sheets("AutoMail").Range("i42")
End With
Set Myattachments = olFMail.Attachments
While Myattachments.Count > 0
Myattachments.Remove 1
Wend
olFMail.Attachments.Add "\\IPSAABACUS\CM_Shared$\SalesForce\Jyoti Sahay\VA-Training\Scrubbing feedback\Observations\Consolidated observation file - Dec-2022.rar"
olFMail.Display
Exit For
End If
End If
Next
'Dim outForward As Outlook.MailItem
'Set outForward = ActiveExplorer.Selection.Item(1).Forward
'outForward.Recipients.Add "pravin.angane#eclerx.com"
'outForward.Save
End Sub
Function RangetoHTML(rng As Range)
Dim obj As Object
Dim txtstr As Object
Dim File As String
Dim wb As Workbook
File = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
rng.Copy
Set wb = Workbooks.Add(1)
With wb.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
.Cells.EntireColumn.AutoFit
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
With wb.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=File, _
Sheet:=wb.Sheets(1).Name, _
Source:=wb.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
Set obj = CreateObject("Scripting.FileSystemObject")
Set txtstr = obj.GetFile(File).OpenAsTextStream(1, -2)
RangetoHTML = txtstr.readall
txtstr.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
wb.Close savechanges:=False
Kill File
Set txtstr = Nothing
Set obj = Nothing
Set wb = Nothing
End Function
Sub OnlineJapan_Email()
Dim outlookApp
Dim olNs As Outlook.Namespace
Dim Fldr As Outlook.MAPIFolder
Dim olMail As Variant 'Outlook.MailItem
Dim olFMail As Outlook.MailItem
Dim myTasks
Dim sir() As String
Dim rng As Range
'Set outlookApp = New Outlook.Application
Set outlookApp = CreateObject("Outlook.Application")
Set olNs = outlookApp.GetNamespace("MAPI")
Set Fldr = olNs.GetDefaultFolder(olFolderInbox)
Set myTasks = Fldr.Items
Dim wb As Workbook
Dim obwb As Workbook
For Each wb In Workbooks
If wb.Name Like "Consolidated observation file*.xlsb" Then
Set obwb = wb
obwb.Activate
Exit For
End If
Next
lastrow = obwb.Sheets("Daily Observation").Range("bm50000").End(xlUp).Row
Set rng = obwb.Sheets("Daily Observation").Range(Cells(8, 60), Cells(lastrow, 65)).SpecialCells(xlCellTypeVisible)
'
'Set olMail = myTasks.Find("[Subject] = ""123456""")
'
For Each olMail In myTasks
'
If TypeName(olMail) = "MailItem" Then
If (InStr(1, olMail.Subject, "Japan Observations for ", vbTextCompare) > 0) Then
Set olFMail = olMail.Forward
With olFMail
.To = "Pravin.Angane#eclerx.com;Jaysing.Pardeshi#eclerx.com;Suhas.Bhange#eclerx.com;Dadasaheb.Kamble#eclerx.com"
.CC = "Jaysing.Pardeshi#eclerx.com;Suhas.Bhange#eclerx.com"
.HTMLBody = "<HTML><BODY>" & obwb.Sheets("AutoMail").Range("a40") & "<br><br>" & obwb.Sheets("AutoMail").Range("a41") & "</BODY></HTML>" & RangetoHTML(rng) & olFMail.HTMLBody
.Subject = obwb.Sheets("AutoMail").Range("i42")
End With
Set Myattachments = olFMail.Attachments
While Myattachments.Count > 0
Myattachments.Remove 1
Wend
olFMail.Attachments.Add "\\IPSAABACUS\CM_Shared$\SalesForce\Jyoti Sahay\VA-Training\Scrubbing feedback\Observations\Consolidated observation file - Dec-2022.rar"
olFMail.Display
Exit For
End If
End If
Next
'Dim outForward As Outlook.MailItem
'Set outForward = ActiveExplorer.Selection.Item(1).Forward
'outForward.Recipients.Add "pravin.angane#eclerx.com"
'outForward.Save
End Sub
Function RangetoHTML(rng As Range)
Dim obj As Object
Dim txtstr As Object
Dim File As String
Dim wb As Workbook
File = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
rng.Copy
Set wb = Workbooks.Add(1)
With wb.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
.Cells.EntireColumn.AutoFit
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
With wb.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=File, _
Sheet:=wb.Sheets(1).Name, _
Source:=wb.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
Set obj = CreateObject("Scripting.FileSystemObject")
Set txtstr = obj.GetFile(File).OpenAsTextStream(1, -2)
RangetoHTML = txtstr.readall
txtstr.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
wb.Close savechanges:=False
Kill File
Set txtstr = Nothing
Set obj = Nothing
Set wb = Nothing
End Function
I have to send an email that includes a table, in the body, that was copied from a filter table.
The filter table's name is "ds" in this code.
I use function RangetoHTML (code below) but it only copies the format, not the contents of the table:
Sub Email_Syndicate()
Dim OutApp As Object
Dim OutMail As Object
Dim EmailSubject As String
Dim EmailSendTo As String
Dim MailBody As String
Dim cell As Range
Dim Signature As String
Dim ds As Range
Set rng = Range(Range("B2"), Range("B" & Rows.Count).End(xlUp))
For Each cell In rng
rw = cell.Row
If cell.Value <> "" Then
EmailSendTo = cell.Value
Nme = cell.Offset(0, 3).SpecialCells(xlCellTypeVisible)
xCC = cell.Offset(0, 1)
att = cell.Offset(0, 4).Value
EmailSubject = cell.Offset(0, 2)
lr1 = Sheet3.Cells(Rows.Count, 1).End(xlUp).Row
Sheet3.Range("A1:N" & lr1).AutoFilter field:=6, Criteria1:=Sheet4.Range("F2").Value
lr = Sheet3.Cells(Sheet3.Rows.Count, 1).End(xlUp).Row
Set ds = Sheet3.Range("A1:N" & lr).SpecialCells(xlCellTypeVisible)
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(o)
With OutMail
.Display
End With
Signature = OutMail.HTMLBody
'On Error Resume Next
With OutMail
.Subject = EmailSubject
.To = EmailSendTo
.CC = xCC
'.Body = MailBody
.HTMLBody = RangetoHTML(ds)
.Display
.send
End With
Set OutMail = Nothing
Set OutApp = Nothing
MailBody = ""
End If
With Application
.EnableEvents = 1
.Calculation = xlCalculationAutomatic
End With
Set OutMail = Nothing: Set OutApp = Nothing
Next
End Sub
Function RangetoHTML(rng As Range)
Dim fso As Object, ts As Object, TempWB As Workbook, TempFile As String
TempFile = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=xlPasteAll
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteColumnWidths, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
End With
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.readall
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
TempWB.Close 0
Kill TempFile
Set ts = Nothing: Set fso = Nothing: Set TempWB = Nothing
End Function
How can I copy a filter table containing full content to the email body?
Sub SendEmail_1()
Dim outlook As Object
Dim newEmail As Object
Dim xInp As Object
Dim pgEdit As Object
Dim pos As Integer
Set outlook = CreateObject("Outlook.Application")
Set newEmail= outlook.Createitem(o)
'construction email
With newEmail
.Recipients.Add ("person#email.com")
.Subject = "Subject goes here"
Set xInp = newEmail.GetInspector 'gets you into the test editor
Set pgEdit = xInp.WordEditor 'returns a word document object you can edit
'selects data we want to copy into email
Sheets("your Sheet").Range("your Range").Copy
'pastes the excel range over the indicator
pgEdit.Range(Start:=0, End:=1).PasteSpecial Placement:=wdInLine
Application.CutCopyMode = True
.display
.send
End With
End Sub
I'm on VBA 7 and Excel 2010.
I'm trying to create a button that will automatically take cells C4:J15 from my spreadsheet and insert it in an email. But no matter what combination I list for xmailbody (see code), the email is blank. How do I get the values? The formatting would be nice to copy as well, but that's not absolutely necessary
Private Sub CommandButton1_Click()
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
On Error Resume Next
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = ActiveSheet.Range(F7).Value
On Error Resume Next
With xOutMail
.To = "test#test.com"
.CC = ""
.BCC = ""
.Subject = "Schedule Request"
.Body = xMailBody
.Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
MsgBox ("Your request has been submitted to your supervisor. Please contact your supervisor if you do not receive a reply in the same business day")
End Sub
I want to be able to have a button in my excel spreadsheet that will insert values into an outlook email and automatically send. This will be used for employees to email their scheduled hours every week.
Ron de Bruin write really useful code in VBA on his website and had helped me to understand better interactions with Outlook. This one for exemple (just a copy paste, modified for taking your cell F7) might do the job. Do not forget to change the field To, CC, Subject etc:
Sub Mail_Selection_Range_Outlook_Body()
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
'Don't forget to copy the function RangetoHTML in the module.
'Working in Excel 2000-2016
Dim rng As Range
Dim OutApp As Object
Dim OutMail As Object
Set rng = Nothing
On Error Resume Next
Set rng = Range("F7")
On Error GoTo 0
If rng Is Nothing Then
MsgBox "The selection is not a range or the sheet is protected" & _
vbNewLine & "please correct and try again.", 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 = ""
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.HTMLBody = RangetoHTML(rng)
.Send 'or use .Display
End With
On Error GoTo 0
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Function RangetoHTML(rng As Range)
' Changed by Ron de Bruin 28-Oct-2006
' Working in Office 2000-2016
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.readall
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = No
End function
I've been looking for an answer for this for a few weeks, and it's driving me crazy:
I have a macro that copies specific cells to a new email in Outlook. It works perfectly if the IDE is open, but typically if it isn't it pastes the content into the current sheet instead of the new email. Even weirder is that sometimes it WILL work while the IDE is closed, but 99% of the time it won't, making this a nightmare to diagnose.
It's driving me crazy, you guys are my only hope!
Sub EmailReports()
Dim rngSubject As Range
Dim rngTo As Range
Dim rngBody As Range
Dim objOutlook As Object
Dim objMail As Object
Set objOutlook = CreateObject("Outlook.Application")
Set objMail = objOutlook.CreateItem(0)
xRow = ActiveCell.Row
RMName = Sheets("Dashboard").Range("B" & xRow)
LastTaskRow = Sheets(RMName).Range("A1")
With Target
Range("E" & xRow) = Format(Now(), "MM/DD/YYYY")
End With
Set rngTo = Range("C" & xRow)
Set rngSubject = Worksheets("Dashboard").Range("K4")
Set rngBody = Worksheets(RMName).Range("D4:E" & LastTaskRow)
rngBody.Copy
With objMail
.To = rngTo
.Subject = rngSubject
.Display
End With
SendKeys "^({v})", True
Set objOutlook = Nothing
Set objMail = Nothing
End Sub
I tried adding Dmitry's suggestion, though I'm not sure I added it properly.
Sub EmailReports()
Dim rngSubject As Range
Dim rngTo As Range
Dim rngBody As Range
Dim objOutlook As Object
Dim objMail As Object
Set objOutlook = CreateObject("Outlook.Application")
Set objMail = objOutlook.CreateItem(0)
xRow = ActiveCell.Row
RMName = Sheets("Dashboard").Range("B" & xRow)
LastTaskRow = Sheets(RMName).Range("A1")
With Target
Range("E" & xRow) = Format(Now(), "MM/DD/YYYY")
End With
Set rngTo = Range("C" & xRow)
Set rngSubject = Worksheets("Dashboard").Range("K4")
Set rngBody = Worksheets(RMName).Range("D4:E" & LastTaskRow)
rngBody.Copy
With objMail
.To = rngTo
.Subject = rngSubject
.Display
End With
Set objHTML = CreateObject("htmlfile")
ClipboardText = objHTML.ParentWindow.ClipboardData.GetData("text")
objMail.Body = rngBody.Text
Set objOutlook = Nothing
Set objMail = Nothing
End Sub
Instead of using SendKeys (which will send the specified input to the foreground window, whatever it happens to be), paste the text using
Set objHTML = CreateObject("htmlfile")
ClipboardText = objHTML.ParentWindow.ClipboardData.GetData("text")
objMail.Body = ClipboardText
Or, even better, do not use clipboard at all and read the text of the current selection in Excel explicitly and set the Body property in Outlook:
objMail.Body = rngBody.Text
I finally figured it out. Dmitry was on the right track by using an HTML file instead of a simple copy/SendKeys.
Here is the new code:
Sub EmailReports()
Dim rngSubject As Range
Dim rngTo As Range
Dim rngBody As Range
Dim objOutlook As Object
Dim objMail As Object
Set objOutlook = CreateObject("Outlook.Application")
Set objMail = objOutlook.CreateItem(0)
xRow = ActiveCell.Row
RMName = Sheets("Dashboard").Range("B" & xRow)
LastTaskRow = Sheets(RMName).Range("A1")
With Target
Range("E" & xRow) = Format(Now(), "MM/DD/YYYY")
End With
Set rngTo = Range("C" & xRow)
Set rngSubject = Worksheets("Dashboard").Range("K4")
Set rngBody = Worksheets(RMName).Range("D4:E" & LastTaskRow)
With objMail
.To = rngTo
.Subject = rngSubject
.HTMLBody = RangetoHTML(rngBody)
.Display
End With
Set objOutlook = Nothing
Set objMail = Nothing
End Sub
It is calling a function I found on Microsoft's website called "RangetoHTML":
Function RangetoHTML(rng As Range)
' Works in Excel 2000, Excel 2002, Excel 2003, Excel 2007, Excel 2010, Outlook 2000, Outlook 2002, Outlook 2003, Outlook 2007, and Outlook 2010.
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "/" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
' Copy the range and create a workbook to receive the data.
rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
' Publish the sheet to an .htm file.
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
' Read all data from the .htm file into the RangetoHTML subroutine.
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.ReadAll
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
' Close TempWB.
TempWB.Close savechanges:=False
' Delete the htm file.
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
I want to paste a range of cells in Outlook.
Here is my code:
Sub Mail_Selection_Range_Outlook_Body()
Dim rng As Range
Dim OutApp As Object
Dim OutMail As Object
Set rng = Nothing
On Error Resume Next
' Only send the visible cells in the selection.
Set rng = Selection.SpecialCells(xlCellTypeVisible)
Set rng = Sheets("Sheet1").RangeToHtml("D4:D12").SpecialCells(xlCellTypeVisible, xlTextValues)
On Error GoTo 0
If rng Is Nothing Then
MsgBox "The selection is not a range or the sheet is protected. " & _
vbNewLine & "Please correct and try again.", 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 = ThisWorkbook.Sheets("Sheet2").Range("C1").Value
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.HTMLBody = RangeToHtml.rng
' In place of the following statement, you can use ".Display" to
' display the e-mail message.
.Display
End With
On Error GoTo 0
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
I am not getting any error, it just does not paste range in Outlook.
I have removed the On Error Resume Next. It gives me an error
Object doesn't support this property or method.
First off, RangeToHTML. The script calls it like a method, but it isn't. It's a popular function by MVP Ron de Bruin. Coincidentally, that links points to the exact source of the script you posted, before those few lines got b̶u̶t̶c̶h̶e̶r̶e̶d̶ modified.
On with Range.SpecialCells. This method operates on a range and returns only those cells that match the given criteria. In your case, you seem to be only interested in the visible text cells. Importantly, it operates on a Range, not on HTML text.
For completeness sake, I'll post a working version of the script below. I'd certainly advise to disregard it and revisit the excellent original by Ron the Bruin.
Sub Mail_Selection_Range_Outlook_Body()
Dim rng As Range
Dim OutApp As Object
Dim OutMail As Object
Set rng = Nothing
' Only send the visible cells in the selection.
Set rng = Sheets("Sheet1").Range("D4:D12").SpecialCells(xlCellTypeVisible)
If rng Is Nothing Then
MsgBox "The selection is not a range or the sheet is protected. " & _
vbNewLine & "Please correct and try again.", vbOKOnly
Exit Sub
End If
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = ThisWorkbook.Sheets("Sheet2").Range("C1").Value
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.HTMLBody = RangetoHTML(rng)
' In place of the following statement, you can use ".Display" to
' display the e-mail message.
.Display
End With
On Error GoTo 0
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Function RangetoHTML(rng As Range)
' By Ron de Bruin.
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "/" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.ReadAll
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
Often this question is asked in the context of Ron de Bruin's RangeToHTML function, which creates an HTML PublishObject from an Excel.Range, extracts that via FSO, and inserts the resulting stream HTML in to the email's HTMLBody. In doing so, this removes the default signature (the RangeToHTML function has a helper function GetBoiler which attempts to insert the default signature).
Unfortunately, the poorly-documented Application.CommandBars method is not available via Outlook:
wdDoc.Application.CommandBars.ExecuteMso "PasteExcelTableSourceFormatting"
It will raise a runtime 6158:
But we can still leverage the Word.Document which is accessible via the MailItem.GetInspector method, we can do something like this to copy & paste the selection from Excel to the Outlook email body, preserving your default signature (if there is one).
Dim rng as Range
Set rng = Range("A1:F10") 'Modify as needed
With OutMail
.To = "xxxxx#xxxxx.com"
.BCC = ""
.Subject = "Subject"
.Display
Dim wdDoc As Object '## Word.Document
Dim wdRange As Object '## Word.Range
Set wdDoc = OutMail.GetInspector.WordEditor
Set wdRange = wdDoc.Range(0, 0)
wdRange.InsertAfter vbCrLf & vbCrLf
'Copy the range in-place
rng.Copy
wdRange.Paste
End With
Note that in some cases this may not perfectly preserve the column widths or in some instances the row heights, and while it will also copy shapes and other objects in the Excel range, this may also cause some funky alignment issues, but for simple tables and Excel ranges, it is very good: