Page 1 of 1

COM, Outlook, ClipboardAll

Posted: 21 Aug 2018, 10:18
by Vh_
Hello,

In the code below, ClipboardAll does not appear to be working. I'm copying a range of cells from Excel and then wanting that data to be in the message body, with the formatting and cell colors as a manual paste result. Does anyone know how I can accomplish this?

Thanks in advance!

Code: Select all

Outlook := ComObjActive("Outlook.Application")
email := Outlook.Application.CreateItem(0)
email.To := "[email protected]"
email.Body := ClipboardAll
email.Subject := "COM email test with formatting"
email.Display(true)

Re: COM, Outlook, ClipboardAll

Posted: 21 Aug 2018, 14:38
by FanaticGuru
Vh_ wrote:Hello,

In the code below, ClipboardAll does not appear to be working. I'm copying a range of cells from Excel and then wanting that data to be in the message body, with the formatting and cell colors as a manual paste result. Does anyone know how I can accomplish this?

Thanks in advance!

Code: Select all

Outlook := ComObjActive("Outlook.Application")
email := Outlook.Application.CreateItem(0)
email.To := "[email protected]"
email.Body := ClipboardAll
email.Subject := "COM email test with formatting"
email.Display(true)
The Help for ClipboardAll explains it pretty well.

ClipboardAll returns the binary formatted information of the clipboard and is rarely what you want.

Clipboard is what you would normally use in situations like this.

On a side note, Windows implementation of the clipboard is a complex piece of coding. When you seem to copy only 1 letter to the clipboard, several kilobytes of information is actually copied to the clipboard with all kinds of information about where that 1 letter was copied from and how it should react when pasted to many different applications. ClipboardAll allows you to access this kilobytes of behind the scenes information which is rarely needed.

FG

Re: COM, Outlook, ClipboardAll

Posted: 21 Aug 2018, 14:43
by Vh_
FanaticGuru wrote: The Help for ClipboardAll explains it pretty well.

ClipboardAll returns the binary formatted information of the clipboard and is rarely what you want.

Clipboard is what you would normally use in situations like this.

FG

Thanks for the reply. The only thing is, when I use Clipboard it just behaves as if I were to use "Paste values" option. I'm wanting to keep the boxes and colors of the cells when pasting. Does that help?

Re: COM, Outlook, ClipboardAll

Posted: 21 Aug 2018, 15:00
by FanaticGuru
Vh_ wrote:
FanaticGuru wrote: The Help for ClipboardAll explains it pretty well.

ClipboardAll returns the binary formatted information of the clipboard and is rarely what you want.

Clipboard is what you would normally use in situations like this.

FG

Thanks for the reply. The only thing is, when I use Clipboard it just behaves as if I were to use "Paste values" option. I'm wanting to keep the boxes and colors of the cells when pasting. Does that help?
When you hit control+v to paste something Windows is doing a lot of heavy lifting to make that happen.

First email.Body is plain text only. You would need to use email.HTMLBody but that alone will not solve the problem. You would need to set HTMLBody to the HTML code that you want for the effect you are wanting to achieve. When you hit control+v, Windows figures out what is on the clipboard from all that behinds the scenes data it is storing and then creates the HTML code needed to replicate that and then paste that HTML code into the email.

If you want to do it directly then you have to create that HTML code. If the HTML code is fairly static then that is not all that hard. If you are wanting it to be dynamic and really use anything that is on the clipboard without actually pasting, that is hard. You would basically have to replicate all the heavy lifting that Windows does when pasting, which is a lot.

It is ok though to use a combination of COM and pasting. You could create all the email setup and then paste the body. Then you can easily add stuff before or after the pasted stuff in the email.

FG

Re: COM, Outlook, ClipboardAll

Posted: 21 Aug 2018, 15:22
by Vh_
FanaticGuru wrote:
When you hit control+v to paste something Windows is doing a lot of heavy lifting to make that happen.

