Automating Paste In Outlook 2007

  • Thread starter Thread starter Neil
  • Start date Start date
N

Neil

I have some code which automates an Edit | Paste in Outlook 2003, as
follows:

objOutlookMsg.GetInspector.CommandBars.Item("Menu
Bar").Controls("Edit").Controls("Paste").Execute

where objOutlookMsg is an object variable set to an e-mail message.

This code works fine in 03. However, it results in an "Automation Error" in
Outlook 2007.

How do I automate an Edit | Paste in Outlook 2007?

Thanks!

Neil
 
objOutlookMsg.GetInspector.CommandBars.ExecuteMso() where the supplied idMso
is that of the ribbon control you want to execute, in this case "Paste".
 
That worked great. Thanks!

The only thing I'm finding is that the code (which sets an Outlook object;
creates a new mail message; set the To and Subject fields; and then pastes
into the body) works most of the time. But every once in a while (maybe one
out of three or four times) I get an automation error at the paste command.
If I break the code and re-execute the paste command, it then works.

So I'm thinking perhaps it's a time thing, where occasionally Outlook is
delayed in creating the mail message, and so the paste command fails because
the message isn't created yet? (Outlook is usually open when it's run; so
it's not a question of Outlook being opened.)

I tried putting a DoEvents statement in between the creation of the mail
message and the execution of the paste command. But it had no effect.

Any idea why I might be getting these intermittent failures? Code I'm
executing is below. Thanks!

Neil

Dim objOutlook As Outlook.Application
Dim objOutlookMsg As Outlook.MailItem
Set objOutlook = GetOutlookObject(False)
Set objOutlookMsg = objOutlook.CreateItem(olMailItem)
With objOutlookMsg
.To = varTo
.Subject = varSubject
.Display
.GetInspector.CommandBars.ExecuteMso ("Paste")
End With

Public Function GetOutlookObject(NewInstance As Boolean) As Object
Dim objOutlook As Object

If NewInstance Then
Set objOutlook = CreateObject("Outlook.Application", "LocalHost")
Else
Set objOutlook = GetAppObject("Outlook.Application")
End If

Set GetOutlookObject = objOutlook
Set objOutlook = Nothing
End Function

Public Function GetAppObject(ClassName As String) As Object
Dim obj As Object
Dim blnError As Boolean

On Error Resume Next
Set obj = GetObject(, ClassName)
blnError = Err.Number > 0

If blnError Then
Set obj = CreateObject(ClassName, "LocalHost")
End If

Set GetAppObject = obj
Set obj = Nothing
End Function
 
Some more information related to what I wrote in my last reply to you.

We found that when Outlook is first started, or when it's closed and
restarted, the code works fine. However, after the first time, it fails.

I put a loop in the code to retry up to 3 times with a 1 second delay
between tries. We found that it always works on the first retry. Never needs
more than one retry.

While I'm glad to have found a workaround, I am curious as to what might be
causing this, and if there's a better way to address the problem.

Thanks!

Neil
 
Hard to say offhand, but first thing I'd do is to add a call to get the
NameSpace and log on as you're not using an Outlook addin:

Dim oNS As Outlook.NameSpace
Set oNS = objOutlook.GetNameSpace("MAPI")
oNS.Logon "", "", False, False

Then, in between calling Display and getting the Inspector I'd add a
DoEvents call. See if that helps.
 
Yeah, I had tried the DoEvents in that spot. Had no effect.

I'll try adding the code for the namespace and log on. I'm not familiar with
those. What does that accomplish?
 
Oh, one other thing. I don't have this problem in 2003; but my client (who's
running Outlook 2007) does have the problem of it working the first time,
but then getting an Automation error from Access after the first time. While
trying to troubleshoot the problem, I sent him a bit of code to put into an
Outlook macro, as follows:

Dim newmail As MailItem
Set newmail = CreateItem(olMailItem)
With newmail
.To = "(e-mail address removed)"
.Subject = "sdljs lksj flkj"
.Display
.GetInspector.CommandBars.ExecuteMso ("Paste")
End With

