Question

I am currently automating some PowerPoint 2010 functions in Groovy using Scriptom - though this problem may be generic to any PowerPoint automation approach (ie more of a "VBA macro" issue than the particular environment I'm using?).

(Scriptom allows you to use ActiveX or COM Windows components from Groovy. Underneath the hood it uses the Jacob library (Java COM Bridge), I believe. The underlying code is similar to what I'd use in a VBA macro or other Microsoft automation component, and is based on the PowerPoint 2010 Object API.)

My current code works well and opens PowerPoint visibly and does a range of functions on it - except for a component where I "copy and paste" slides from one document to another, "keeping source formatting".

I have tried two attemps to do this copy and paste step, both leading to a different problem. I wonder if anyone has thoughts on solving either (or both?) of these problems:

Method 1: I use a basic "copy" and "paste" methods, suggested by various others, namely:

sourceSlide.Copy()
destinationSlide = destinationPresentation.Slides.Paste(slideIndex+i-1)
destinationSlide.Design = sourceSlide.Design
destinationSlide.ColorScheme = sourceSlide.ColorScheme
destinationSlide.FollowMasterBackground = sourceSlide.FollowMasterBackground
... and so on copying formats...

That is, I manually copy all the formats across to keep slide-formatting. This is the method used prior to PowerPoint 2010. I've actually got this working, however to copy the formats I loop over each slide in the "source" slidepack and do the copy/paste code above. In this loop, the following line (alone) is problematic:

destinationSlide.Design = sourceSlide.Design

This line runs incredibly slowly once the destination SlidePack has a large number of "Designs" in the SlideMaster. I am copying a source slide-pack of 19 slides, each of which has a different SlideMaster Design Theme (that's how it comes to me). This single line of code takes about 0.01 seconds for copying the first slide over, but by the time it comes to the final slide in the loop, the single line of code takes over 20 seconds to run each time. Thus, copying the first five slides might take <1 second, but the total 20 slides takes around 100 seconds in total, with all the latter slides taking longer and longer to run just this single line. The rest of the code races by!

The slow-down isn't linear, and gets even worse beyond 20 slides. It isn't related to the content on the final slide(s), but seems to be that as the number of SlideMaster "designs/themes" increases it slows exponentially to copy across the "sourceSlide.Design". I realise having a different "Design" object for each slide is a bit of a waste, but I don't own the initial source presentation, and often they do come to me like this, with just slight difference between the Designs for each slide. If I remove the "destinationSlide.Design" line the time it takes can reduce from 100+ seconds to around 1 second!

Method 2: In order to avoid this, and given I'm using PowerPoint 2010, I tried to use the following code, instead:

sourceSlide.Copy() 
def destinationPresentation = objPpt.Presentations.Open(destinationFilename)
destinationPresentation.CommandBars.ExecuteMso("PasteSourceFormatting")

I believe this should provide direct access to PowerPoint 2010 "Paste with Source Formatting" functionality. However, this fails with a "null pointer exception" at the ExecuteMso("PasteSourceFormatting") line.

What am I doing wrong? Is there any way to speed up the slow line in Method 1? Why is method 2 not working at all? It looks like "destinationPresentation.CommandBars" is not null, but that the "ExecuteMso" line throws a null pointer exception.

Are there any other suggestions for efficiently "copy and paste" slides that should work in a reasonable time frame for 20-100 slides, even if there are multiple different designs/themes?

Thanks, in advance, for any ideas.

Was it helpful?

Solution

The problem with method 2 is I was using:

destinationPresentation.CommandBars.ExecuteMso("PasteSourceFormatting")

Whereas this should have been:

destinationPresentation.Application.CommandBars.ExecuteMso("PasteSourceFormatting")

Using this code, I no longer get the null pointer exception.

I've submitted this as an answer to assist anyone who makes a similar error in future.

That being said, I still find that the performance of this approach (method 2) is not significantly better than the manual "copy and paste formats" method (method 1). In both cases, the performance with "paste with source formatting" functionality is many, many times slower than a normal "paste" - and takes around 2 minutes to do the paste of about 20 slides (each with its own design template). This is reduced to less than a second if I use "destination formatting", or don't have each slide with its an individual design template.

This may just be an issue with PowerPoint 2010 performance, however, so I will accept this answer unless someone has more information that would provide a better solution to the performance aspect of the original query.

OTHER TIPS

Not sure it helps, but you can do this sort of thing with Apache POI:

@Grab( 'org.apache.poi:poi-ooxml:3.10-beta1' )
import org.apache.poi.xslf.usermodel.XMLSlideShow

new File( '/tmp/Presentation1.pptx' ).withInputStream { p1 ->
    new File( '/tmp/Presentation2.pptx' ).withInputStream { p2 ->

        // Load our 2 presentations
        inpptx = new XMLSlideShow( p1 )
        outpptx = new XMLSlideShow( p2 )

        // Add slide 1 from inpptx to the end of outpptx
        outpptx.createSlide().importContent( inpptx.slides[ 0 ] )

        // Save it out again to a 3rd presentation
        new File( '/tmp/Presentation3.pptx' ).withOutputStream { out ->
            outpptx.write( out )
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top