如何在PowerPoint 2010中以编程方式复制和粘贴源格式?

时间:2013-08-27 05:39:35

标签: groovy activex powerpoint-vba powerpoint-2010 scriptom

我目前正在使用Scriptom在Groovy中自动化一些PowerPoint 2010功能 - 虽然这个问题可能是任何PowerPoint自动化方法的通用(即比我正在使用的特定环境更多的“VBA宏”问题?)。

(Scriptom允许你使用Groovy的ActiveX或COM Windows组件。我相信它下面使用了Jacob库(Java COM Bridge)。底层代码类似于我在VBA宏中使用的代码或者其他Microsoft自动化组件,基于PowerPoint 2010 Object API。)

我当前的代码效果很好,并且可以看到明显的PowerPoint并在其上执行一系列功能 - 除了我将“幻灯片从一个文档复制并粘贴”到另一个文档的组件,“保持源格式”。

我尝试过两次尝试复制和粘贴步骤,这两种方法都会导致不同的问题。我想知道是否有人想解决这些问题中的任何一个(或两个?):

方法1:我使用基本的“复制”和“粘贴”方法,由其他人建议,即:

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...

也就是说,我手动复制所有格式以保持幻灯片格式化。这是PowerPoint 2010之前使用的方法。我实际上已经有了这个工作,但是要复制我在“源”幻灯片包中的每张幻灯片上循环的格式,并执行上面的复制/粘贴代码。在此循环中,以下行(单独)存在问题:

  

destinationSlide.Design = sourceSlide.Design

一旦目标SlidePack在SlideMaster中有大量“设计”,这条线的运行速度非常慢。我正在复制一个包含19张幻灯片的源幻灯片包,每张幻灯片都有一个不同的SlideMaster设计主题(这就是我的方式)。复制第一个幻灯片时,这一行代码大约需要0.01秒,但是当它进入循环中的 final 幻灯片时,单行代码需要每次运行超过20秒。因此,复制前五张幻灯片可能需要<1秒,但总共20张幻灯片总共花费大约100秒,所有后者幻灯片花费的时间越来越长,仅运行这一行。剩下的代码比赛了!

减速不是线性的,甚至超过20张幻灯片。它与最终幻灯片中的内容无关,但似乎随着SlideMaster“设计/主题”的数量增加,它会以指数方式减慢以复制“sourceSlide.Design”。我意识到为每张幻灯片设置一个不同的“设计”对象有点浪费,但我不拥有初始源代码,并且他们经常会这样来找我,每张幻灯片的设计略有不同。如果我删除“destinationSlide.Design”行,则花费的时间可以从100秒减少到大约1秒!

方法2:为了避免这种情况,并且鉴于我使用的是PowerPoint 2010,我尝试使用以下代码:

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

我认为这应该可以直接访问PowerPoint 2010“使用源格式粘贴”功能。但是,如果null pointer exception行显示“ExecuteMso("PasteSourceFormatting")”,则会失败。

我做错了什么?有没有办法加快方法1中的慢速线?为什么方法2根本不起作用?看起来“destinationPresentation.CommandBars”不为null,但“ExecuteMso”行抛出空指针异常。

是否有其他建议可以有效地“复制和粘贴”幻灯片,这些幻灯片应该在20-100张幻灯片的合理时间范围内工作,即使有多种不同的设计/主题?

提前感谢任何想法。

2 个答案:

答案 0 :(得分:1)

方法2的问题是我正在使用:

destinationPresentation.CommandBars.ExecuteMso("PasteSourceFormatting")

这应该是:

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

使用此代码,我不再获得null pointer exception

我已经提交了这个作为答案,以帮助将来犯下类似错误的任何人。

话虽如此,我仍然发现这种方法(方法2)的性能并没有明显优于手动“复制和粘贴格式”方法(方法1)。在这两种情况下,使用“使用源格式粘贴”功能的性能比普通的“粘贴”慢很多倍,并且大约需要2分钟来完成大约20个幻灯片的粘贴(每个幻灯片都有自己的设计模板)。如果我使用“目标格式化”,或者没有每个幻灯片的单独设计模板,则减少到不到一秒。

这可能只是PowerPoint 2010性能的一个问题,所以我会接受这个答案,除非有人有更多的信息可以为原始查询的性能方面提供更好的解决方案。

答案 1 :(得分:0)

不确定它会有所帮助,但您可以使用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 )
        }
    }
}