I have a simple question regarding PowerPoint VBA:
Which VBA code should I use to switch between the "active sheet of paper" (I am sorry I don't know how to name it properly), in which I am doing something with the object(s), and the file (or "field", again sorry for my poor terminology) where all the slides are ?
For example, if I want to move a selected object in the "active sheet of paper" I would use this macro:
ActiveWindow.Selection.ShapeRange.IncrementLeft
6#
and if I want to copy the selected slide in the slides file, I would use this code:
ActiveWindow.Selection.Copy
ActiveWindow.View.Paste
But how can I connect these two pieces of script? Let's say I want to move an object in the "active sheet of paper", then copy this whole "sheet", then create its twin in the slides field, and then jump into the twin sheet of paper to do something with objects there?
Shortly, how do I switch from "paper" to "slides" and back to "paper" in VBA?
(Again, I am sorry for terrible terminology here, I hope you understand what I mean here.)
Thank you all in advance.
If you record a macro in PowerPoint and examine the code, you'll see that it uses the Selection object for just about everything. That's sometimes useful (because it means it's more likely that the code will do what you want if you select another object), but for anything more than a very short macro, it's probably better to refer to the objects directly, as in the following code:
Sub Test()
' Get the active presentation
Dim oPresentation As Presentation
Set oPresentation = ActivePresentation
' Get the first slide in the presentation
Dim oSlide As Slide
Set oSlide = oPresentation.Slides(1)
' Get the first shape on the slide
Dim oShape As Shape
Set oShape = oSlide.Shapes(1)
' Nudge the shape to the right
oShape.Left = oShape.Left + 1
' Copy the whole slide
oSlide.Copy
' Paste the slide as a new slide at position 2
Dim oNewSlides As SlideRange
Set oNewSlides = oPresentation.Slides.Paste(2)
' Get a reference to the slide we pasted
Dim oNewSlide As Slide
Set oNewSlide = oNewSlides(1)
' Get the first shape on the NEW slide
Dim oNewShape As Shape
Set oNewShape = oNewSlide.Shapes(1)
' Nudge the shape to the right
oNewShape.Left = oNewShape.Left + 1
End Sub
Note that pretty much every object has a Select method, so if you do want to explicitly select something, you can. In some cases, you may need to change the active window's view type first - so for example, you can't select a shape on a slide while in slide-sorter view.
Related
I'm currently working on PowerPoint VBA and writing a code to be able to copy the first slide and paste it again in the same presentation. However, I keep getting the error "Clipboard is empty or contains data which may not be posted here" and according to Microsoft page the problem is the use of "ActivePresentation"
I'm looking for another way to refer to the slide that I have open without using ActivePresentation. Any help? Ideas?
The line of code I use ActivePresentation is below:
ActivePresentation.Slides(1).Copy
ActivePresentation.Slides.Paste(ActivePresentation.Slides.Count=1)
Don't copy, duplicate
Dim NewSlide as Slide
Set newSlide = ActivePresentation.Slides(1).Duplicate
NewSlide.MoveTo toPos:=4 'move it to become the fourth slide
Slight variant on Harassed Dad's solution. PPT barks at the Set line because Duplicate returns a SlideRange object rather than a Slide object. .Duplicate(1) returns the first slide in the range as a Slide object. This duplicates slide 2 and moves it to the first position in the presentation.
Sub CopySlide()
Dim oSl As Slide
With ActivePresentation
Set oSl = .Slides(2).Duplicate(1)
oSl.MoveTo (1)
End With
End Sub
I have been searching for hours to try to find the answer to this question, but to no avail, so I'm hoping I can find the answer here.
I want to create a variable that refers to a pre-existing chart in PowerPoint so I can start automating its data. I want to refer to the chart by its name to make things very easy, but no matter what I do I cannot seem to give PPT a satisfactory Chart address.
I have tried almost every possible variation of the below, but without success:
Dim chrtPP As PowerPoint.Chart
Set chrtPP = ActivePresentation.Slides(1).Shapes.Charts("Chart3")
Could someone please tell me what I'm doing wrong?
Thanks!
You need to reference the shape by name (a 'Shape" in PowerPoint is actually any object that is on a slide and can be a simple shape, textbox, table, chart, group, media clip etc.). If you're on PowerPoint 2010 and higher, press Alt+F10 to open the selection pane to find the name of the selected chart object. It may be a standard chart object or a chart within a placeholder object. You can then reference the chart as follows:
Option Explicit
Sub ChartStuff()
Dim oShp As Shape
Dim oCht As Chart
Set oShp = ActivePresentation.Slides(1).Shapes("Chart 3")
If oShp.HasChart Then
Set oCht = oShp.Chart
End If
' Do stuff with your chart
If oCht.HasTitle Then Debug.Print oCht.ChartTitle.Text
' Clean up
Set oShp = Nothing
Set oCht = Nothing
End Sub
The key in programming PowerPoint is to ignore the object name in the Object Model for 'Shape' as it's very misleading!
I'm trying to programatically change the language of each shape in each customlayout in a PowerPoint template and I can't figure out how to do this. I've done it before, but I can't find the macro anymore so I don't really know how I did it. I've been able to select each custom layout though. But I need to loop through each textbox in each layout and select the language as well. My problem is targetting each shape. How do I do this?
This is what I've got so far:
ActiveWindow.ViewType = ppViewSlideMaster
For Each oLayout In ActivePresentation.SlideMaster.CustomLayouts
oLayout.Select
Next
This basically loops through each layout. But I can't figure out how to select each placeholder? How do I do this?
Edit: Resolution is now:
For Each oLayout In ActivePresentation.SlideMaster.CustomLayouts
oLayout.Select
Dim oShape As Shape
For Each oShape In oLayout.Shapes
oShape.Select
Next
Next
Loop through oLayout.Shapes, or perhaps oLayout.Shapes.Placeholders.
Thanks you two. I needed a solution to updating an embedded Excel object on the master slide.
This lead me to the perfect solution
'loops through all shapes in slidemaster
Dim oShape As Shape
For Each oShape In ActivePresentation.SlideMaster.Shapes
oShape.Select
'checks for excel object (type=7)
If oShape.Type = msoEmbeddedOLEObject Then
oShape.OLEFormat.Activate
ActiveWindow.Selection.Unselect 'deactivates shape
End If
Next
I need to be able to copy shapes (chart, table, etc.) programmatically from one slide to another in PowerPoint 2007 keeping their original colors. The source and destination slides are in different presentations which have different themes.
These shapes might be complex and include a lot of colors, e.g., charts, tables, etc. The destination slide must maintain its theme, so I cannot simply copy the entire original slide colorScheme.
When copying a shape manually in PowerPoint, I get an option to "Keep Source Formatting". This copies all the original colors of the shape, converting theme colors into absolute RGB values.
What is the simplest way to do this programmatically?
You need to go to the slide and use Application.CommandBars.ExecuteMso
If you don't need to return to the previously selected slide afterwards, you can skip DoEvents and the second call to Application.CommandBars.ExecuteMso
It seemed like the position of the new shape was sometimes a little bit skewed after pasting, so I obtain a reference to the last shape in the Shapes collection of the second slide and copy the position of the original shape.
At least on my machine, without DoEvents, the macro would do nothing when I executed it (but it would work if I stepped through it).
Sub CopySelectedShapeToNextSlide()
Dim oShape As Shape
Dim oSlide As Slide
Dim nextSlide As Slide
Dim newShape As Shape
Set oShape = Application.ActiveWindow.Selection.ShapeRange(1)
Set oSlide = Application.ActiveWindow.Selection.SlideRange(1)
Set nextSlide = oSlide.Parent.Slides(oSlide.SlideIndex + 1)
oShape.Copy
Application.ActiveWindow.View.GotoSlide nextSlide.SlideIndex
Application.CommandBars.ExecuteMso "PasteSourceFormatting"
Set newShape = nextSlide.Shapes(nextSlide.Shapes.Count)
newShape.Left = oShape.Left
newShape.Top = oShape.Top
DoEvents
Application.ActiveWindow.View.GotoSlide oSlide.SlideIndex
Debug.Print newShape.Name
End Sub
As far as I know, the code below gets a shape from the active window, nudges it a bit, copies the slide and pastes it right after the current one, then turns the pasted slide into an active window, and nudges it again:
Sub Test()
' Get the active presentation
Dim oPresentation As Presentation
Set oPresentation = ActivePresentation
' Get the first slide in the presentation
Dim oSlide As Slide
Set oSlide = oPresentation.Slides(1)
' Get the first shape on the slide
Dim oShape As Shape
Set oShape = oSlide.Shapes(1)
' Nudge the shape to the right
oShape.Left = oShape.Left + 1
' Copy the whole slide
oSlide.Copy
' Paste the slide as a new slide at position 2
Dim oNewSlides As SlideRange
Set oNewSlides = oPresentation.Slides.Paste(2)
' Get a reference to the slide we pasted
Dim oNewSlide As Slide
Set oNewSlide = oNewSlides(1)
' Get the first shape on the NEW slide
Dim oNewShape As Shape
Set oNewShape = oNewSlide.Shapes(1)
' Nudge the shape to the right
oNewShape.Left = oNewShape.Left + 1
End Sub
As far as I can understand, in order to implement this code, I should have an active window opened and it should have at least one shape in it. Before I run this code I have only one slide; after the code has been run, I have two slides: the older one is number 1, and the newer one is number 2.
If I run this code one more time, I will get three slides as a result: the oldest one being still number 1, but the oldest one being number 2, not number 3.
My question is how can I make it produce slides, so that the newer slides are always the ones with a greater ordinal number, i.e. every newly created slide should be the last one in the slide preview sidebar (the lowest one)?
And also, how can I make it into a loop? So that I don't need to re-run this code again and again, but simply make a loop with a given number of loop's iterations.
I guess, if it should be a loop, then slides index should be turned into a variable, but I don't know how to do it in PowerPoint VBA.
I'm not sure your code makes any sense. It essentially:
Gets the 1st slide
Gets the 1st shape on the slide
Moves it 1 unit to the right
Copies the 1st slide
Pastes it in as the 2nd slide
Gets the 1st shape on the new 2nd
slide
Moves it 1 unit to the right
Why is it moving it twice, once on the original and once on the copy?
Regardless to answer your specific questions:
To paste it as the last slide, replace
Set oNewSlides = oPresentation.Slides.Paste(2)
With
Set oNewSlides = oPresentation.Slides.Paste() #no index pastes as last
To loop use something like this:
Dim oPresentation As Presentation
Set oPresentation = ActivePresentation
Dim oSlide As Slide
Dim oSlides As SlideRange
Dim oShape As Shape
Dim slideNumber As Integer
For slideNumber = 1 To 10
Set oSlide = oPresentation.Slides(oPresentation.Slides.Count)
oSlide.Copy
Set oNewSlides = oPresentation.Slides.Paste()
Set oSlide = oNewSlides(1)
Set oShape = oSlide.Shapes(1)
oShape.Left = oShape.Left + 5
Next slideNumber
This takes the last slide, copies it, pastes the copy as the new last one, nudges the first shape to the right, takes new last slide, copies it, pastes the copy as the last one, nudges the first shape to the right, etc.... It'll do this 10 times.