First email.Body is plain text only. You would need to use email.HTMLBody but that alone will not solve the problem. You would need to set HTMLBody to the HTML code that you want for the effect you are wanting to achieve. When you hit control+v, Windows figures out what is on the clipboard from all that behinds the scenes data it is storing and then creates the HTML code needed to replicate that and then paste that HTML code into the email.

If you want to do it directly then you have to create that HTML code. If the HTML code is fairly static then that is not all that hard. If you are wanting it to be dynamic and really use anything that is on the clipboard without actually pasting, that is hard. You would basically have to replicate all the heavy lifting that Windows does when pasting, which is a lot.

It is ok though to use a combination of COM and pasting. You could create all the email setup and then paste the body. Then you can easily add stuff before or after the pasted stuff in the email.

FG

I'm not sure where to begin on writing some HTML.. so I looked into a normal paste. The one thing is, when I use window spy I can't seem to 'see' the body messsage. The only control name I can find is "_WwG1" and setting text has no effect. I can however use ControlFocus to activate the body. The only challenge now, is moving the text cursor in the mid area of the text that needs to surround it. I have a template in Outlook so I can see "Run, mytemplatefile" being just fine for creating the email. Any ideas?

Re: COM, Outlook, ClipboardAll

Posted: 21 Aug 2018, 16:02
by FanaticGuru
Vh_ wrote:I'm not sure where to begin on writing some HTML.. so I looked into a normal paste. The one thing is, when I use window spy I can't seem to 'see' the body messsage. The only control name I can find is "_WwG1" and setting text has no effect. I can however use ControlFocus to activate the body. The only challenge now, is moving the text cursor in the mid area of the text that needs to surround it. I have a template in Outlook so I can see "Run, mytemplatefile" being just fine for creating the email. Any ideas?
I would start with the body of the email blank, do the paste, then with some string manipulation put stuff before and after the pasted HTML data.

Here is an example.

Code: Select all

olApp := ComObjActive("Outlook.Application")
olItem := olApp.ActiveWindow.CurrentItem
olItem.HTMLBody := "Stuff Before Pasted Data" olItem.HTMLBody "Stuff After Pasted Data"
This assumes an email is open with some data already in the email. Then it addes stuff before and after the existing stuff.

By the way you can display the olItem.HTMLBody in a MsgBox and see what Window really pasted to the email. It will be a bunch of HTML code, more complex than it needs to be because it also has a bunch of behind the scenes information. Not nearly as much as the clipboard had on it but a condensed version that was generated for this specific paste.

FG

Re: COM, Outlook, ClipboardAll

Posted: 21 Aug 2018, 16:16
by Vh_
FanaticGuru wrote:
Vh_ wrote:I'm not sure where to begin on writing some HTML.. so I looked into a normal paste. The one thing is, when I use window spy I can't seem to 'see' the body messsage. The only control name I can find is "_WwG1" and setting text has no effect. I can however use ControlFocus to activate the body. The only challenge now, is moving the text cursor in the mid area of the text that needs to surround it. I have a template in Outlook so I can see "Run, mytemplatefile" being just fine for creating the email. Any ideas?
I would start with the body of the email blank, do the paste, then with some string manipulation put stuff before and after the pasted HTML data.

Here is an example.

Code: Select all

olApp := ComObjActive("Outlook.Application")
olItem := olApp.ActiveWindow.CurrentItem
olItem.HTMLBody := "Stuff Before Pasted Data" olItem.HTMLBody "Stuff After Pasted Data"
This assumes an email is open with some data already in the email. Then it addes stuff before and after the existing stuff.

By the way you can display the olItem.HTMLBody in a MsgBox and see what Window really pasted to the email. It will be a bunch of HTML code, more complex than it needs to be because it also has a bunch of behind the scenes information. Not nearly as much as the clipboard had on it but a condensed version that was generated for this specific paste.

