Paste in Outlook an excel range - excel

I'm trying to use VBA to paste a selected range from Excel to Outlook. I want to keep it under the same conversation with all the recipients.
I have seen some codes: Outlook Reply or ReplyAll to an Email
I am stuck with this code (Application.ActiveExplorer.Selection).
Any ideas how to do this?
This is the code I have when creating a new email instead of replying:
Sub a()
Dim r As Range
Set r = Range("B1:AC42")
r.Copy
'Paste as picture in sheet and cut immediately
Dim p As Picture
Set p = ActiveSheet.Pictures.Paste
p.Cut
'Open a new mail item
Dim outlookApp As Outlook.Application
Set outlookApp = CreateObject("Outlook.Application")
Dim outMail As Outlook.MailItem
Set outMail = outlookApp.CreateItem(olMailItem)
'Get its Word editor
outMail.Display
Dim wordDoc As Word.Document
Set wordDoc = outMail.GetInspector.WordEditor
With outMail
.BodyFormat = olFormatHTML
.Display
'.HTMLBody = "write your email here" & "<br>" & .HTMLBody
.Subject = ""
.Attachments.Add ("path")
End With
'Paste picture
wordDoc.Range.Paste
For Each shp In wordDoc.InlineShapes
shp.ScaleHeight = 50 shp.ScaleWidth = 50
Next
End Sub

