Automating PowerPoint

H

Howard Kaikow

It is my understanding that PowerPoint is a single instance app, i.e., there
can be only a single instance of Powerpoint running.

I've been using code such as the following:

'Get existing instance of PowerPoint; otherwise create a new one
' Powerpoint is a single instance application
On Error Resume Next
Set appPPT = GetObject(, "PowerPoint.Application")
If Err.Number = 0 Then
blnNewPPT = False
Else
Set appPPT = New PowerPoint.Application
blnNewPPT = True
End If
On Error Goto 0

and then

With appPPT
If blnNewPPT Then
.Quit
Else
.ActivePresentation.Close
End If
End With

However, I suspect that code may not be good enough.

If I created the NEW PowerPoint instance in code, how can I determine
whether the instance is not being by somebody outside of my code? Somebody
could have started Powerpoint session whilst my code is running, AFTER I
created the NEW Powerpoint.

Is the only choice to leave PowerPoint running?
 
J

Jezebel

PowerPoint is indeed a single instance app. There's no need for the code you
have -- simply use

Set appPPT = new PowerPoint.Application

That will return a reference to the existing instance if there is one, and
create a new instance if not. If someone else then tries to start
PowerPoint, they will get a reference to YOUR instance. Do you need to
prevent that?
 
H

Howard Kaikow

Jezebel said:
PowerPoint is indeed a single instance app. There's no need for the code you
have -- simply use

Set appPPT = new PowerPoint.Application
That will return a reference to the existing instance if there is one, and
create a new instance if not. If someone else then tries to start
PowerPoint, they will get a reference to YOUR instance. Do you need to
prevent that?

That won't do if there are extant Powerpoint sessions.
Cannot quit appPPT if there were already running PowerPoint sessions.

In general, when one creates an instance of an app, e.g., Word, it is
usually desired/necessary to shut down the instance.

However, I cannot to that with PowerPoint as someone could start using
Powerpoint before I get a chance to kill the instance, or somebody may have
already been using Powerpoint, so I cannot kill it, which why it is
inadequate to always use New.
 
J

Jezebel

OK, I think I get what you're asking if I understand you rightly, you want
to quit the instance of PPT when your code finishes, unless a) it was
already running when you started, or b) another app has picked up a
reference to it in the meantime.

The answer is actually straightforward: create the reference using NEW
(which picks up an existing instance if any or creates a new one if not);
make sure you clean up your use of PPT when you've finished (ie save and
close your presentation); then set your reference to nothing.

Try it with the Task Manager running to see what happens ... when you set
the reference to nothing, or simply let it go out of scope, the instance of
PPT quietly disappears from the Task Manager, unless there is another
reference to it ... in which case the instance persists exactly as you'd
expect.


Try this as an experiment --

in VBA: Set objPPT = new PowerPoint.Application

Now start PowerPoint from the desktop

switch back to VBA and use: Set objPPT = nothing
 
H

Howard Kaikow

Jezebel said:
OK, I think I get what you're asking if I understand you rightly, you want
to quit the instance of PPT when your code finishes, unless a) it was
already running when you started, or b) another app has picked up a
reference to it in the meantime.

The answer is actually straightforward: create the reference using NEW
(which picks up an existing instance if any or creates a new one if not);
make sure you clean up your use of PPT when you've finished (ie save and
close your presentation); then set your reference to nothing.

Try it with the Task Manager running to see what happens ... when you set
the reference to nothing, or simply let it go out of scope, the instance of
PPT quietly disappears from the Task Manager, unless there is another
reference to it ... in which case the instance persists exactly as you'd
expect.


Try this as an experiment --

in VBA: Set objPPT = new PowerPoint.Application

Now start PowerPoint from the desktop

switch back to VBA and use: Set objPPT = nothing

That would be OK only if I can find that is documented behavior.
 
H

Howard Kaikow

Came up with a "solution".
Seems too simple to be correct.

For the code below, one needs a Userform with 3 buttons.

1. Shut down any running PowerPoint.
2. Click on the Create PPT button.
3. After the program creates a PPT session, create a PPT session via the
GUI, not using the icon minimized by the code.
4. Click on the Close PPT button.
5. Click on the Bye Bye button.

