Solution - Novice Challenge 6: How Animated Am I?

For the first five challenges we sort of eased you into all the Visual Basic for Applications (VBA) stuff. This is, after all, the Novice division, so these challenges aren’t supposed to be too hard. But after easing beyond the halfway point, it was time to make things a little more, well, challenging, here in Challenge number 6.

In this challenge you needed to work with several different aspects of Microsoft Office PowerPoint. You had to work with shapes, animations, new slides, all sorts of different things. And we’d have to say that we’re pretty impressed with how well people did on this. (No, it doesn’t take a lot to impress us, but you should feel proud of yourselves anyway.)

Here’s the solution we came up with:

Sub getAnimations()

 

Dim s As Slide

Dim sh As Shape

Dim sObjs As Shapes

 

Dim str As String

 

Dim intSlides As Integer

Dim i As Integer

Dim j As Integer

 

' Set counters

i = 1

j = 0

 

'Find out how many slides there are

intSlides = ActivePresentation.Slides.Count

'Add a new slide to the end of the deck with a new shape

Set sObjs = _

    ActivePresentation.Slides.Add((intSlides + 1), ppLayoutText).Shapes

'Add a title to the new slide

sObjs.Title.TextFrame.TextRange.Text = "Animated Shapes Per Slide"

 

'Cycle through the slides one at a time

For Each s In ActivePresentation.Slides

 

    'Make sure we're not at the last slide

    If i <= intSlides Then

 

        'Cycle through all the shapes on the slide

        For Each sh In s.Shapes

       

            'If there's an animation effect, increment the counter

            If sh.AnimationSettings.TextLevelEffect <> ppAnimateLevelNone Then

                j = j + 1

            End If

 

        Next

 

        'Build a string the has the slide number plus

        ' the number of animations on each slide

        str = str & "Slide " & i & " has " & j & " animated shapes." & vbNewLine

        i = i + 1

 

    End If

   

    j = 0

 

Next

 

'Add the string to the Text shape on the last slide

sObjs.Placeholders(2).TextFrame.TextRange.Text = str

       

End Sub

We start off by declaring a bunch of variables we’ll be using throughout the subroutine and then initializing some counter variables. Next, because we need to go through and look at each slide, we retrieve the Count property of the Slides object to find out how many slides there are:

intSlides = ActivePresentation.Slides.Count

Part of the challenge is to list the results on a new slide. Now that we have the number of slides in the original slide show, we can add one new slide. We do that by calling the Add method:

Set sObjs = _

    ActivePresentation.Slides.Add((intSlides + 1), ppLayoutText).Shapes

 

Notice that we pass the number of slides (intSlides) plus 1 to the Add method. This number represents the position in the presentation where we want to add the new slide. We’re adding to the end of the presentation, so the position would be the number of slides in the original plus 1. We also passed a second parameter to the Add method, ppLayoutText. This parameter specifies the layout of the slide. We want a standard text layout, which will include a title and a text box.

And speaking of the title and text box, notice how, following the call to the Add method we tack on the .Shapes property:

Set sObjs = _

    ActivePresentation.Slides.Add((intSlides + 1), ppLayoutText) .Shapes

 

This returns a collection of all the shapes on the slide we just created (the title shape and text box shape). We assign this collection to the sObjs variable. And the reason we do this becomes evident in the next line of code:

sObjs.Title.TextFrame.TextRange.Text = "Animated Shapes Per Slide"

Here we’re using the object reference sObjs to make it easy to add a title to our new slide.

We now know how many slides we started with (which just happens to be the number of slides we need to look through to find our animations), plus we have a new slide where we can display the results. Now it’s time to start looking for our animations. We do that with a For Each loop:

For Each s In ActivePresentation.Slides

We’re going to go through our presentation one slide at a time, each time assigning the current slide to the variable s. Of course, we don’t need to look at the last slide we just created; we only need to look at the original slides. So the first thing we do is check to make sure we’re not past the original set of slides:

If i <= intSlides Then

If we’re still within the original set of slides, we need to check the slide for animations. Animations exist on shapes, so have to go through each slide and find all the shapes. We do that with another For Each loop:

For Each sh In s.Shapes

For each shape on a slide we check the shape to see whether or not it’s animated. How do we do that? Like this:

If sh.AnimationSettings.TextLevelEffect <> ppAnimateLevelNone Then

We check the TextLevelEffect of the AnimationSettings of each slide to see whether it has an animation. If the shape doesn’t have any animations attached to it then the TextLevelEffect will be equal to ppAnimateLevelNone. If the shape does have an animation attached, we increment our counter by 1, like so:

j = j + 1

In order to display the number of animations per slide on the new slide we created, we’ll need to populate the text box on that slide with a string containing that information. That’s why, after we’ve found all the animations on a slide, we run this line of code:

str = str & "Slide " & i & " has " & j & " animated shapes." & vbNewLine

We’re going to keep building this string as we go, adding information to it for each slide. Because of that we start by assigning the value current contents of the string back to the string:

str = str

Next we add some text, the word Slide:

str = str & "Slide "

We then tack on the slide number, which we’re keeping track of in the variable i:

str = str & "Slide " & i

We add some more text (the word has, with spaces on either side), then we include the number of animations that we kept track of with our counter variable j:

str = str & "Slide " & i & " has " & j

We then end our string with some more text:

str = str & "Slide " & i & " has " & j & " animated shapes."

The end result will be something like this:

Slide 1 has 0 animated shapes.

When we do this for the next slide, we want the information for slide 2 to be on the next line, so the last thing we do in building our string is to add a new line character:

str = str & "Slide " & i & " has " & j & " animated shapes." & vbNewLine

After that we increment our slide counter, reset our animated shapes counter, and start over again with the next slide. After we’ve done that for all the slides, the only thing left to do is to put our string on the last slide:

sObjs.Placeholders(2).TextFrame.TextRange.Text = str

Here’s what your final slide should have looked like:

last slide

And that’s it. Yes, compared to the other challenges so far that seems like a lot, but once we broke it all down it wasn’t that bad, was it? We didn’t think so, either.