PowerPoint is a creative tool in the right hands but it also includes a much underutilised programming dimension. In this beginner level article, we're going to show you some of some key elements of programming PowerPoint using the VBA (Visual Basic for Applications) editor that's included with Microsoft Office.
We're going to build a small project that is fairly arbitrary in order to demonstrate several key elements of VBA programming. The project will add a user-defined number of random shapes to a given slide.
We're going to look at the following elements when building a simple macro to add a sequence of randomly sized, randomly positioned and randomly coloured shapes:
When you've completed the project, you will be able to create the arbitrary random slide like the one shown below in less than a second!
You will need any version of PowerPoint (including Mac) that uses the latest graphics engine and theme design model. This includes 2013 (which we will use), 2010, 2007 and 2011 for the Mac. Your version of PowerPoint must also have the VBA environment enabled (it is installed by default but your IT administrator may have disabled it).
The first thing to do is to recognise that you will be working in two windows, the PowerPoint slide view that you will be familiar with as a PowerPoint content author and the VBE (Visual Basic Editor). You can either Alt+Tab between the two windows, set them up on a different displays if you have a multi-monitor setup or use the Windows snap feature to show them side-by-side on your desktop.
To start the VBE:
Now that you know how to create a VBA project, let's step back and think about what we need our program to do:
It is good practice to start every code module with the line Option Explicit. What this does is to force the VBA compiler to check that variables have been declared. While this isn't strictly necessary, it will save a lot of debugging issues as your projects get larger and you make the inevitable typos with variables in your code.
Option Explicit
Next, we are going to define a couple of constants to set the minimum and maximum size of the random shapes, which are available globally to any procedure in the project. These are defined outside of procedures:
Public Const ShapeMinSize = 50
Public Const ShapeMaxSize = 200
Now, VBA provides a nice random number generator function called Rnd which generates numbers between 0 and 1 (but not 1 itself). We want to be able to generate integer numbers between different lower and upper limits so instead of repeating the same code multiple times, we're goign to create a function procedure. A function can optionally accept one or more input parameters and optionally returns a single value, string or object.
This is our function to create a random number within provided limits:
Function GetRandomInt(Lower As Integer, Upper As Integer) As Integer
Dim number As Single
' Initialize the random-number generator with a seed based on the system timer
Randomize
Do
' Get a random number between 0 and < 1
number = Rnd()
' Scale it up to the upper limit
number = number * Upper
Loop While number < Lower ' Repeat until the number is above the lower limit
' Set the value returned by the function
GetRandomInt = number
End Function
It's worth pointing out at this stage that it's also good practice to add comments to your code and these are made in VBA by prefixing your comment with a apostrophe.
The function accepts two integer parameters for the Lower and Upper limits and returns a value as an Integer.
The next step is to create our main macro procedure of type Sub:
Sub AddRandomShapes()
End Sub
Checking back on our list of things to do, we need to define the shapes we want to use. Shape types in PowerPoint are defined using an enumeration. Enumerations allow human readable names to be associated with integer values. For example, we could create a custom enumaeration for fruit:
Public Enum Fruit
Apple
Orange
Pear
End Enum
This would assign value of 0 to 2 for the three fruit types which we could then refer to in code by the fruit names. In the same way, Microsoft has defined enumerations for many aspects of the PowerPoint object model. There are over 150 different pre-defined shapes such as rectangle, oval, stars etc. and they are defined by the enumeration msoAutoShapeType. You can check the values in the VBE for enumerations by opening the Object Model with F2 and searching for enumerations, properties, methods and more. We have decide to use the various star shapes in our macro and because the values are not contiguous, we put them in an array so that we can refer to them with our random number generator:
Sub AddRandomShapes()
Dim ShapeIDArray(1 To 10) As Integer
' Shape types are defined with the enumeration msoAutoShapeType
' Stars (points) : 149 (10), 150 (12), 94 (16), 95 (24), 96 (32), 91 (4), 92 (5), 147 (6), 148 (7), 93 (8)
' Load with star shapes
ShapeIDArray(1) = msoShape10pointStar
ShapeIDArray(2) = msoShape12pointStar
ShapeIDArray(3) = msoShape16pointStar
ShapeIDArray(4) = msoShape24pointStar
ShapeIDArray(5) = msoShape32pointStar
ShapeIDArray(6) = msoShape4pointStar
ShapeIDArray(7) = msoShape5pointStar
ShapeIDArray(8) = msoShape6pointStar
ShapeIDArray(9) = msoShape7pointStar
ShapeIDArray(10) = msoShape8pointStar
So, calling ShapeIDArrary(3) will return the enumerated value for a 16 point star.
We now need to declare variables for the shape position and size:
Dim shpTop As Single, shpLeft As Single, shpWidth As Single, shpHeight As Single
And because the user could be using a 16:9 slide, a 4:3 slide or any other slide size, we need to declare variables for the slide height and width:
Dim sldWidth As Single, sldHeight As Single
Finally, we need variables for a loop counter, the number of shapes the user wants to add and an object declaration for the shape that we will add in each occurence of our loop:
Dim counter As Integer
Dim NumShapes As Integer
Dim oShp As Shape
When the macro starts, we need to find out the slide dimensions and we use the SlideWidth and SlideHeight properties in the cascading object model. These properties belong to PageSetup which in turn belongs to the ActivePresentation (the presentation currently in view). The VBA object model is hierarchical and each level is separated with a dot, so these are the two lines we need to get the dimensions saved into our variables:
sldWidth = ActivePresentation.PageSetup.SlideWidth
sldHeight = ActivePresentation.PageSetup.SlideHeight
You'll notice that when you type a dot at the end of a valid property, if it has any children, the Microsoft system called IntelliSense will show you permitted child properties and methods. This makes self-discovery of the object model much easier.
Next we need to get the number of shapes to be added by the user and we use the InputBox function for this:
NumShapes = Val(InputBox("How many random shapes to you want to add to this slide?", _
"Macro by youpresent.biz", 100))
Note that we've split this line in two to make it easier to read. You can do this with any line of code by adding a space plus an underscore at the point where you want to break the line and then press return.
Now we need to set up the main loop in which the shapes will be added to the slide:
For counter = 1 To NumShapes
Next
Within this loop, we need to calculate the shape size and position and we call our random number generator function GetRandomInt to do this:
shpWidth = GetRandomInt(ShapeMinSize, ShapeMaxSize)
shpHeight = shpWidth
shpLeft = GetRandomInt(-shpWidth, CInt(sldWidth))
shpTop = GetRandomInt(-shpWidth, CInt(sldHeight))
We're now going to use the very useful With statement. What this does is allow us to shorten our code by eliminating the need to repeat long object model statements. We want to do something the the collection of shapes in the current slide in view so this line sets that up for us:
With ActivePresentation.Slides(ActiveWindow.View.Slide.SlideIndex).Shapes
And the thing we want to do is add a shape. We could just add the shape and forget about it but because we want to adjust the formatting of the shape after it's been added to the slide, we need to Set a reference to the new shape object:
Set oShp = .AddShape(ShapeIDArray(GetRandomInt(1, 10)), _
shpLeft, shpTop, shpWidth, shpHeight)
We're going to set a random fill colour from the 6 accent colours of the presentation theme, set a transparnecy of 70%, turn on the outline and make it white:
With oShp
.Fill.ForeColor.ObjectThemeColor = GetRandomInt(5, 10)
.Fill.Transparency = 0.7
.Line.Visible = msoTrue
.Line.ForeColor.RGB = RGB(255, 255, 255)
End With
Adding the closing lines to loops, we end up with our completed code:
Option Explicit
Public Const ShapeMinSize = 50
Public Const ShapeMaxSize = 200
Sub AddRandomShapes()
Dim ShapeIDArray(1 To 10) As Integer
Dim shpTop As Single, shpLeft As Single, shpWidth As Single, shpHeight As Single
Dim sldWidth As Single, sldHeight As Single
Dim counter As Integer
Dim NumShapes As Integer
Dim oShp As Shape
' Shape types are defined with the enumeration msoAutoShapeType
' Stars (points) : 149 (10), 150 (12), 94 (16), 95 (24), 96 (32), 91 (4), 92 (5), 147 (6), 148 (7), 93 (8)
' Load with star shapes
ShapeIDArray(1) = msoShape10pointStar
ShapeIDArray(2) = msoShape12pointStar
ShapeIDArray(3) = msoShape16pointStar
ShapeIDArray(4) = msoShape24pointStar
ShapeIDArray(5) = msoShape32pointStar
ShapeIDArray(6) = msoShape4pointStar
ShapeIDArray(7) = msoShape5pointStar
ShapeIDArray(8) = msoShape6pointStar
ShapeIDArray(9) = msoShape7pointStar
ShapeIDArray(10) = msoShape8pointStar
sldWidth = ActivePresentation.PageSetup.SlideWidth
sldHeight = ActivePresentation.PageSetup.SlideHeight
NumShapes = Val(InputBox("How many random shapes to you want to add to this slide?", _
"Macro by youpresent.biz", 100))
For counter = 1 To NumShapes
shpWidth = GetRandomInt(ShapeMinSize, ShapeMaxSize)
shpHeight = shpWidth
shpLeft = GetRandomInt(-shpWidth, CInt(sldWidth))
shpTop = GetRandomInt(-shpWidth, CInt(sldHeight))
With ActivePresentation.Slides(ActiveWindow.View.Slide.SlideIndex).Shapes
Set oShp = .AddShape(ShapeIDArray(GetRandomInt(1, 10)), _
shpLeft, shpTop, shpWidth, shpHeight)
' Choose a random colour from the theme accent colours 1 to 6 (which are enumerations 5 to 10)
With oShp
.Fill.ForeColor.ObjectThemeColor = GetRandomInt(5, 10)
.Fill.Transparency = 0.7
.Line.Visible = msoTrue
.Line.ForeColor.RGB = RGB(255, 255, 255)
End With
End With
Next
End Sub
Function GetRandomInt(Lower As Integer, Upper As Integer) As Integer
Dim number As Single
' Initialize the random-number generator with a seed based on the system timer
Randomize
Do
' Get a random number between 0 and < 1
number = Rnd()
' Scale it up to the upper limit
number = number * Upper
Loop While number < Lower ' Repeat until the number is above the lower limit
' Set the value returned by the function
GetRandomInt = number
End Function
When we run the AddRandomShapes procudure (or macro in this case), we are asked how many shapes we want to add (with a default set to 100) and then they are added to the current slide.
In closing, you will want to save your completed project. To do this, you need to save it in one of the macro-enabled formats, the most common being .pptm but you can also save as macro-enabled templates and slide shows.
The complete project may be downloaded in the macro-enabled PowerPoint pptm format but because Experts Exchange does not yet support the PPTM format, you will need to change the extension to .pptm before opening the file:
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (0)