This code would appear to work for those cases in which my code need not
keep a presentation alive. So, if I close all the code's presentations, this
method appears to work.

If I have to keep a presentation alive, that should be no problem as I just
would not close PowerPoint, just set its object variable = Nothing.

Does this hanky panky solve the problem?

Option Explicit
Private appPPT As Powerpoint.Application
Private blnNewPPT As Boolean
' Private MyPrivateName As String

Private Sub btnByeBye_Click()
Unload Me
End Sub

Private Sub btnClosePPT_Click()
With appPPT
If blnNewPPT Then
If .Presentations.Count = 0 Then
.Quit
lstActions.AddItem "New instance was Quit."
Else
lstActions.AddItem "New instance was NOT Quit."
End If
Else
On Error Resume Next
.ActivePresentation.Close
On Error GoTo 0
lstActions.AddItem "Extant instance was not Quit."
End If
End With
Set appPPT = Nothing
lstActions.AddItem "Set instance = Nothing."
On Error Resume Next
lstActions.AddItem Err.Number & ":" & Err.Description
On Error GoTo 0
End Sub

Private Sub btnCreatePPT_Click()
'Get existing instance of PowerPoint; otherwise create a new one
On Error Resume Next
Set appPPT = GetObject(, "PowerPoint.Application")
lstActions.AddItem Err.Number & ":" & Err.Description
If Err.Number = 0 Then
blnNewPPT = False
lstActions.AddItem "Extant instance is being used."
Else
Set appPPT = New Powerpoint.Application
blnNewPPT = True
lstActions.AddItem "New instance was created."
End If
With appPPT
' MyPrivateName = "HK" & Now & CDbl(Now)
.Visible = True
.WindowState = ppWindowMinimized
lstActions.AddItem "Presentations Count: " & .Presentations.Count
End With
On Error GoTo 0
End Sub
 
J

Jezebel

Seems fair enough. The behaviour isn't documented specifically in respect of
PowerPoint, but it is documented for objects in general: they disappear when
their reference count drops to zero. PowerPoint is merely a well-behaved
object in this sense. (If only all MS objects followed that discipline!)

As a minor side issue: since you are using early binding, it would be better
practice to detect an existing instance of PPT using --

On Error Resume Next
Set appPPT = PowerPoint.Application <======
lstActions.AddItem Err.Number & ":" & Err.Description
If Err.Number = 0 Then

This avoids any possiblity of library conflicts.
 
H

Howard Kaikow

Jezebel said:
Seems fair enough. The behaviour isn't documented specifically in respect of
PowerPoint, but it is documented for objects in general: they disappear when
their reference count drops to zero. PowerPoint is merely a well-behaved
object in this sense. (If only all MS objects followed that discipline!)

Setting the object to Nothing does not make the object go away, even if the
instance was the only one.
This is easily demonstrated using the example from Office 2000 programmer's
guide.

I've been using the wrong terminology. MSFT uses "multi-use" and I've been
using "single use".

Option Explicit
Sub AutomatePPT()
Dim ppApp As PowerPoint.Application

' Because PowerPoint is a multi-use COM component, if
' PowerPoint is not running, initializing an object variable
' to work with the Application object creates new hidden instance.
' But if PowerPoint is already running, initializing the object
' variable returns a reference to the running instance.
Set ppApp = New PowerPoint.Application
' Show this instance of PowerPoint.
ppApp.Visible = True
' Stop ' Press F8 to continue stepping through code.
With ppApp
' Code to automate PowerPoint here.
Debug.Print .Presentations.Count
Debug.Print Hex(.Creator)
Debug.Print .Caption
Debug.Print .Name
End With
'''''''''''''''' ppApp.Quit
Set ppApp = Nothing
End Sub
 
J

Jezebel

Here's one of about a dozen statements from microsoft help files --

On the other hand, setting a variable to Nothing doesn't guarantee that the
object will be removed from memory. It simply reduces the reference count by
one. When the reference count is 0, the object gets removed from memory
automatically.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top