EDIT:
I noticed that your question was edited by another user and now the mention of your need for the email to be a reply-all email is gone. This was probably in order to make your question simpler, but now my answer won't make as much sense. My answer also assumes that you also already have the HTML code needed to insert the email. If that's not the case, you might want to have a look at this gist to get you started on converting a range to HTML code.
The question you are linking to was on Outlook VBA so you have to make sure that you declare your variables differently since in Excel VBA, Application will refer to the Excel application and not Outlook.
Here's how you could go about this:
Sub ReplyAllWithTable()
Dim outlookApp As Outlook.Application
Set outlookApp = CreateObject("Outlook.Application")
Dim olItem As Outlook.MailItem
Dim olReply As MailItem ' ReplyAll
Dim HtmlTable As String
HtmlTable = "<table><tr><td>Test</td><td>123</td></tr><tr><td>123</td><td>test</td></tr></table>"
For Each olItem In outlookApp.ActiveExplorer.Selection
Set olReply = olItem.ReplyAll
olReply.HTMLBody = "Here is the table: " & vbCrLf & HtmlTable & vbCrLf & olReply.HTMLBody
olReply.Display
'Uncomment next line when you're done with debugging
'olReply.Send
Next olItem
End Sub
About pasting range as a picture
If you take the approach in the code above, you won't be able to use the copy-paste method to insert your image. I personally prefer to set the HTML body of the email instead since it gives you more control. If you are ok with using the HTML method you could either:
convert your range to HTML code and insert it inside the email (similarly as how it was done in the code above); or
convert your range to an image, save it and insert it with HTML in the email body.
In order to achieve the 2nd option, you could run the following code:
Sub ReplyAllWithTableAsPicture()
'REFERENCE:
'- https://excel-macro.tutorialhorizon.com/excel-vba-send-mail-with-embedded-image-in-message-body-from-ms-outlook-using-excel/
Dim outlookApp As Outlook.Application
Set outlookApp = CreateObject("Outlook.Application")
Dim olItem As Outlook.MailItem
Dim olReply As MailItem ' ReplyAll
Dim fileName As String
Dim fileFullName As String
fileFullName = Environ("temp") & "\Temp.jpg" 'CUSTOMIZABLE (make sure this file can be overwritten at will)
fileName = Split(fileFullName, "\")(UBound(Split(fileFullName, "\")))
RangeToImage fileFullName:=fileFullName, rng:=ActiveSheet.Range("B1:AC42") 'CUSTOMIZABLE (choose the range to save as picture)
For Each olItem In outlookApp.ActiveExplorer.Selection 'if we have only one email, we could use: set olItem = outlookApp.ActiveExplorer.Selection(1)
Set olReply = olItem.ReplyAll
olReply.Attachments.Add fileFullName, olByValue, 0
olReply.HTMLBody = "Here is the table: " & "<br>" & "<img src='cid:" & fileName & "'>" & vbCrLf & olReply.HTMLBody
olReply.Display
'Uncomment this line when you're done with debugging
'olReply.Send
Next olItem
End Sub
And add the following sub procedure in the module as well:
Sub RangeToImage(ByVal fileFullName As String, ByRef rng As Range)
'REFERENCE:
'- https://analystcave.com/excel-image-vba-save-range-workbook-image/
Dim tmpChart As Chart, n As Long, shCount As Long, sht As Worksheet, sh As Shape
Dim pic As Variant
'Create temporary chart as canvas
Set sht = rng.Worksheet
rng.Copy
sht.Pictures.Paste.Select
Set sh = sht.Shapes(sht.Shapes.Count)
Set tmpChart = Charts.Add
tmpChart.ChartArea.Clear
tmpChart.Name = "PicChart" & (Rnd() * 10000)
Set tmpChart = tmpChart.Location(Where:=xlLocationAsObject, Name:=sht.Name)
tmpChart.ChartArea.Width = sh.Width
tmpChart.ChartArea.Height = sh.Height
tmpChart.Parent.Border.LineStyle = 0
'Paste range as image to chart
sh.Copy
tmpChart.ChartArea.Select
tmpChart.Paste
'Save chart image to file
tmpChart.Export fileName:=fileFullName, FilterName:="jpg"
'Clean up
sht.Cells(1, 1).Activate
sht.ChartObjects(sht.ChartObjects.Count).Delete
sh.Delete
End Sub
Explanations:
In the ReplyAllWithTableAsPicture procedure, we are essentially doing the same thing as the first code, but we are now attaching an image to the email but keep it "hidden" so we can just include it in the body of the email without it being in the list of attachements when people receive the email. To include the image, we use the img tag with a source starting with "cid" allowing us to refer to the "hidden" attachment.
Since the image has to be a file, we use the RangeToImage procedure to generate the image file from the range that we supply. Currently, the file will be saved in the temporary directory always with the same name, which means that the file would be overwritten. Feel free to change the name or add the date to the name if you which to keep copies of these image files.

Instead of creating mail item, Work with Selection item
Example outlookApp.ActiveExplorer.Selection(1)
Your code
Dim outMail As Outlook.MailItem
Set outMail = outlookApp.CreateItem(olMailItem)
'Get its Word editor
outMail.Display
Change to
Dim sel_Item As Outlook.MailItem
Set sel_Item = outlookApp.ActiveExplorer.Selection(1)
Dim outMail As Outlook.MailItem
'Get its Word editor
Set outMail = sel_Item.ReplyAll

Related

Adjusting the size of Excel range pasted to Outlook mail using Word .PasteandFormat

I created code to copy a cell range into an email.
A) This gets me an image where the text is blurry and overly bold
.PasteandFormat wdChartPicture
B) This gets me the correct text clarity but I need to zoom the email itself to x300 to visualize the numbers and letters clearly
.PasteandFormat wdMatchDestinationFormatting
How can I paste in a size that is clear to visualize?
Alternatively how can I increase the pasted image so that the recipient doesn't have to zoom x300 to see the email?
Option Explicit
Sub Send_Email()
Dim OutApp As Object
Dim OutMail As Object
Dim table As Range
Dim pic As Picture
Dim wb As Workbook, ws As Worksheet, wsSettings As Worksheet
Dim wordDoc
Dim strHTMLBody As String
Dim lonZoom As Long
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
Set wb = ThisWorkbook
Set wsSettings = wb.Worksheets("Settings")
'grab table, convert to image, and cut'
Set ws = ThisWorkbook.Sheets("Summary")
Set table = ws.Range("B8:AA338")
ws.Activate
table.Copy
Set pic = ws.Pictures.Paste
pic.Cut
'create email message'
On Error Resume Next
With OutMail
strHTMLBody = strHTMLBody & "</span>"
.HTMLBody = strHTMLBody
.To = wsSettings.Range("Email_To").Value
.Subject = wsSettings.Range("Email_Subject").Value
.Display
Set wordDoc = OutMail.GetInspector.WordEditor
With wordDoc.Range
.PasteandFormat wdMatchDestinationFormatting
End With
End With
On Error GoTo 0
Set OutApp = Nothing
Set OutMail = Nothing
End Sub
You deal with a message body which is an HTML markup. So, you can save the generated image in Excel as a file and then attach it to the mail item and use in the body markup in the way you like.
The Attachments.Add method allows to attach a file. But you need to use an embedded image (not visible attachments). You need to set up the CID property on the attachment and use the CID attribute in the HTML markup.
Refer to the image in the HTML body through the cid attribute
<img src="cid:xyz">
Then add the attachment using Attachments.Add.
After that you can set the PR_ATTACH_CONTENT_ID property (DASL name http://schemas.microsoft.com/mapi/proptag/0x3712001F) using Attachment.PropertyAccessor.SetProperty. This will be your cid value.

Bitmap pasted into Outlook using VBA always blank/white

So I have this code that will capture a range in excel and export it and then embed it into the body of an email, along with a bunch of text however the image is appearing white/blank unless I have the worksheet open in front (I have tried adding code to maximize the window and this doesn't work).
it only seems to work when I run it one line at a time. was hoping someone could help me as I am lost
I am not very good at vba only a small bit of self-teaching so it may be a little ugly looking, sorry I will try to explain more if necessary.
Public reportInterval As String
Public startBody As String
Public digitalBody As String
Public socroBody As String
Public fleetBody As String
Public loopBody As String
Public morningOrDay As String
Public picFile As String
Public picBody As String
Sub emailPic()
'===================================================
' Export Range as PNG file
'===================================================
' Set Range you want to export to file
Dim r As Range
Dim co As ChartObject
Workbooks(controlWS).Sheets(tempWS).Select
Set r = Range("A1:R133")
' Copy range as picture onto Clipboard
r.CopyPicture Appearance:=xlScreen, Format:=xlBitmap
picFile = Environ("Temp") & "\TempExportChart.png"
' Create an empty chart with exact size of range copied
Set co = r.Parent.ChartObjects.Add(Left:=r.Left, Top:=r.Top, Width:=r.Width, Height:=r.Height)
With co
' Paste into chart area, export to file, delete chart.
.Chart.Paste
.Chart.Export picFile
.Delete
End With
End Sub
Sub sendMail()
On Error GoTo ErrHandler
Dim objOutlook As Object
Set objOutlook = CreateObject("Outlook.Application")
Dim objEmail As Object
Set objEmail = objOutlook.CreateItem(olMailItem)
reportInterval = ""
Call emailPic
Call intervalFinder
Call morningOrDayFinder
Call htmlEmailBody
picBody = "<img src=""" & picFile & """ style=""width:304px;height:228px"">"
With objEmail
.Display
.SentOnBehalfOfName =
.To =
.CC =
.Recipients.ResolveAll
.Subject = "Intraday Report: " & reportInterval
.HTMLBody = HTMLBody & startBody & digitalBody & socroBody & fleetBody & loopBody _
& picBody
End With
Set objEmail = Nothing: Set objOutlook = Nothing
ErrHandler:
'
End Sub
The issue is the picture file is being created as blank via the chart object. I have previously found issues using chart objects to save pictures adding borders where I don't want them so I use publishers functions instead to save pictures. This does require a reference to be added.
Updated function to save the picture (you will need to re-edit back to the sheet you want to export)
Sub emailPic()
' Requires reference: Microsoft Publisher x.x Object Library
'===================================================
' Export Range as PNG file
'===================================================
Dim r As Range
Dim picFile As String: picFile = Environ("Temp") & "\TempExport.png"
If Dir(picFile) <> "" Then Kill picFile
With ThisWorkbook.Sheets("Sheet1")
Set r = .Range("A1:R133")
r.CopyPicture Appearance:=xlScreen, Format:=xlBitmap ' Copy range as picture onto Clipboard
End With
Dim PubDoc As New Publisher.Document
PubDoc.Pages(1).Shapes.Paste
PubDoc.Pages(1).Shapes(1).SaveAsPicture _
PbResolution:=pbPictureResolutionCommercialPrint_300dpi, _
Filename:=picFile
PubDoc.Close
End Sub

How do I duplicate / copy an Outlook MailItem

I have a user who sends eMails to a large "To" list, Sometimes over 20 addresses. With this large a "To" list, the received mail sometimes ends up on the recipient's SPAM folder. Obviously, we'd like to avoid this.
My idea is to have the user create an original eMail and then run a Macro. The Macro would loop through all the eMail addresses in an Excel worksheet and then copy the original message and send it to each recipient individually.
I'm unsure as to how to copy a MailItem from the original to a new MailItem. The Excel looping works fine.
Here's my abbreviated macro:
Option Explicit
Sub Send_emails()
'.
'.
Set objDoc = objInspector.WordEditor
Set objWrdApp = objDoc.Application
Set objSelection = objWrdApp.Selection
'Loop through the Rows in the worksheet. Start at row 2 to ignore header
For lngCurrSheetRow = 2 To lngLastSheetRow
strEmailAddress = objWorksheet.Cells(lngCurrSheetRow, 1).Value
'Set objNewMail so that the new message is created and can be referenced.
Set objNewMail = Application.CreateItem(0)
With objNewMail
.Body = objSelection
.To = strEmailAddress
End With
Next lngCurrSheetRow
'.
'.
End Sub
To copy mailitem.body Example would be
Option Explicit
Sub Send_emails()
Dim olMsg As Outlook.MailItem
Set olMsg = ActiveExplorer.Selection.Item(1)
Dim objNewMail As Outlook.MailItem
Set objNewMail = Application.CreateItem(0)
With objNewMail
.Body = olMsg.Body
.Display
End With
End Sub
For HTML Body simply do HTMLBody = olMsg.HTMLBody

Copy range as image and paste into Outlook (results small/blurry)

I'm trying to copy a range of cells as a picture, put that picture in an email, then send the email with an Excel macro.
I'm able to do all of this, however the image comes out smaller/blurrier than the original. I've tried all sorts of copy/paste methods but the results are the same.
When I copy the picture manually with copy as picture (as shown on screen) without a macro, then paste into outlook using just ctrl+v, the image looks fine.
Any idea why this is happening?
Here's the code:
Sub SendMail()
Dim aOutlook As Object
Dim aEmail As Object
Dim rngeAddresses As Range, rngeCell As Range, strRecipients As String
Dim rngeData As Range
Set aOutlook = CreateObject("Outlook.Application")
Set aEmail = aOutlook.CreateItem(0)
Set rngeData = Worksheets("Promo Sync").Range("A5:Y86")
'Copy Range
rngeData.CopyPicture Appearance:=xlScreen, Format:=xlPicture
Dim wordDoc As Word.Document
Set wordDoc = aEmail.GetInspector.WordEditor
'Paste picture
aEmail.Display
wordDoc.Range.Paste
Set rngeAddresses = ActiveSheet.Range("AK2:AK23")
For Each rngeCell In rngeAddresses.Cells
strRecipients = strRecipients & ";" & rngeCell.Value
Next
'Set Subject
aEmail.Subject = "Promo Sync " & Now()
'Set Recipient
aEmail.To = strRecipients
'Send Mail
aEmail.Send
End Sub
Try rngeData.Copy Then wordDoc.Range.PasteAndFormat wdPasteEnhancedMetafile
This should give you good quality wdPasteDataType, similar to Ctrl+V
WdPasteDataType Enumeration (Word)

Pasting formatted Excel range into Outlook message

I would like to paste a range of formatted Excel cells into an Outlook message.
The following code (that I lifted from various sources), runs without error and sends an empty message.
Sub SendMessage(SubjectText As String, Importance As OlImportance)
Dim objOutlook As Outlook.Application
Dim objOutlookMsg As Outlook.MailItem
Dim objOutlookRecip As Outlook.Recipient
Dim objOutlookAttach As Outlook.Attachment
Dim iAddr As Integer, Col As Integer, SendLink As Boolean
'Dim Doc As Word.Document, wdRn As Word.Range
Dim Doc As Object, wdRn As Object
' Create the Outlook session.
Set objOutlook = CreateObject("Outlook.Application")
' Create the message.
Set objOutlookMsg = objOutlook.CreateItem(olMailItem)
Set Doc = objOutlookMsg.GetInspector.WordEditor
'Set Doc = objOutlookMsg.ActiveInspector.WordEditor
Set wdRn = Doc.Range
wdRn.Paste
Set objOutlookRecip = objOutlookMsg.Recipients.Add("MyAddress#MyDomain.com")
objOutlookRecip.Type = 1
objOutlookMsg.Subject = SubjectText
objOutlookMsg.Importance = Importance
With objOutlookMsg
For Each objOutlookRecip In .Recipients
objOutlookRecip.Resolve
' Set the Subject, Body, and Importance of the message.
'.Subject = "Coverage Requests"
'objDrafts.GetFromClipboard
Next
.Send
End With
Set objOutlookMsg = Nothing
Set objOutlook = Nothing
End Sub
I think you need to call .Save on your Mail Item (objOutlookMsg) after you've made all the changes.
Put .Display before .Send,
Simple but Quick fix, your problem is the email is not refreshing with the pasted contents before it sends, forcing it to Display first gives it time...
Also make sure you have another macro which runs before this to Copy the Range into your clipboard...
There is a button in excel to do this, "Send to mail recipent" its not normally on the ribbon.
You can also use the simple mapi built into office using the MailEnvelope in VBA
.. a good article on what you are trying to do http://www.rondebruin.nl/mail/folder3/mail4.htm

Resources