FG
Yes, lots of complex HTML in that msgbox.. thanks for your help. I may just leave this one be, it seems simple enough manually for now, considering the effort to get this working. :yawn: :)

Re: COM, Outlook, ClipboardAll

Posted: 21 Aug 2018, 18:33
by awel20

Code: Select all

Outlook := ComObjActive("Outlook.Application")
email := Outlook.CreateItemFromTemplate(A_Desktop "\Untitled.oft")
email.To := "[email protected]"
email.Subject := "COM email test with formatting"

; .Display(true) - True to make the window modal. The default value is False.
; The modal window seems to break pasting.
email.Display 

; If Word is not the editor. msoTrue = -1, olEditorWord = 4
if !(Outlook.ActiveInspector.IsWordMail = -1 && Outlook.ActiveInspector.EditorType = 4)
{
    MsgBox, 48, Error, Editor is not Word.
    return
}

WordDoc := Outlook.ActiveInspector.WordEditor
WordApp := WordDoc.Application

; Option1 - Select the end of the document a paste there
; Move selection to the end
;WordApp.Selection.EndOf(6) ; wdStory = 6
; Add a new line
;WordApp.Selection.TypeParagraph

;OR

; Option2 - The template is saved with a bookmark named "MyBookmark"
; The bookmark is used to locate the selection. You could also directly assign text to the bookmark instead of pasting:
; https://autohotkey.com/boards/viewtopic.php?p=84712#p84712
WordDoc.Bookmarks("MyBookmark").Select

; Paste
WordApp.Selection.Paste

Outlook := "", email := "", WordDoc := "", WordApp := ""

Re: COM, Outlook, ClipboardAll

Posted: 21 Aug 2018, 19:42
by FanaticGuru
awel20 wrote:

Code: Select all

Outlook := ComObjActive("Outlook.Application")
email := Outlook.CreateItemFromTemplate(A_Desktop "\Untitled.oft")
email.To := "[email protected]"
email.Subject := "COM email test with formatting"

; .Display(true) - True to make the window modal. The default value is False.
; The modal window seems to break pasting.
email.Display 

; If Word is not the editor. msoTrue = -1, olEditorWord = 4
if !(Outlook.ActiveInspector.IsWordMail = -1 && Outlook.ActiveInspector.EditorType = 4)
{
    MsgBox, 48, Error, Editor is not Word.
    return
}

WordDoc := Outlook.ActiveInspector.WordEditor
WordApp := WordDoc.Application

; Option1 - Select the end of the document a paste there
; Move selection to the end
;WordApp.Selection.EndOf(6) ; wdStory = 6
; Add a new line
;WordApp.Selection.TypeParagraph

;OR

; Option2 - The template is saved with a bookmark named "MyBookmark"
; The bookmark is used to locate the selection. You could also directly assign text to the bookmark instead of pasting:
; https://autohotkey.com/boards/viewtopic.php?p=84712#p84712
WordDoc.Bookmarks("MyBookmark").Select

; Paste
WordApp.Selection.Paste

Outlook := "", email := "", WordDoc := "", WordApp := ""
Good information for more advanced pasting in Outlook.

Outlook emails are composed in a mini-version of Word with almost all of the same COM abilities as Word.

If you just want to paste in an open email at the current position then you can do this:

Code: Select all

^F12::
	olApp := ComObjActive("Outlook.Application")
	wdApp := olApp.ActiveInspector.WordEditor.Application
	wdApp.Selection.Paste
return
Beginning and End of email:

Code: Select all

^F10::
	olApp := ComObjActive("Outlook.Application")
	wdApp := olApp.ActiveInspector.WordEditor.Application
	wdApp.Selection.HomeKey(6) ; Beginning (wdStory = 6)
	wdApp.Selection.Paste
return

^F11::
	olApp := ComObjActive("Outlook.Application")
	wdApp := olApp.ActiveInspector.WordEditor.Application
	wdApp.Selection.EndKey(6) ; End (wdStory = 6)
	wdApp.Selection.Paste
