Sunday, August 31, 2008

Automating PowerPoint with Ruby

Here at Ruby on Windows, we've looked at how to automate a variety of applications using Ruby. One popular MS Office app that I haven't yet discussed is PowerPoint, Microsoft's ubiquitous presentation software. But, like other Office apps, PowerPoint exposes a full-featured object model for automating, so there's virtually nothing that you can't do with PowerPoint via Ruby code.

As usual, we'll be leveraging the win32ole library:


require 'win32ole'

We'll start by creating an instance of the PowerPoint Application object, and assigning that object to a variable we'll call ppt :

ppt = WIN32OLE.new('PowerPoint.Application')

Note that PowerPoint (like Outlook and Project) is a single-instance application. This means that if an instance of PowerPoint is already running, that instance will be returned, even though you called the WIN32OLE.new method. If PowerPoint is not currently running, a new instance will be launched.

Like most MS Office applications, the PowerPoint application window is not visible by default when launched from code. To show or hide the Application window, set the Visible property...

ppt.Visible = true

The Presentations collection contains the list of presentation documents currently open. To create a new Presentation, we'll call the Presentations.Add() method...

doc = ppt.Presentations.Add()

To open an existing presentation, we'll call the Presentations.Open() method and pass it the path and name of the PPT file...

doc = ppt.Presentations.Open('c:\docs\mully1.ppt')

The Presentations.Add() and Presentations.Open() methods add the new Presentation object to the Presentations collection, and return a reference to the Presentation object. As you can see above, we're assigning that object to a variable we've called doc.

The Presentation object contains a collection of Slide objects. To add a new slide to your presentation, call the Slides.Add() method and pass it two integers as arguments: the position at which to insert the new slide, and the layout to use for the new slide...

ppLayoutText = 2
slide = doc.Slides.Add(1, ppLayoutText)

The position argument must be between 1 and the current number of slides plus 1.

The Slides.Add() method adds the new slide to the Slides collection and returns a reference to the new slide, which we've assigned to the variable slide.

To get the current count of slides, call the Slides.Count() method.

So, we could use this code to add a new blank slide to the end of the collection:

slide = doc.Slides.Add(doc.Slides.Count + 1, ppLayoutBlank)

You can find a complete list of Slide Layout constants in this Microsoft document.

Each slide object contains a Shapes collection of all objects on the slide, such as textboxes, pictures, and OLE objects.

In the words of Microsoft, a shape object's TextFrame "contains the text in the text frame and the properties and methods that control the alignment and anchoring of the text frame". The TextFrame object's TextRange property "returns a TextRange object that represents the text in the specified text frame". You can get/set the text via the TextRange object's Text property. Got all that? There'll be a quiz later.

Putting this all together, we can insert or change the text of the first textbox on our slide using a line of code like this:

slide.Shapes(1).TextFrame.TextRange.Text = "Hello, World!"

To save your newly-created presentation, call the SaveAs() method and pass it the path and filename:

doc.SaveAs('c:\docs\presentation1.ppt')

To save changes to a previously-saved presentation, call the Save() method:

doc.Save()

Call the presentation object's Close() method to close the presentation, and call the application object's Quit() method to exit the PowerPoint application:

doc.Close()
ppt.Quit()

Well, that's our show for today. There's much more to be covered on this topic. Please let me know if you have specific questions or suggestions for future articles.

Thanks for stopping by!

6 comments:

shevy said...

Very nice info

I wonder if that is possible with Openoffice + Ruby as well though.

aleks.kiev.ua said...

Does anybody know how to get Font Color of text in the Shape?

When I try

Slides(6).Shapes(8).TextFrame.TextRange.
Sentences(1).Font.Color

it always return a String like WIN32OLE:0x3b5af9c

Unknown said...

Hi,
I've changed the settings in my system so that if the download to powerpoint link is clicked then the powerpoint gets opened automatically.

I am using the below code which is working ok but I need to count the no of slides. Pls let me know how would I proceed?
require 'win32ole'

$ie.goto("http://www.thelancet.com/journals/lancet/article/PIIS0140-6736%2810%2960523-5/fulltext")
$ie.link(:text, "Download to PowerPoint").click

###The ppt gets opened automatically as a separate ppt file without file download prompt because settings changed in registry key.

ppt = WIN32OLE.new('PowerPoint.Application')
ppt.Visible = true
##I want to do the count how many slides in the powerpoint.
ppt.Quit()

Anonymous said...

Dear Sir, could you please take look at this issue? http://stackoverflow.com/questions/9213460/opening-powerpoint-presentations-in-ruby-via-win32ole
You clearly seem to be knowledgeable on the topic

David Mullet said...

@Anonymous:

The problem is not necessarily with your code. I created a PowerPoint 2007 file and saved it as 'c:\file.pptx'. Your code ran correctly on my PC without any modifications. I am running Ruby 1.9.2 on Windows 7, with PowerPoint 2007.

What version of PowerPoint? What version of Ruby? Does your PPT deck have any macros? If you open it manually, do you receive any warnings?

_skare said...

How can we select the "Repair" option automatically for damaged files while Open?