C H A P T E R 10 | Microsoft Office 97/Visual Basic Programmer's Guide |
Shapes and the Drawing Layer |
There are three different objects that represent shapes: the Shapes collection, which represents all the shapes in the drawing layer of a Microsoft Excel, Word, or PowerPoint document; the ShapeRange collection, which represents a subset of the shapes in the drawing layer; and the Shape object, which represents an individual shape. In general, you use the Shapes collection when you want to add shapes to the drawing layer or iterate through all the shapes in the drawing layer; you use the Shape object when you want to format or manipulate a single shape; and you use the ShapeRange collection when you want to format or manipulate multiple shapes the same way you work with multiple selected shapes in the user interface.
Note A ShapeRange collection can have as few as one member or as many members as there are shapes in the drawing layer. A ShapeRange collection that contains a single member is essentially equivalent to a Shape object. You can use a ShapeRange collection that contains all the members in the Shapes collection to format all the shapes in the drawing layer at at the same time. Properties and methods that apply to the Shape object also apply to the ShapeRange collection . For information about how these properties and methods behave when they're applied to a ShapeRange collection that contains a single shape or to a ShapeRange collection that contains multiple shapes, see "Working with More Than One Shape" later in this chapter.
Returning the Shapes Collection
To return the entire collection of shapes in the drawing layer,
use the Shapes property. The following example selects
all the shapes in the drawing layer of myDocument.
Returning the Shape Object
Use Shapes(index), where index
is the shape's name or the index number, to return a Shape
object that represents a shape on a slide. The following example
duplicates the third shape on myDocument
and places it on the Clipboard.
Returning the ShapeRange Collection
Use Shapes.Range(index), where index
is either the shape's name or index number or an array of shape
names or shape index numbers (or both), to return a ShapeRange
collection that represents a subset of the Shapes collection.
The following example sets the fill for shapes one and three on
myDocument.
Use Selection.ShapeRange to return a ShapeRange
collection that represents all the shapes in the selection. Use
Selection.ShapeRange(index), where index
is the shape's name or index number, to return a Shape
object that represents one of the shapes in the selection. The
following example sets the fill for the first shape in the selection.
Note The
macro recorder generates selectionbased code
that is, when you work with a shape with the macro recorder turned
on, it records a step for selecting the shape, records a step
for accessing the ShapeRange collection in the selection, and
then records the properties and methods you apply to the shape.
When you write code from scratch or edit recorded code, you can
create more efficient code by skipping the selection step and
returning shapes directly from the Shapes collection.
myDocument.Shapes.SelectAll
The following example duplicates the shape named "Red Square"
on myDocument.
myDocument.Shapes(3).Duplicate
Each shape is assigned a default name (for example, "Rectangle
3") when you add it to the Shapes collection. To give
the shape a more useful, meaningful name, use the Name
property. The following example adds a rectangle to myDocument
and gives the rectangle the name "Red Square."
myDocument.Shapes("Red Square").Duplicate
Tip The
methods that add a shape to the drawing layer also return a reference
to the added shape, so you can add a shape and apply a property
or method to it in a single statement, as shown in the preceding
example. For more information, see "Drawing a Shape on a Document, Worksheet, or Slide" later in this chapter.
myDocument.Shapes.AddShape(msoShapeRectangle,144, 144, 72, 72).Name = "Red Square"
myDocument.Shapes.Range(Array(1, 3)).Fill.PresetGradient _
msoGradientHorizontal, 1, msoGradientLateSunset
ActiveWindow.Selection.ShapeRange(1).Fill.PresetGradient _
msoGradientHorizontal, 1, msoGradientLateSunset
Use one of the methods of the Shapes collection, listed in the following table, to add a shape to a document, worksheet, or slide. For detailed syntax information, see the Help topic for the specific method.
To add this kind of graphic | Use this method |
Callout | AddCallout |
Sticky-note-like comment (PowerPoint only) | AddComment |
Line or curve that connects two other shapes (Microsoft Excel and PowerPoint) | AddConnector |
Bézier curve | AddCurve |
Native Microsoft Excel form control (Microsoft Excel only) | AddFormControl |
Rectangle with no line and no fill and an attached text frame | AddLabel |
Line | AddLine |
Sound or movie (PowerPoint only) | AddMediaObject |
ActiveX control (Word only; use AddOLEObject in Microsoft Excel and PowerPoint) | AddOLEControl |
Embedded or linked OLE object | AddOLEObject |
Picture | AddPicture |
Placeholder for text or for a graphic object (PowerPoint only) | AddPlaceholder |
Open polyline or closed polygon drawing | AddPolyline |
AutoShape | AddShape |
Rectangle with no line and no fill and an attached text frame | AddTextbox |
WordArt | AddTextEffect |
Slide title (PowerPoint only) | AddTitle |
Freeform | BuildFreeform and ConvertToShape |
The following example adds a rectangle to myDocument.
myDocument.Shapes.AddShape msoShapeRectangle, 50, 50, 100, 200
When you add a shape, you usually specify the dimensions of the shape and the position of the upperleft corner of the bounding box for the shape relative to the upperleft corner of the page, worksheet, or slide. Distances in the drawing layer are measured in points (72 points = 1 inch).
The methods that add shapes to the drawing layer return a reference
to each added shape. You can therefore add a shape and apply properties
and methods to it in a single step, as shown in the following
example, which adds a shape to myDocument
and sets its name it the same statement.
The following example adds a shape to myDocument
and formats its fill.
myDocument.Shapes.AddShape(msoShapeIsoscelesTriangle, 10, 10, 100, 100).Name = "shpOne"
With myDocument.Shapes.AddShape(msoShapeRectangle, 90, 90, 90, 50).Fill
.ForeColor.RGB = RGB(128, 0, 0)
.BackColor.RGB = RGB(170, 170, 170)
.TwoColorGradient msoGradientHorizontal, 1
End With
You can use properties and methods of the Shape and ShapeRange objects to move, resize, or delete a shape; change its appearance; or add text to it.
Finding the Properties and Methods You
Need to Perform a Task
Properties and methods that control attributes and behavior common
to all types of shapes apply directly to the Shape and
ShapeRange objects. Related properties and methods that
apply to specific types of shapes are encapsulated in secondary
objects that you return from the Shape object.
Common Properties and Methods
Properties and methods that control and attributes and behavior
common to shapes of different types apply directly to the Shape
and ShapeRange objects. This group includes properties
that control the size and position of the shape (such as Left,
Top, Height, and Width) and methods that
control generic editing behavior (such as Duplicate and
ZOrder). The following example sets the size of shape one
on myDocument.
Properties and Methods for Specific Types of Shapes
Related shape attributes that apply to a specific type of shape
are grouped under secondary objects, such as the FillFormat
object, which contains the properties that apply to shapes with
fills, or the CalloutFormat object, which contains all
the properties that are unique to callouts. To set these kinds
of attributes for a shape, you must first return the object that
contains them and then set properties of that object. For example,
you use the Fill property to return the FillFormat
object, and then you set the ForeColor property of the
FillFormat object to set the fill foreground color for
the specified shape. The following example sets the foreground
color to red for the fill for shape one on myDocument.
The following table shows the objects accessible from the Shape
object that contain functionally related properties and methods.
Note that some of the properties that return these secondary objects
have the same name as the returned object (for example, the PictureFormat
property returns the PictureFormat object) whereas other
properties have the name of the returned object minus the word
"Format" (for example, the Fill property returns
the FillFormat object).
Trying to return certain secondary objects (such as the CalloutFormat,
ConnectorFormat, OLEFormat, PictureFormat,
or TextEffectFormat object) from an inappropriate type
of shape can cause an error. For example, if you apply the OLEFormat
property to a shape that isn't an OLE object, you'll get an error.
(Trying to return certain other secondary objects
such as the FillFormat, LineFormat, ShadowFormat,
or ThreeDFormat object from an inappropriate
type of shape doesn't cause an error.)
To avoid problems, check the Type property and, when applicable,
the AutoShapeType property of a shape before applying a
property or method that applies only to certain types of objects,
and be sure to include error handling in your code. The following
example updates all linked OLE objects on myDocument.
Note that you cannot change the type of an existing object; for
example, you cannot change an object that's not a picture into
a picture.
For information about error handling, see Chapter 14, "Debugging and Error Handling."
Working with the Shape's Fill
The FillFormat object represents a shape's fill. You use
properties and methods of the FillFormat object to set
the type, color, and transparency of the fill. Because there are
a number of factors that determine a fill's appearance, many individually
valid property settings for the FillFormat object don't
make any sense in combination with other properties or without
additional information being supplied. For example, the value
msoPatternDarkVertical for the Pattern property
doesn't make much sense in conjunction with the value msoGradientDiagonalUp
for the GradientStyle property, and the value msoFillPicture
for the Type property doesn't make sense if you haven't
specified a picture file to use.
So that you don't inadvertently assign incompatible values to
individual properties of the FillFormat object or neglect
to supply a necessary piece of information when you assign a property
value, most of the properties are readonly. You can set
their values only by using methods that set multiple individual
properties to compatible values at the same time. For example,
you could not write code that would leave you with the two incompatible
settings mentioned in the preceding paragraph, because using the
Patterned method to set a patterned fill automatically
sets the GradientStyle property to msoGradientMixed,
and using the OneColorGradient, PresetGradient,
or TwoColorGradient method to set a gradient fill automatically
sets the value of the Pattern property to msoPatternMixed.
Use one of the following methods to set a shape's fill type: Background
(PowerPoint only), OneColorGradient, Patterned,
PresetGradient, PresetTextured, Solid, TwoColorGradient,
UserPicture, or UserTextured. You can also use any
of the following read/write properties to control the fill's appearance:
BackColor, ForeColor, Transparency, or Visible.
The following example adds a rectangle to myDocument
and then sets the foreground color, background color, and gradient
for the rectangle's fill.
Adding Shadows and 3D Effects
Use the Shadow property of the Shape object to return
the ShadowFormat object, and use the properties and methods
of the ShadowFormat object to edit a shape's shadow. The
following example sets the shadow for shape three on myDocument
to semitransparent red. If the shape doesn't already have a shadow,
this example adds one to it.
Use the ThreeD property of the Shape object to return
the ThreeDFormat object, and use the properties and methods
of the ThreeDFormat object to edit a shape's extrusion.
The following example adds an oval to myDocument
and then specifies that the oval be extruded to a depth of 50
points and that the extrusion be purple, orthographic, and lit
from the left.
You cannot apply threedimensional formatting to certain
kinds of shapes. Most of the properties and methods of the ThreeDFormat
object for such a shape will fail.
Note If
you don't see the shadow or extrusion you expect, make sure that
the Visible property of the ShadowFormat or ThreeDFormat object
is set to True.
Adding Text to a Shape
The area within a shape that can contain text is called a text
frame. The TextFrame object of a given shape
contains the text in the text frame as well as the properties
and methods that control the alignment and anchoring of the text
frame.
Note Only
builtin, twodimensional AutoShapes have text frames;
lines, connectors, freeforms, pictures, OLE objects, and media
objects don't. Before applying the TextFrame property to a shape,
check to see whether the shape has a text frame. In PowerPoint,
you can do this by checking the value of the HasTextFrame property.
In Microsoft Excel and Word, check the Type property of the shape
to see whether it's a type of shape that can contain text. You
should always include error handling in case the TextFrame property
gets applied to a shape that doesn't have a text frame.
In Word, use the TextRange property of the TextFrame
object to return a Range object that represents the range
of text inside the specified text frame. The following example
adds text to the text frame for shape one in the active document.
In Microsoft Excel, use the Characters property of the
a TextFrame object to return a Characters object
that represents the text inside the specified text frame. The
following example adds text to the text frame for shape one on
the active worksheet.
In PowerPoint, use the TextRange property of the TextFrame
object to return a TextRange object that represents the
range of text inside the specified text frame. The following example
adds text to the text frame for shape one on slide one in the
active presentation.
With myDocument.Shapes(1)
.Height = 50
.Width = 100
End With
myDocument.Shapes(1).Fill.ForeColor.RGB = RGB(255, 0, 0)
Use this property of the Shape object
To return this object
Which contains properties and methods that apply to
Callout CalloutFormat
Callouts
ConnectorFormat (Microsoft Excel and PowerPoint only)
ConnectorFormat
Connectors ControlFormat(Microsoft Excel only)
ControlFormat
Native form controls
Fill FillFormat
Shapes that can contain fills (all shapes except lines)
Line LineFormat
All shapes (the LineFormat object can represent a line or a shape's border)
LinkFormat
LinkFormat Linked OLE objects, linked pictures (Word only), and linked fields (Word only)
OLEFormat
OLEFormat OLE objects
PictureFormat
PictureFormat Pictures and OLE objects
Shadow ShadowFormat
All shapes
TextEffect
TextEffectFormat WordArt objects
ThreeD ThreeDFormat
Shapes that can be extruded
WrapFormat(Word only)
WrapFormat
Shapes that text will wrap around
For Each sh In myDocument.Shapes
If sh.Type = msoLinkedOLEObject Then
sh.LinkFormat.Update
End If
Next
With myDocument.Shapes.AddShape(msoShapeRectangle, 90, 90, 90, 50).Fill
.ForeColor.RGB = RGB(128, 0, 0)
.BackColor.RGB = RGB(170, 170, 170)
.TwoColorGradient msoGradientHorizontal, 1
End With
With myDocument.Shapes(3).Shadow
Visible = True
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0.5
End With
Set myShape = myDocument.Shapes.AddShape(msoShapeOval, 90, 90, 90, 40)
With myShape.ThreeD
.Visible = True
.Depth = 50
.ExtrusionColor.RGB = RGB(255, 100, 255) ' RGB value for purple
.Perspective = False
.PresetLightingDirection = msoLightingLeft
End With
ActiveDocument.Shapes(1).TextFrame.TextRange.Text = "My Text"
ActiveWorksheet.Shapes(1).TextFrame.Characters.Text = "My Text"
ActivePresentation.Slides(1).Shapes(1).TextFrame.TextRange.Text = "My Text"
You use the properties and methods of the OLEFormat object
such as the Activate and DoVerb methods
to control the OLE object contained in a shape. Use the OLEFormat
property of the Shape object to return the OLEFormat
object. The following example performs the default verb for shape
three on myDocument
if this shape contains an OLE object.
With myDocument.Shapes(3)
If .Type = msoEmbeddedOLEObject Or _
.Type = msoLinkedOLEObject Then
.OLEFormat.DoVerb
End If
End With
Use the Object property of the OLEFormat object
to return the OLE object contained in the specified shape. (In
Microsoft Excel, you must use the Object property twice
in a row, separated by the dot operator, to return the OLE object.)
The following example, run from Word or PowerPoint, adds text
to cell A1 on worksheet one in the Microsoft Excel workbook contained
in shape three on myDocument.
With myDocument.Shapes(3)
.OLEFormat.Activate
.OLEFormat.Object.Worksheets(1).Range("A1").Value = "New text"
End With
Use the Application property of the OLE object returned
by the Object property to return the toplevel object
of the application that created the OLE object. The following
example, run from Microsoft Excel, displays the name of the application
in which each embedded OLE object on the active sheet was created.
Notice that you must use the Object property twice in a
row to return an OLE object in Microsoft Excel.
For Each s In ActiveSheet.Shapes
If s.Type = msoEmbeddedOLEObject Then
s.OLEFormat.Activate
MsgBox s.OLEFormat.Object.Object.Application.Name
End If
Next
For information about using ActiveX controls (a special type of interactive OLE object), see Chapter 12, "ActiveX Controls and Dialog Boxes."
There are several ways to work with multiple shapes. If you want to set properties for multiple shapes individually, you can loop through a Shapes or ShapeRange collection and apply properties and methods to the individual Shape objects in the collection. If you want to apply a property or method to multiple shapes at the same time, you can construct a ShapeRange collection that contains the shapes and then apply the property or method to the ShapeRange collection. If you want to form a single shape out of multiple shapes that can then be formatted, sized, and positioned as a single entity, you can group the shapes. If you want to position shapes relative to each other, you can align and distribute them horizontally or vertically.
Constructing a Shape Range That Contains
Only Certain Types of Shapes
If you want to construct a shape range that contains only the
shapes in the specified collection that possess a certain attribute
or attributes, use a conditional statement to test for the attributes
you want, and add the names or index numbers of the shapes that
satisfy your conditions to a dynamic array. You can then construct
a shape range by using this array as an argument. The following
example constructs a shape range that contains all the AutoShapes
on myDocument
and then groups them.
Tip If
you want to include shapes that have one of several possible values
for a property in an array for example, if you
want to include all shapes that are of type msoEmbeddedOLEObject,
msoLinkedOLEObject, msoLinkedPicture, or msoPicture
use a Select Case structure instead of an If
End
If structure to determine which shapes to include in the shape
range.
Applying a Property or Method to Several
Shapes at the Same Time
In the user interface, there are some operations you can perform
with several shapes selected; for example, you can select several
shapes and set all their individual fills at once. There are other
operations you can only perform with a single shape selected;
for example, you can only edit the text in a shape if a single
shape is selected.
In Visual Basic, there are two ways to apply properties and methods
to a set of shapes. These two ways allow you to perform any operation
that you can perform on a single shape on a range of shapes, whether
or not you can perform the same operation in the user interface.
Important Many
properties and methods that apply to the Shape object and the
ShapeRange collection fail if they're applied to certain kinds
of shapes. For example, the TextFrame property fails if it's applied
to a shape that cannot contain text. If you're not positive that
each of the shapes in a ShapeRange collection can have a certain
property or method applied to it, don't apply the property or
method to the collection. If you want to apply one of these properties
or methods to a collection of shapes, you must loop through the
collection and test each individual shape to make sure that it's
an appropriate type of shape before applying one of these properties
or methods to it.
Applying a Property or Method to a ShapeRange Collection
If you can perform an operation on multiple selected shapes in
the user interface at the same time, you can do the programmatic
equivalent by constructing a ShapeRange collection and
then applying the appropriate properties or methods to it. The
following example constructs a shape range that contains the AutoShapes
named "Big Star" and "Little Star" on myDocument
and applies a gradient fill to them.
The following are general guidelines for how properties and methods
behave when they're applied to a ShapeRange collection:
The preceding guidelines also apply when you are setting properties
of shapes that are grouped under secondary objects of the ShapeRange
collection, such as the FillFormat object. If the secondary
object represents operations that can be performed on multiple
selected objects in the user interface, you will be able to return
the object from a ShapeRange collection and set its properties.
For example, you can use the Fill property to return the
FillFormat object that represents the fills of all the
shapes in the ShapeRange collection. Setting the properties
of this FillFormat object will set the same properties
for all the individual shapes in the ShapeRange collection.
Looping Through a Shapes or ShapeRange Collection
Even if you cannot perform an operation on several shapes in the
user interface at the same time by selecting them and then applying
a command, you can perform the equivalent action programmatically
by looping through the Shapes or ShapeRange collection
that contains the shapes you want to work with and applying the
appropriate properties and methods to the individual Shape
objects in the collection. The following example loops through
all the shapes on myDocument
and adds text to each shape that's an AutoShape.
Grouping, Aligning, Distributing, and Layering Shapes
Use the Align and Distribute methods of the ShapeRange
object to align or evenly distribute shapes horizontally or vertically.
Use the ZOrder method of the Shape or ShapeRange
object to change the layering order of shapes on a document relative
to one another. For examples of the syntax you use to perform
these operations, see the appropriate Help topics in Microsoft
Excel, Word, or PowerPoint.
When you want to work with multiple shapes as a single entity,
you can group a range of shapes together into single shape by
using the Group method of the ShapeRange collection.
The following example adds two shapes to myDocument,
groups the two new shapes together, sets the fill for the group,
rotates the group, and then sends it to the back of the drawing
layer.
Use the Ungroup method of the Shape object to ungroup
a group of shapes, and use the Regroup method of the ShapeRange
collection to restore a group of shapes that you've ungrouped.
If you want to work with the individual shapes in a group without
ungrouping them, use the GroupItems property of the Shape
object that represents the group of shapes to return the GroupShapes
object, and use the Item method of the GroupShapes
object to return an individual shape within the group of shapes.
The following example adds three triangles
to myDocument,
groups the triangles, sets a color for the entire group, and then
changes the color for the second triangle only.
With myDocument.Shapes
numShapes = .Count
If numShapes > 1 Then
numAutoShapes = 0
ReDim autoShpArray(1 To numShapes)
For i = 1 To numShapes
If .Item(i).Type = msoAutoShape Then
numAutoShapes = numAutoShapes + 1
autoShpArray(numAutoShapes) = .Item(i).Name
End If
Next
If numAutoShapes > 1 Then
ReDim Preserve autoShpArray(1 To numAutoShapes)
Set asRange = .Range(autoShpArray)
asRange.Group
End If
End If
End With
Set myRange = myDocument.Shapes.Range(Array("Big Star", "Little Star"))
myRange.Fill.PresetGradient msoGradientHorizontal, 1, msoGradientBrass
For Each sh In myDocument.Shapes
If sh.Type = msoAutoShape Then
sh.TextFrame.TextRange.InsertAfter " (version 1)"
End If
Next
With myDocument.Shapes
.AddShape(msoShapeCan, 50, 10, 100, 200).Name = "shpOne"
.AddShape(msoShapeCube, 150, 250, 100, 200).Name = "shpTwo"
With .Range(Array("shpOne", "shpTwo")).Group
.Fill.PresetTextured msoTextureBlueTissuePaper
.Rotation = 45
.ZOrder msoSendToBack
End With
End With
With myDocument.Shapes
.AddShape(msoShapeIsoscelesTriangle, 10, 10, 100, 100).Name = "shpOne"
.AddShape(msoShapeIsoscelesTriangle, 150, 10, 100, 100).Name = "shpTwo"
.AddShape(msoShapeIsoscelesTriangle, 300, 10, 100, 100).Name = "shpThree"
With .Range(Array("shpOne", "shpTwo", "shpThree")).Group
.Fill.PresetTextured msoTextureBlueTissuePaper
.GroupItems(2).Fill.PresetTextured msoTextureGreenMarble
End With
End With