PowerPoint from R - Create Amazing Slides

For many of us, there’s just no getting away from PowerPoint. So if you use R (or Python) for data analysis, and PowerPoint for presenting/distributing the results, it’s worthwhile learning how to include this last step into your workflow. In this talk, S Anand uses Python and pywin32 to create some jaw dropping effects in Powerpoint.

RDCOMClient by Duncan Temple Lang allows you to do the same thing using R. It provides the ability to “access and control applications such as Excel, Word, Power Point, Web browsers etc.” Beyond efficiency and repeatability, programmatic access enables you to do things that just would not be possible with point and click.

CautionGratuitous animation ahead

In this tutorial, we’ll learn how to create some elements of the S Anand’s talk, and a few other things, with a focus on interaction and animation. We’ll learn the basics of accessing methods and properties of PowerPoint VBA objects, then scrape data on Clint Eastwood’s movies from IMDB, and use it to create a slide. In the end, we should have a cool, fun PowerPoint slide with Clint Eastwood’s filmography.

(Clearly PowerPoint has a powerful animation engine, and the sophisticated object model allows you to programmatically manipulate almost everything. The Microsoft documentation seems to be organized as a challenge, at least for beginners.)

Let’s get started.
##Setup I’m using:

  • Windows 7 (64bit)
  • Office 2013 (64bit)
  • R version 3.1.3
  • RStudio verison 0.98

We’ll need a few packages.

  1. RDOCMClient by Duncan Temple Lang. COM client that allows us to manipulate PowerPoint through R.
  2. XML by Duncal Temp Lang. Parse XML files.
  3. rvest by Hadley Wickham. Web scraping simplified.

Load the packages:

install.packages(c("RDCOMClient","XML","rvest"))  
library("RDCOMClient")   
library("XML")   
library("rvest")   

##RDCOMClient Basics Some RDCOM basics we’ll need to know:

  • COMCreate starts a new instance of an application.
  • Executing methods takes the form comObj$methodName(arg1,arg2,arg3,...).
  • Setting properties takes the form myObj[["Property"]] = TRUE.

With these basic capabilities, we can access and manipulate all the objects exposed in the PowerPoint API.

Let’s create a new PowerPoint presentation from R

# Start up PowerPoint 
pp <- COMCreate("Powerpoint.Application")

# Make the application visible
pp[["Visible"]] = 1

# Add a new presentation
presentation <- pp[["Presentations"]]$Add()

# The presentation is empty.  Add a slide to it.
slide1 <- presentation[["Slides"]]$Add(1,ms$ppLayoutBlank)
     

The critical part is, of course, knowing what methods and properties are available. This is where the PowerPoint 2013 Developer Reference is handy, but not terribly user-friendly. As a start, let’s recreate one of the examples there, Applying Animations to Shapes in Office 2010, which works with Office 2013 as well.

The VBA Code is:

Sub TestPickupAnimation()
    With ActivePresentation.Slides(1)
        Dim shp1, shp2, shp3 As Shape
        ' Create the initial shape and apply the animations.
        Set shp1 = .Shapes.AddShape(msoShape12pointStar, 20, 20, 100, 100)
       
        .TimeLine.MainSequence.AddEffect shp1, msoAnimEffectFadedSwivel, , msoAnimTriggerAfterPrevious
        .TimeLine.MainSequence.AddEffect shp1, msoAnimEffectPathBounceRight, , msoAnimTriggerAfterPrevious
        .TimeLine.MainSequence.AddEffect shp1, msoAnimEffectSpin, , msoAnimTriggerAfterPrevious
       
        ' Now create a second shape, and apply the same animation to it:
        shp1.PickupAnimation
       
        Set shp2 = .Shapes.AddShape(msoShapeHexagon, 100, 20, 100, 100)
        shp2.ApplyAnimation
       
        ' And one more:
        Set shp3 = .Shapes.AddShape(msoShapeCloud, 180, 20, 100, 100)
        shp3.ApplyAnimation
       
    End With
End Sub

As you can see, Microsoft has defined a set of constants for each element of the presentation, such as shape, animation, trigger, etc. I remember I had to search for a while to find a consolidated list of all the enumerated constants. I created a file and just read them into one variable, ms.

In the ÀddEffect method above, you’ll notice an “empty” argument. That tripped me up for a while, since it doesn’t work with R. The AddEffect method shows the arguments the method expect (expression.AddEffect(Shape, effectId, Level, trigger, Index)). Using an explicitly named argument (trigger) works.

source("mso.txt")
shp1 <- slide1[["Shapes"]]$AddShape(ms$msoShape12pointStar,20,20,100,100)
slide1[["TimeLine"]][["MainSequence"]]$AddEffect(shp1,ms$msoAnimEffectFadedSwivel,
                                                        trigger=ms$msoAnimTriggerAfterPrevious)
slide1[["TimeLine"]][["MainSequence"]]$AddEffect(shp1,ms$msoAnimEffectPathBounceRight,
                                                        trigger=ms$msoAnimTriggerAfterPrevious)
slide1[["TimeLine"]][["MainSequence"]]$AddEffect(shp1,ms$msoAnimEffectSpin,
                                                        trigger=ms$msoAnimTriggerAfterPrevious)

shp1$PickupAnimation()
shp2 <- slide1[["Shapes"]]$AddShape(ms$msoShapeHexagon,100,20,100,100)
shp2$ApplyAnimation()

shp3 <- slide1[["Shapes"]]$AddShape(ms$msoShapeCloud,180,20,100,200)
shp3$ApplyAnimation()

This should create a presentation with the three shapes. If you go into animation mode, the shapes should appear, with the animations triggered.

That’s neat! We now know how to create a new presentation, add shapes and some animation.

Next, we’ll set background and fill colours (soon).

Written on