This worked from Outlook. But then, without my knowledge, he pasted it into
an Access public Sub. And it worked. I was perplexed, because there's no
reference to an Outlook object -- just the reference to the mail item.

In any case, not only did this work without an error, but it didn't have the
same problem of failing on the second time the Paste command is executed. It
worked flawlessly each time.

So this is really bizarre. Why would that work; but when

Dim objOutlook As Outlook.Application
Dim objOutlookMsg As Outlook.MailItem
Set objOutlook = GetAppObject("Outlook.Application")
Set objOutlookMsg = objOutlook.CreateItem(olMailItem)

is used, the Paste command fails after the first time it's used?

Thanks.
 
It makes sure that your Outlook session is the same as the running Outlook
session and logs you into it.

Now for a question that I should have asked before, where is the code
running? Is it running within the Outlook VBA project? If so get rid of the
CreateObject() call and set your Outlook.Application object to the trusted
and intrinsic Application object:

Set objOutlookMsg = Application

In the Access code, if a reference has been set to Outlook in the project
then MailItem would work as long as no reference ahead of that also had a
MailItem object in its object model.
 
The code is all being run from Access (the bit of code I had the client run
from Outlook was just to troubleshoot from Outlook to see what kind of error
we were getting). This is all being run from Outlook using early binding.

Thanks for explaining about why MailItem worked from Access without a
reference to the Outlook object.

Now for the $64,000 question:

why is it, when I do:

Dim objOutlookMsg As MailItem
Set objOutlookMsg = CreateItem(olMailItem)
With objOutlookMsg
.To = "(e-mail address removed)"
.Subject = "sdljs lksj flkj"
.Display
.GetInspector.CommandBars.ExecuteMso ("Paste")
End With

the code works fine, time after time; but when I do:

Dim objOutlook As Outlook.Application
Dim objOutlookMsg As Outlook.MailItem
Set objOutlook = GetObject(, "Outlook.Application")
Set objOutlookMsg = objOutlook.CreateItem(olMailItem)
With objOutlookMsg
.To = "(e-mail address removed)"
.Subject = "sdljs lksj flkj"
.Display
.GetInspector.CommandBars.ExecuteMso ("Paste")
End With

it works fine the first time it's run, but then gives "automation error" on
the "Paste" line the 2nd and subsequent times it's run? (And when the
automation error occurs, it is resolved by looping back to the "Paste" line
after a 1 second delay and trying again.)

I don't know if there's an answer to that. But it's the same code -- except
one makes an explicit reference to the Outlook object, and the other
doesn't. Very bizarre.

Thanks!

Neil
 
I would set up a a more global Outlook.Application object and check it and
only instantiate it if it's nothing. In the initial code when Access is
started I'd put Set objOutlook = Nothing. Then I'd set it and check it
whenever I needed to use it.

If I started Outlook if GetObject() failed I'd use CreateObject() and set a
Boolean to indicate that. If I started Outlook when my code was terminating
I'd close it.

So, something like this:

If (objOutlook Is Nothing) Then
' do application init
End If


I would also establish a NameSpace object globally and instantiate that and
also use the Logon code.

When I got the Inspector I'd do it like this:

Dim oInsp As Outlook.Inspector
Set oInsp = .GetInspector
oInsp.Display
DoEvents
oInsp.CommandBars.ExecuteMso "Paste"
 
Thanks, Ken. I'll give it a shot.

Neil

Ken Slovak said:
I would set up a a more global Outlook.Application object and check it and
only instantiate it if it's nothing. In the initial code when Access is
started I'd put Set objOutlook = Nothing. Then I'd set it and check it
whenever I needed to use it.

If I started Outlook if GetObject() failed I'd use CreateObject() and set
a Boolean to indicate that. If I started Outlook when my code was
terminating I'd close it.

So, something like this:

If (objOutlook Is Nothing) Then
' do application init
End If


I would also establish a NameSpace object globally and instantiate that
and also use the Logon code.

When I got the Inspector I'd do it like this:

Dim oInsp As Outlook.Inspector
Set oInsp = .GetInspector
oInsp.Display
DoEvents
oInsp.CommandBars.ExecuteMso "Paste"
 
Back
Top