Using VBA to Paste Excel Chart with Data into PowerPoint

匿名 (未验证) 提交于 2019-12-03 01:00:01

问题:

Answer: TL;DR: pasting a chart with embedded data takes a long time so you have to install a delay to prevent vba from moving on before the paste operation completes.

Question:I'm trying to paste an excel chart with embedded data into a powerpoint presentation. The only thing I am getting hung up on is referring to and positioning the chart in ppt once it has been pasted.

    Dim newPowerPoint As PowerPoint.Application      ActiveSheet.ChartObjects("Chart 1").Activate     ActiveChart.ChartArea.Copy     newPowerPoint.CommandBars.ExecuteMso ("PasteExcelChartDestinationTheme") 

Since I need to paste multiple charts into single slides, repositioning them is necessary. I try to do that with this piece of code:

        newPowerPoint.ActiveWindow.Selection.ShapeRange.Left = 0 

but am always met with the error: "Method 'ShapeRange' of object 'Selection' failed".

What's particularly odd is that running the code from start to finish results in this error, but stepping through the code using the F8 key does not.

I have tried every way I can think of to move this chart around but I am totally stuck. Does anyone know how I can do this? Also, please keep in mind that is necessary that the chart have data in it (I can't paste the chart as a picture and I would strongly prefer that the data not be linked).

Thanks,

Steve

edit new modified code with multiple chart objects. I needed to add an if conditional:

If activeSlide.Shapes.Count = 1 Then GoTo NextiLoop End If 

for additional chart objects because the delay pasting chart 2 makes the loop name chart 1 "pptcht2" since chart2 did not exist yet.

Sub CreatePPT()   Dim newPowerPoint As PowerPoint.Application   Dim activeSlide As PowerPoint.Slide   Dim cht1 As Excel.ChartObject   Dim Data As Excel.Worksheet   Dim pptcht1 As PowerPoint.Shape   Dim iLoopLimit As Long    Application.ScreenUpdating = False    'Look for existing instance   On Error Resume Next   Set newPowerPoint = GetObject(, "PowerPoint.Application")   On Error GoTo 0    'Let's create a new PowerPoint   If newPowerPoint Is Nothing Then     Set newPowerPoint = New PowerPoint.Application   End If    'Make a presentation in PowerPoint   If newPowerPoint.Presentations.Count = 0 Then   newPowerPoint.Presentations.Add   End If    'Show the PowerPoint   newPowerPoint.Visible = True   Application.ScreenUpdating = False    'Add a new slide where we will paste the chart   newPowerPoint.ActivePresentation.Slides.Add _       newPowerPoint.ActivePresentation.Slides.Count + 1, ppLayoutText   newPowerPoint.ActiveWindow.View.GotoSlide _       newPowerPoint.ActivePresentation.Slides.Count   Set activeSlide = newPowerPoint.ActivePresentation.Slides _       (newPowerPoint.ActivePresentation.Slides.Count)   activeSlide.Shapes(1).Delete   activeSlide.Shapes(1).Delete    'ActiveSheet.ChartObjects("Chart 1").Activate   Set Data = ActiveSheet    Set cht1 = Data.ChartObjects("Share0110")   Set cht2 = Data.ChartObjects("SOW0110")   Set cht3 = Data.ChartObjects("PROP0110")    cht1.Copy    newPowerPoint.CommandBars.ExecuteMso "PasteExcelChartDestinationTheme"    DoEvents    On Error Resume Next   Do     DoEvents     Set pptcht1 = activeSlide.Shapes(activeSlide.Shapes.Count)     If Not pptcht1 Is Nothing Then Exit Do     iLoopLimit = iLoopLimit + 1     If iLoopLimit > 100 Then Exit Do   Loop   On Error GoTo 0    Debug.Print "iLoopLimit = " & iLoopLimit    With pptcht1     .Left = 25     .Top = 150   End With    iLoopLimit = 0     'ActiveSheet.ChartObjects("Chart 2").Activate   'Set Data = ActiveSheet    cht2.Copy    newPowerPoint.CommandBars.ExecuteMso "PasteExcelChartDestinationTheme"    DoEvents   On Error Resume Next   Do     DoEvents      If activeSlide.Shapes.Count = 1 Then     GoTo NextiLoop     End If     Set pptcht2 = activeSlide.Shapes(activeSlide.Shapes.Count)     If Not pptcht2 Is Nothing Then Exit Do NextiLoop:     iLoopLimit = iLoopLimit + 1     If iLoopLimit > 100 Then Exit Do   Loop   On Error GoTo 0    Debug.Print "iLoopLimit = " & iLoopLimit    With pptcht2     .Left = 275     .Top = 150   End With    iLoopLimit = 0      AppActivate ("Microsoft PowerPoint")     Set activeSlide = Nothing     Set newPowerPoint = Nothing  End Sub 

edit: OLD not working code:

    Sub CreatePPT()          Dim newPowerPoint As PowerPoint.Application         Dim activeSlide As PowerPoint.Slide         Dim cht As Excel.ChartObject          Application.ScreenUpdating = False        'Look for existing instance         On Error Resume Next         Set newPowerPoint = GetObject(, "PowerPoint.Application")         On Error GoTo 0      'Let's create a new PowerPoint         If newPowerPoint Is Nothing Then             Set newPowerPoint = New PowerPoint.Application         End If      'Make a presentation in PowerPoint         If newPowerPoint.Presentations.Count = 0 Then             newPowerPoint.Presentations.Add         End If      'Show the PowerPoint         newPowerPoint.Visible = True         Application.ScreenUpdating = False          'Add a new slide where we will paste the chart             newPowerPoint.ActivePresentation.Slides.Add newPowerPoint.ActivePresentation.Slides.Count + 1, ppLayoutText             newPowerPoint.ActiveWindow.View.GotoSlide newPowerPoint.ActivePresentation.Slides.Count             Set activeSlide = newPowerPoint.ActivePresentation.Slides(newPowerPoint.ActivePresentation.Slides.Count)                     activeSlide.Shapes(1).Delete                     activeSlide.Shapes(1).Delete                'ActiveSheet.ChartObjects("Chart 1").Activate             Set Data = ActiveSheet             Set cht1 = Data.ChartObjects("Chart 1")             cht1.Copy              newPowerPoint.CommandBars.ExecuteMso ("PasteExcelChartDestinationTheme")              Set pptcht1 = newPowerPoint.ActiveWindow.Selection                 With pptcht1                     .Left = 0                     End With         AppActivate ("Microsoft PowerPoint")     Set activeSlide = Nothing     Set newPowerPoint = Nothing  End Sub 

回答1:

  1. Do yourself a favor and enter this as the first line of the code module:

Option Explicit

This will force you to declare all variables. You have a lot of undeclared variables, including a couple that are almost the same as the few you did declare. Then go to VBA's Tools menu > Options, and check the Require Variable Declaration on the first tab of the dialog, which will put Option Explicit at the top of every new module.

  1. Declare the shape as a PowerPoint.Shape, then find it using this, since any newly added shape is the last one on the slide:

Set pptcht1 = activeSlide.Shapes(activeSlide.Shapes.Count)

  1. The following line first of all does not need the parentheses, despite the poorly written Microsoft Help article. Second, it takes a long time to run. Excel is already trying to move the shape long before the shape has been created. DoEvents is supposed to help with this by making Excel wait until everything else happening on the computer is finished, but the line is still too slow.

newPowerPoint.CommandBars.ExecuteMso ("PasteExcelChartDestinationTheme")

So I cobbled together a little loop that tries to set the variable to the shape, and keeps looping until the shape is finished being created.

On Error Resume Next Do   DoEvents   Set pptcht1 = activeSlide.Shapes(activeSlide.Shapes.Count)   If Not pptcht1 Is Nothing Then Exit Do   iLoopLimit = iLoopLimit + 1   If iLoopLimit > 100 Then Exit Do Loop On Error GoTo 0 

In a small number of tests, I found that the loop would have to run 20 to 60 times. I also crashed PowerPoint a few times. Weird.

I'm sure there are better ways to paste the copied chart and keep the slide's color theme, but off the top of my head I don't know one.

  1. This is unreliable, since the application caption changes with different versions of Office (and again the parentheses are not needed):

AppActivate ("Microsoft PowerPoint")

Use this instead:

AppActivate newPowerPoint.Caption

  1. So your whole code becomes:

` Sub CreatePPT()

  Dim newPowerPoint As PowerPoint.Application   Dim activeSlide As PowerPoint.Slide   Dim cht1 As Excel.ChartObject   Dim Data As Excel.Worksheet   Dim pptcht1 As PowerPoint.Shape   Dim iLoopLimit As Long    Application.ScreenUpdating = False    'Look for existing instance   On Error Resume Next   Set newPowerPoint = GetObject(, "PowerPoint.Application")   On Error GoTo 0    'Let's create a new PowerPoint   If newPowerPoint Is Nothing Then     Set newPowerPoint = New PowerPoint.Application   End If    'Make a presentation in PowerPoint   If newPowerPoint.Presentations.Count = 0 Then   newPowerPoint.Presentations.Add   End If    'Show the PowerPoint   newPowerPoint.Visible = True   Application.ScreenUpdating = False    'Add a new slide where we will paste the chart   newPowerPoint.ActivePresentation.Slides.Add _       newPowerPoint.ActivePresentation.Slides.Count + 1, ppLayoutText   newPowerPoint.ActiveWindow.View.GotoSlide _       newPowerPoint.ActivePresentation.Slides.Count   Set activeSlide = newPowerPoint.ActivePresentation.Slides _       (newPowerPoint.ActivePresentation.Slides.Count)   activeSlide.Shapes(1).Delete   activeSlide.Shapes(1).Delete    'ActiveSheet.ChartObjects("Chart 1").Activate   Set Data = ActiveSheet   Set cht1 = Data.ChartObjects("Chart 1")   cht1.Copy    newPowerPoint.CommandBars.ExecuteMso "PasteExcelChartDestinationTheme"    DoEvents    On Error Resume Next   Do     DoEvents     Set pptcht1 = activeSlide.Shapes(activeSlide.Shapes.Count)     If Not pptcht1 Is Nothing Then Exit Do     iLoopLimit = iLoopLimit + 1     If iLoopLimit > 100 Then Exit Do   Loop   On Error GoTo 0    Debug.Print "iLoopLimit = " & iLoopLimit    With pptcht1     .Left = 0   End With    AppActivate newPowerPoint.Caption   Set activeSlide = Nothing   Set newPowerPoint = Nothing  End Sub` 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!