return
As awel20 shows there are lots of other selection commands to paste right where you want. There are many more. Once you get that wdApp handle you can use most all the power that COM with Word brings. I have a script that I use everyday that creates and inserts a table of dynamically generated information into an email.

Here is an example of inserting a table at the end of the current email.

Code: Select all

^F9::
	olApp := ComObjActive("Outlook.Application")
	olMailItem := olApp.ActiveWindow.CurrentItem
	olInspector := olApp.ActiveInspector.WordEditor.Application.ActiveDocument
	olTable := olInspector.Tables.Add(olInspector.Range(olInspector.Range.End - 1), 6, 7, 1, 0) ; Range, NumRows, NumColumns, DefaultTableBehavior, AutoFitBehavior
	olTable.Cell(1,1).Range.Text := "First Cell"
	olTable.Cell(3,2).Range.Text := "Three Down, Two Over"
return
If you are pasting from Excel a table is really what is being created in an email.

Kind of off track from the original post but good information that might be useful to someone.

FG

Re: COM, Outlook, ClipboardAll

Posted: 13 Jan 2021, 11:31
by mankvl
FanaticGuru wrote:
21 Aug 2018, 16:02
Vh_ wrote:I'm not sure where to begin on writing some HTML.. so I looked into a normal paste. The one thing is, when I use window spy I can't seem to 'see' the body messsage. The only control name I can find is "_WwG1" and setting text has no effect. I can however use ControlFocus to activate the body. The only challenge now, is moving the text cursor in the mid area of the text that needs to surround it. I have a template in Outlook so I can see "Run, mytemplatefile" being just fine for creating the email. Any ideas?
I would start with the body of the email blank, do the paste, then with some string manipulation put stuff before and after the pasted HTML data.

Here is an example.

Code: Select all

olApp := ComObjActive("Outlook.Application")
olItem := olApp.ActiveWindow.CurrentItem
olItem.HTMLBody := "Stuff Before Pasted Data" olItem.HTMLBody "Stuff After Pasted Data"
This assumes an email is open with some data already in the email. Then it addes stuff before and after the existing stuff.

By the way you can display the olItem.HTMLBody in a MsgBox and see what Window really pasted to the email. It will be a bunch of HTML code, more complex than it needs to be because it also has a bunch of behind the scenes information. Not nearly as much as the clipboard had on it but a condensed version that was generated for this specific paste.

FG
Any way to change font and size of "Stuff Before Pasted Data" now it's Arial by default.

Re: COM, Outlook, ClipboardAll

Posted: 18 Jan 2021, 17:56
by FanaticGuru
mankvl wrote:
13 Jan 2021, 11:31
FanaticGuru wrote:
21 Aug 2018, 16:02
I would start with the body of the email blank, do the paste, then with some string manipulation put stuff before and after the pasted HTML data.

Here is an example.

Code: Select all

olApp := ComObjActive("Outlook.Application")
olItem := olApp.ActiveWindow.CurrentItem
olItem.HTMLBody := "Stuff Before Pasted Data" olItem.HTMLBody "Stuff After Pasted Data"
Any way to change font and size of "Stuff Before Pasted Data" now it's Arial by default.

You just have to use HTML code.

Code: Select all

olApp := ComObjActive("Outlook.Application")
olItem := olApp.ActiveWindow.CurrentItem
olItem.HTMLBody := "<p><font color=""red"" face=""Verdana"" size=""+1"">Formatted Stuff Before Data</font></p>" olItem.HTMLBody "Stuff After Pasted Data"
; or to avoid the " within a " problem requiring ""
;~ HTMLcode = <p><font color="red" face="Verdana" size="+1">Formatted Stuff Before Data</font></p>
;~ olItem.HTMLBody := HTMLcode olItem.HTMLBody "Stuff After Pasted Data"

FG