You are on page 1of 20

Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Peltier Tech Blog Search this website Search


Peltier Tech Excel Charts and Programming Blog

Excel Chart Add-Ins Advanced Excel Training Jons Excel and Chart Pages RSS Email Feed Facebook Twitter

Programming Excel 2007 and Excel 2010 AutoShapes with Peltier Tech Home
About Jon Peltier
VBA (Guest Post)
About Peltier Tech
Tuesday, January 12, 2010 by Jon Peltier Copyright and Licensing
Peltier Technical Services, Inc., Copyright 2017.
Blog Comment Policy
Privacy Policy

Today I am pleased to present a guest post written by my colleague Nicholas Hebb. Nick appears
online frequently, commenting on Excel-related blogs and corresponding in the various forums. 2017 International Excel
Conferences
Programming Excel 2007 and Excel 2010 AutoShapes with VBA
By Nicholas Hebb

With the release of Office 2007, Microsoft rewrote the drawing tools from the ground up. On the plus side, this
meant new shapes, new styles, and the addition of SmartArt. On the downside, they didnt have time to
incorporate AutoShape operations in their macro recorder prior to release. Thankfully, Excel 2010 has added
macro support back, but like all macros the code generated is often bloated and relies heavily on the
Selection object, which tends to hide the core objects in use. For the most part, the online help is good, but
there is some information that doesnt get explained in detail. This article attempts to provide a basic overview
of working with AutoShapes using VBA and touch on some areas that are not covered extensively in the help
documentation.

Definitions
Two properties of the Shape object will be used in the code samples below Shape.Type and
Shape.AutoShapeType. Excel has a broad range of shape Types consisting not only of AutoShapes, but
also connectors, lines, pictures, charts, comments, and many other graphical items. For AutoShapes, the
AutoShapeType property lets you get/set the type of shape as shown in the gallery image below.

Peltier Tech Products that Create


Special Charts in Microsoft Excel

Knowing when to check the Shape.Type property versus the Shape.AutoShapeType is very useful. For
example, if the AutoShapeType value is -2, then for all practical purposes the shape is not an AutoShape. If
the value is greater than 1, then the shape is one of the types display in the Shapes gallery. The tricky part
comes when the AutoShapeType is 1, which equals the AutoShape constant msoShapeRectangle. It could
be a Rectangle AutoShape, but it could also be anything shaped like a rectangle, such as a text box, a
comment, or even a picture. So if the AutoShapeType evaluates to 1, then you also need to check the Type

1 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

property.

Callouts are another special type of shape tha


Miscellaneous Issues section below.

Accessing a Shape Object


Peltier Technical Services, Inc. Copyright 2017. Admin
Each worksheet contains a Shapes collection consisting of Shape objects. Like other collections in VBA, the
Shape object is accessed either via its name or index number, as in:

ActiveSheet.Shapes("SHAPE_NAME")

or

ActiveSheet.Shapes(1)

Or, using the ForEach syntax:

Dim shp as Shape


For Each shp in ActiveSheet.Shapes
MsgBox shp.Name
Next

Adding an AutoShape
The syntax for adding a shape is:

Recent Blog Posts


Worksheet.Shapes.AddShape(AutoShapeType, Left, Top, Width, Height)
Upcoming 2017 Conferences and
The AutoShapeType is a constant that ranges from 1 to 137 for Excel 2003 and earlier versions. Excel 2007 Training
added shapes 139 through 183. AutoShapeTypes 125-136 are special AutoShapes. The online help file
Open CSV File and Chart CSV Data
states that they support mouse over and click events, but that only applies when they are used in PowerPoint
presentations. You can use them in Excel but they dont have any special properties. Excel Books
Connect Two XY Series with Arrows
To see what the AutoShapeType constant is for each AutoShape, you can copy and paste the following code
Export an Excel Chart to Word
into the Excel Visual Basic Editor and run it (or download the sample file and run the macro). Not all the
AutoShapes are available in the Shapes gallery, so this will also give you a look at some of the hidden ones. Export an Excel Chart to PowerPoint
Chart a Wide Range of Values
Sub CreateAutoshapes() The New Waterfall Chart in Excel 2016
Dim i As Integer
Dim t As Integer
Popular Blog Posts
Dim shp As Shape
Excel Books
t = 10 Installing an Add-In in Excel 2007
For i = 1 To 137
Error Bars in Excel 2007 Charts
Set shp = ActiveSheet.Shapes.AddShape(i, 100, t, 60, 60)
Clustered and Stacked Column and Bar
shp.TextFrame.Characters.Text = i
Charts
t = t + 70
Next Excel Box and Whisker Diagrams (Box
' skip 138 - not supported Plots)

If CInt(Application.Version) >= 12 Then Excel Waterfall Charts (Bridge Charts)


For i = 139 To 183 Conditional Formatting of Excel Charts
Set shp = ActiveSheet.Shapes.AddShape(i, 100, t, 60, 60)
Broken Y Axis in an Excel Chart
shp.TextFrame.Characters.Text = i
Grouping by Date in a Pivot Table
t = t + 70
Next Referencing Pivot Table Ranges in VBA
End If
End Sub

The Left, Top, Width, and Height parameters of AddShape() are specified in points. The origin is the top left
corner of the worksheet, with the Left and Top values increasing to the right and down, respectively. Dealing
with points on a worksheet isnt intuitive, so if you prefer you can add a shape to a given range address by

2 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

using code like this:

Function AddShapeToRange(ShapeType As MsoAutoShapeType, sAddress As String) As Shape


With ActiveSheet.Range(sAddress)
Set AddShapeToRange = ActiveSheet.Shapes.AddShape(ShapeType, _
.Left, .Top, .Width, .Height)
End With
End Function

Adding Text to an AutoShape


The Shape object has both a TextFrame and TextFrame2 members. The TextFrame2 member was added in
Excel 2007 and gives better control over the formatting of the text. Because it is not backward compatible, I
would recommend using the TextFrame object, as shown in the following code.

Sub AddFormattedTextToShape(oShape As Shape, sText As String)


If Len(sText) > 0 Then
With oShape.TextFrame
.Characters.Text = sText
.Characters.Font.Name = "Garamond"
.Characters.Font.Size = 12
.HorizontalAlignment = xlHAlignCenter
.VerticalAlignment = xlVAlignCenter
End With
End If
End Sub

Setting Border and Fill Styles


If you take advantage of the built-in styles for Excel 2007 and Excel 2010, setting the AutoShape formatting is
ridiculously easy compared to Excel 2003 and previous versions. Excel 2007 introduced the ShapeStyle
property with the 42 preset styles shown below.

The style numbers can be set using a simple line of code:

Shape.ShapeStyle = msoShapeStylePresetXX

Where Shape is the shape object and XX is the style number. The style numbers are shown in the image
gallery in order from left to right, top to bottom. For example, the red button in the second row
is msoShapeStylePreset10.

Adding Connectors and Lines


Connectors and lines are different objects in Excel. Connectors are special lines that connect to shapes,
and if the shape is moved the connector stays connected and reroutes accordingly. Connectors cannot
connect to other connectors, but they can connect to the end point of a line.

3 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

The syntax for adding a line is straightforward:

Worksheet.Shapes.AddLine(BeginX, BeginY, EndX, EndY)

with all coordinates as Singles. Adding a connector is a bit more complex, since you typically want it to
connect two shapes. The code below calculates the begin and end points, creates the connector, attaches the
connector to the two shapes, then finally does a reroute to ensure the shortest path.

Function AddConnectorBetweenShapes(ConnectorType As MsoConnectorType, _


oBeginShape As Shape, oEndShape As Shape) As Shape

Const TOP_SIDE As Integer = 1


Const BOTTOM_SIDE As Integer = 3
Dim oConnector As Shape
Dim x1 As Single
Dim x2 As Single
Dim y1 As Single
Dim y2 As Single

With oBeginShape
x1 = .Left + .Width / 2
y1 = .Top + .Height
End With
With oEndShape
x2 = .Left + .Width / 2
y2 = .Top
End With
If CInt(Application.Version) < 12 Then
x2 = x2 - x1
y2 = y2 - y1
End If

Set oConnector = ActiveSheet.Shapes.AddConnector(ConnectorType, x1, y1, x2, y2)


oConnector.ConnectorFormat.BeginConnect oBeginShape, BOTTOM_SIDE
oConnector.ConnectorFormat.EndConnect oEndShape, TOP_SIDE
oConnector.RerouteConnections

Set AddConnectorBetweenShapes = oConnector

Set oConnector = Nothing


End Function

Several points worth mentioning are:

The ConnectorType can be one of three constants msoConnectorCurve, msoConnectorElbow,


or msoConnectorStraight.
The calculations for the beginning and ending points are not normally needed. You could put any
values in for the AddConnector() function because once you call BeginConnect and
EndConnect, the connector is attached to the shapes and the begin and end points get set
automatically.
How the end coordinates are specified is not consistent between Excel versions. Prior to Excel 2007,
the end coordinates were relative to the begin coordinates. Starting in Excel 2007, the function now
uses absolute coordinates.
When you route a Connector to an AutoShape, you need to specify the side using a connection site
constant. The constants are different for each AutoShape type, but generally they start with the top
side = 1 and go counter-clockwise. For example, most rectangular shapes have connection site
constants where top = 1, left = 2, bottom = 3, and right = 4.
When you call the RerouteConnections() function, it sets the connection sides automatically in
order to create the shortest path between the two shapes. So, unless you want a specific routing,
you can get usually just guess at the connection site values then call RerouteConnections().

4 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Formatting Connectors and Lines


Like AutoShapes, formatting Connectors and Lines is fairly straightforward in Excel 2007 and 2010. Here is a
comparison of two formatting routines for older versions of Excel versus the newer versions:

Sub FormatConnector2003(oConnector As Shape)


With oConnector
If .Connector Or .Type = msoLine Then
' rough approximation of the Excel 2007 preset line style #17
.Line.EndArrowheadStyle = msoArrowheadTriangle
.Line.Weight = 2
.Line.ForeColor.RGB = RGB(192, 80, 77)
.Shadow.Type = msoShadow6
.Shadow.IncrementOffsetX -4.5
.Shadow.IncrementOffsetY -4.5
.Shadow.ForeColor.RGB = RGB(192, 192, 192)
.Shadow.Transparency = 0.5
.Visible = msoTrue
End If
End With
End Sub

Sub FormatConnector2007(oConnector As Shape)


With oConnector
If .Connector Or .Type = msoLine Then
.Line.EndArrowheadStyle = msoArrowheadTriangle
.ShapeStyle = msoLineStylePreset17
End If
End With
End Sub

The Connector property, used above, returns a Boolean indicating whether the shape is a connector. The
Type=msoLine statement checks if the shape is a line. In this case the code will format both connectors and
lines the same way, but at times you may want handle them separately. (NB: The Insert Shapes gallery of
Excel 2007 only lets you add Connectors, not Lines. So unless you are dealing with legacy files or add Lines
via code, testing Type=msoLine may never be an issue for you.)

Like the shape styles, you can format the line style by setting the ShapeStyle to one of the
msoLineStylePresetXX values, where XX matches the order they appear in the style gallery (below) from
left to right, top to bottom.

The Line object has several other members worth mentioning. In addition to the EndArrowheadStyle shown
above, there is a corresponding BeginArrowheadStyle property, a DashStyle property, and also a Style
property that lets you create double lines.

Miscellaneous Issues
Here are a few Excel 2007 issues with AutoShapes that are good to be aware of :

If you copy a set of shapes, older versions of Office gave the option to Paste Special as editable
AutoShapes in other Office applications. This option no longer exists in Office 2007. I havent tested
this in Office 2010 beta yet.
In Excel 2007 and the 2010 beta, changing the AutoShape type will disconnect any incoming or
outgoing Connectors to a shape.
Some print drivers (including PDF export handlers) do not handle printing thick Connectors well, e.g.,

5 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

elbow connectors may straighten. If this happens, either change the line thickness or try grouping all
the shapes together prior to printing.
The Arc is an AutoShape but needs to be treated as a line when setting the ShapeStyle property.
Most of the styles are backward compatible except for styles 37-42 (the glossy button look in the
bottom row of the style gallery). Styles 31-36 (the second row from bottom) do not render very well in
Excel 2000.
You can add Callouts using the AddShape() or AddCallout() methods, but the AddCallout()
method will only let you add four types, two of which are actually the same. Callouts have
AutoShapeType values in the range of 105-124. Even though they have AutoShapeType values, the
Shape.Type property will return msoCallout not msoAutoShape. Confused? Wait, theres
more. The callouts with AutoShapeTypes from 105-108 actually return a Shape.Type =
msoAutoShape not msoCallout.

Sample File
The sample file includes three demo sheets. The ShapeDemo sheet contains a macro to add two shapes,
format them, then add a connector and format it. The Animation sheet has a simple macro showing how to
move a shape around the sheet. The CreateAutoShapes sheet has a macro to create all AutoShapes
available in your version of Excel.

The ShapeDemo routine has two function calls that are commented out IlluminateShapeText2003()
and IlluminateShapeText2007(). These subs add some gaudy formatting to the first letter of each text
block, but they serve to highlight some of the differences between Excel 2007 and previous versions. Two
parts of the code worth looking at are the HasText property and the formatting properties of TextFrame2. With
the old TextFrame object, you would have to try accessing the TextFrame.Characters.Count property,
which throws an error if no text exists. As for the formatting, the font colors in Excel 2003 and previous were
limited to the colors in the pallet. In Excel 2007 and 2010, you can add reflections, drop shadows, and glow as
well as set the color to whatever RGB value your heart desires.

Lastly, there is a module MCommon containing a sub that deletes all the AutoShapes on a sheet. In order not
to delete the command buttons on the sheet (which are shapes too), it creates a ShapeRange of the
AutoShapes and deletes that. The online help file shows the syntax for creating a ShapeRange when you
know the names of the shapes at design time, but the syntax is a bit tricky when creating one dynamically.
The DeleteAllAutoShapes() sub in the sample file shows you how to do this.

Click Here to Download the Sample File

About the Author


Nicholas Hebb is the founder of BreezeTree Software and author of
FlowBreeze Flowchart Software, an add-in that automates flowcharting
in Excel.

Share this:

Posted: Tuesday, January 12th, 2010 under Guest Post.


Tags: Excel 2007, Excel 2010, shapes, VBA.
Comments: 67

6 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Comments

Prerna says:
Friday, January 22, 2010 at 7:00 am

Hi Jon,

I was reading the above article and downloaded the sample file and have a question here.

Function AddShapeToRange(ShapeType As MsoAutoShapeType, sAddress As String) As Shape


With ActiveSheet.Range(sAddress)
Set AddShapeToRange = ActiveSheet.Shapes.AddShape(ShapeType, _
.Left, .Top, .Width, .Height)
End With
End Function

-> Here sAddress is usually static like B2:D6. Can this field be dynamic? e.g. I have to create a diagram where
Job A triggers Job B, Job C and Job D and then Job B triggers Job E. If I give B2:D6 as a static field and put the
code in a loop it gives me an error at sAddress point. Is there anyway to do this?

Jon Peltier says:


Friday, January 22, 2010 at 7:57 am

Which line produces an error? What is the error? Is the active sheet a worksheet?

You can send any address to this function.

Prerna says:
Friday, January 22, 2010 at 8:18 am

Trying to use the below code:

Set oShape1 = AddShapeToRange(msoShapeFlowchartProcess, B3:D5)


AddFormattedTextToShape oShape1, Job 1

Set oShape2 = AddShapeToRange(msoShapeFlowchartAlternateProcess, B9:D11)


AddFormattedTextToShape oShape2, Job 2

Set oShape3 = AddShapeToRange(msoShapeFlowchartAlternateProcess, B16:D18)


AddFormattedTextToShape oShape3, Job 3

The problem here is we are hardcoding the number of shapes we want which is 3 here and hence the range like
B3:D5, B9:D11,B16:D18.

What I am trying to do is put this in a For loop and repeat it n number of times. So obviously I cannot hard code
the ranges and want to give something dynamic.

For i = 2 To 5
job_name = Range(A & i).Value
triby_job = Range(D & i).Value
trigjobname_array(i) = Cells(i, F).Value
Set oShape1 = AddShapeToRange(msoShapeFlowchartAlternateProcess, B3:D5)
AddFormattedTextToShape oShape1, Range(A & i).Value
Next
End Sub
Private Function AddShapeToRange(ShapeType As MsoAutoShapeType, _
sAddress As String) As Shape
With Flow.Range(sAddress)
Set AddShapeToRange = Flow.Shapes.AddShape(ShapeType, .Left, .Top, .Width, .Height)
End With
End Function

I am getting error at line With Flow.Range(sAddress).


Run time error 91 object variable or with block not set.

Can you please suggest something so that the set shape statement can be executed in a loop?

7 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Jon Peltier says:


Friday, January 22, 2010 at 8:46 am

Whats Flow? Is it the sheet where you want the shapes drawn? How does the program understand this?

In the modified calling sub (below), I construct a range address that includes the worksheet name, and in the
function I determine the range, and use the parent of this range (the worksheet that the range is on) as the locaton
of the added shape.

Sub Something()
Dim i As Long
Dim job_name As Variant
Dim triby_job As Variant
Dim trigjobname_array(2 To 5) As Variant
Dim job_address As String
Dim oShape1 As Shape
Dim wsData As Worksheet
Dim wsShapes As Worksheet

Set wsData = Worksheets("Data Sheet")
Set wsShapes = Worksheets("Shapes")

For i = 2 To 5
job_address = "'" & wsShapes.Name & "'!B" & 3 + (i - 2) * 3 & ":D" & 5 + (i - 2) * 3
job_name = wsData.Range("A" & i).Value
triby_job = wsData.Range("D" & i).Value
trigjobname_array(i) = wsData.Range("F" & i).Value
Set oShape1 = AddShapeToRange(msoShapeFlowchartAlternateProcess, job_address)
Next
End Sub

Private Function AddShapeToRange(ShapeType As MsoAutoShapeType, _
sAddress As String) As Shape
With Range(sAddress)
Set AddShapeToRange = .Parent.Shapes.AddShape(ShapeType, .Left, .Top, .Width, .Height)
End With
End Function

Prerna says:
Friday, January 22, 2010 at 12:15 pm

Yes, Flow is the worksheet where I am trying to create a flow diagram in the excel using this macro.

Table -> the worksheet which has the input in the below format:

Job name triggered by Job triggered job


in colmn A in Colmn D in colmn F

AB
BAC
D
DBE

above is an example input. Here Job A triggers Job B. Job B triggers C and D. D triggers job E. I am trying to
create a Job flow diagram using shapes and I am stuck at the second job where B is triggering 2 jobs C and D
where it involves to create 2 branches.

Appreciate your help on this Jon!!

Thanks again.

Prerna says:
Friday, January 22, 2010 at 12:28 pm

Hi Jon,

The above tabular column which is the input didnt come properly in the post. I have emailed you the same @
jonxlmvp@peltiertech.com

8 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Jon Peltier says:


Friday, January 22, 2010 at 2:53 pm

Trying to program a flow chart generator goes beyond the scope of this post and its comments. Before spending
too much time, search Google for excel vba flow chart, and youll see a lot of information from people who have
already invented that wheel.

Brett says:
Tuesday, January 26, 2010 at 1:44 pm

Thank you soo much for this article. I have been searching and searching for some tips on working with drawing
objects (because my usual record macro method wasnt working) and this article explained how to do everything
that, so far, I think I need to do to complete my project :)

jumpjack says:
Friday, January 29, 2010 at 5:59 pm

great article, thanks for helping working around MS dumbness

I know about an excel add-on to get back the old-fashioned menu ( http://www.ubit.ch/software/ubitmenu-
languages/ ), I wonder if also getting back drawing recorder would be possibile (maybe its just there but
disabled, like menu?)

Jon Peltier says:


Saturday, January 30, 2010 at 9:55 am

Jumpjack

The old fashioned menu add-in is like many others, which mimic the old menu arrangement as best they can,
assuming the old features are still available. The drawing recorder is just not available in 2007. It has not just
been disabled, it was not (yet) written for the new generation of shapes.

Steve says:
Tuesday, March 15, 2011 at 11:07 am

To: Jon Peltier


Great post. I like how you tackle how to not only create the shapes but also how to use them. I knew how to do it
in 2003 but they changed a lot since then.
Thanks for posting this.

To: Prerna
I have created a flow charting tool for excel.
I can try to help you but you with it.

I did an automatic flow charting sheet as a result of 3 months work for line item list of instructions. The user had to
define where in the flow the instructions would go.
Mine had not only the ability to create a flow but it also auto arranged it and it would add connecting lines.

This was very complex and all done in 2003 version of Excel.

Prior to doing all this I knew nothing about VBA.

hmm perhaps I can submit my auto flow thing to Jon and maybe get it put up on the site. Of course Jon or
someone would have to update the code and look for mistakes as I am still considered a novice with VBA. :)

sprimax says:
Wednesday, April 20, 2011 at 7:42 pm

Hi Jon Peltier,

Would you help me on Excel 2007 VBA code, how to change a foreground of a shape lets say from grey into blue
when a mouse or pointer is over it automatically ?

Thx so much

prima indonesia

9 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Jon Peltier says:


Friday, April 22, 2011 at 2:27 pm

Sprimax

Shapes are not able to respond to mouse over events, and charts can only respond if they are active.

prerna says:
Monday, May 14, 2012 at 3:46 am

Hi Jon,

I have create a macro in VBA 2003, which draws a diagram in a excel sheet. Is it possible to export this diagram
to visio 2003?

Thanks in advance!
Prerna

Jon Peltier says:


Tuesday, May 15, 2012 at 9:04 pm

Prerna

Presumably a drawing created in one Microsoft Office application can be copied and pasted into another Microsoft
Office application.

prerna says:
Tuesday, May 15, 2012 at 10:59 pm

Jon,

Unfortunately that is not working here. When I do ctrl A and try to copy paste stuff into Visio it does paste the
whole diagram.

Is there any Macro which can be used?

Prerna

Ibrahim says:
Sunday, May 20, 2012 at 6:01 pm

Jon

I work as a design engineer and use Excel spreadsheet extensively for design and calculations. We have a
spreadsheet for each calculation/equipment sizing. What I would like to do is, to generate a CAD style drag and
drop object plate. A user can select a graphical representation of a calculation from object plate and drop it to an
Excel sheet and link input data to Excel cells and export calculated data to Excel cells.
In addition, a user can connect/link several objects, so complex calculation scenarios can be performed.
For example, a pump can be linked to a pipe and a pipe to a valve.

This is similar to Drawing Shape in Excel. However, I am do not know how to get connectivity of the objects. In
another word, I would like to create a VISIO style of drawing object in Excel.
Using VISIO is not very elegant option based on my experience with a commercial software with integrate VISIO
object in Excel.

I appreciate your help in advance,

Ibrahim

Jon Peltier says:


Monday, May 21, 2012 at 7:48 pm

Prerna

It does or it does not paste the whole diagram?

Jon Peltier says:


Monday, May 21, 2012 at 7:52 pm

10 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Ibrahim

Excel does not accommodate Visio type drawings. It might be possible to handle the connectivity
programmatically, but there are a lot of details you would have to keep track of. My experience with Visio (not
recent) is that Visio is in fact much more elegant than the rest of Office.

Malcolm says:
Sunday, June 17, 2012 at 10:44 pm

Hi Jon
Been trying to create some dial guages and found your shape animation example. Ive chopped it around a bit and
can get a needle (a connector attached to an oval) in my guage to move by using some of the example code to
move the oval but havent been able to figure which variables control the amount of sweep around a dial and how
is screen divided up into positions is like the old machines where the pixels where numbered?

Sub as per the example


left_pt = 0.1 * Application.WorksheetFunction.Pi()
mid_pt = 1 * Application.WorksheetFunction.Pi()
right_pt = 0.65 * Application.WorksheetFunction.Pi()
delta = Application.WorksheetFunction.Pi() / 64

With Worksheets(Step By Step).Shapes(Oval 26)

For angle = mid_pt To left_pt Step -1 * delta


.Left = pivot_x + CSng(r * Cos(angle))
.Top = pivot_y + CSng(r * Sin(angle))
Application.Wait Second(Now()) + 1
Next

Jon Peltier says:


Monday, June 18, 2012 at 7:58 am

Malcolm

A dial gauge is such a poor way to represent a value, showing a single value without any historical context in too
large an amount of space. As you have also found, gauges can be very difficult to implement. They might look
fancy, but they are not the part of a cars dashboard that a business dashboard needs to emulate.

More problems with dials are described in Speedometer Charts and Not Gauges Again!, and some general
guidelines and resources for dashboards are presented in Dashboards.

TJ Rucker says:
Saturday, July 28, 2012 at 1:05 am

Hello,

Super helpful article, thanks. I have been trying to build a Graphical Vessel Calendar with the examples you have
provided and have some issues with the shp.TextFrame.Characters.Text command. I have very little exeperience
but I am tryign to get this Text box to actually represent soemthign that exists in a Cell on the worksheet. I ran into
an article that says you need to use an index but unable to firgure that one out as well.

Been experimenting with this but does not work = shp.TextFrame.Characters.Text = (A,14)

Anyhelp is greatly appreciated.

Thanks
TJ

Jon Peltier says:


Saturday, July 28, 2012 at 7:30 am

Are you looking for this?


shp.TextFrame.Characters.Text = SomeWorksheet.Range(A, 14).Value

Mike Dardis says:


Tuesday, July 31, 2012 at 11:21 am

Hi there,

11 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Awesome article and demo file, it worked great for my coding project. Ive noticed one (new?) glitch however.

Ive got two excel pages, Data Table and Hierarchy. I can create and delete shapes on the Hierarchy page, and
I can create shapes for the Hierarchy page using macros triggered on the Data Table page. However, when I try
and run DeleteAllAutoShapes on THESE created shapes, the line at the end, sr.Delete fails with message
Run-time error -2147467259 (80004005): Method Delete of object ShapeRange failed. These shapes
become un-deleteable, save by hand (which is annoying for 30 shapes per refresh).

I changed all of the sheet references in your original code to HierSheet.Shapes etc (HierSheet being a worksheet
variable), to eliminate bugs Ive encountered; I doubt mixed sheet references are the cause (also because many
lines of code prior to sr.Delete, such as sr.Select, function fine).

For a few reasons, I would like to make this work. However, my project does not HINGE on it working.

Note: The email I provided expires August 25th 2012.

Mike Dardis says:


Tuesday, July 31, 2012 at 11:28 am

Comment Edit:
The culprit shapes might be the arrow connectors created between box shapes, I forgot to mention.

TJ Rucker says:
Wednesday, August 1, 2012 at 10:31 pm

Hey Jon,

Thanks for the earlier assistance, worked perfect. We are also trying to forma the text on the object to write to the
next line. for example, I have values in two cells on a worksheet that I want to put on both the 1st and 2nd line.

Set shp = ActiveSheet.Shapes.AddShape(51, 120, 220, 240, i)


shp.TextFrame.Characters.Text = DataSheet.Cells(r, 2).Value Want this to go to the first line
shp.TextFrame.Characters.Text = DataSheet.Cells(r, 3).Value Want this to go to the second line.

Appreciate the help.


TJ

Jon Peltier says:


Thursday, August 2, 2012 at 5:47 am

shp.TextFrame.Characters.Text = DataSheet.Cells(r, 2).Value _


& vbNewLine & DataSheet.Cells(r, 3).Value

12 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

eric says:
Wednesday, December 12, 2012 at 10:04 pm

Hi Nicholas,

I have very extensive experience in writing vba code, but one glitch in excel 2007-10 puzzles me and I would
appreciate your insights

in xls 2003, when you add a line (manually or using VBA), its a line, not a connector
but in xlsm 2007 -2010, addLine creates a connector with connecting ends, no connector site/node, and it does
not seem possible to force the creation of a true line.

I need the feature because I have numerous applications where i need to attach connector to lines, and you know
that you cant connect 2 connectors to one another.. Using polylines is very cumbersome, because the envelope is
a big rectangle as opposed to the nice slim appearance of a simple line.

The closest solution I found to my need is to draw my line in Excel 2003, where it comes up nice and clean with its
2 extremities being connecting sites/nodes and no connector property, then copy and paste it into Excel
2007-2010 where it retains all its properties and can be used as I wish. I then use VBA to duplicate this element in
Excel 2007-20010, and every daughter copy generated like this behaves as I want.

But it should be possible to generate the line straight from Excel 2007 wouldnt you think ?

Any answer, including Eric you cant do this anymore would be appreciated

Regards

eric

Jon Peltier says:


Thursday, December 13, 2012 at 12:25 pm

Eric
Without knowing how youve tried to code this, its not easy to make any suggestions.
The Shapes object (collection) has both AddLine and AddConnector methods. Lines.Add has been deprecated,
and while VBA will still recognize and run it, you never know what different behavior youll see in deprecated code.

Yoh says:
Sunday, December 30, 2012 at 10:40 am

Hi Jon,

Is it possible to change a font color of a text thats inside the shape? im using excel 2007
i tried the following code, but it doesnt work

Selection.ShapeRange.TextFrame.TextRange.Characters(2, 3).Font.Color = 11851260

Regards
Yoh
it came with an error saying Object doesnt support this property or method

Jon Peltier says:


Sunday, December 30, 2012 at 12:01 pm

Excel 2007 wont record any formatting steps in charts or shapes, but in 2010 I recorded enough code to get this
syntax:

Selection.ShapeRange(1).TextFrame2.TextRange.Characters(2,
3).Font.Fill.ForeColor.RGB = 11851260

But that seems like a long hierarchy of objects. I fiddled a bit and found this to work:

Selection.ShapeRange(1).TextFrame.Characters(2, 3).Font.Color = 11851260

Apparently TextFrame2 has a TextRange, but TextFrame does not.

Yoh says:
Monday, December 31, 2012 at 2:25 am

It work perfectly!
Apparantly i was using textframe2 instead of textframe

13 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Thanks a lot Jon.

Fredrik Nelson says:


Friday, February 22, 2013 at 10:43 am

Hi, I have a problem that maybe with your knowledge you can share some light.
ive tried powerpoint,Word and Excel but all gives me simimlar errors
Using a organisation like smartart i can for example change the TextFrame2, the Rotation etc
ActiveDocument.Shapes(1).SmartArt.Nodes(1).Shapes.Item(1).Rotation=35
this will turn one of the squares. but i f i try ActiveDocument.Shapes(1).SmartArt.Nodes(1).Shapes.Item(1).Height
= 33
i always get an error, all documentations seems to indicate that height and width are read/writes but it does not
work. Office 2010. Any clues to whats going on, would be very nice. (sorry for posting such question here but your
blog seems to be update. Thanks in adavance.

Jon Peltier says:


Friday, February 22, 2013 at 12:54 pm

Fredrik
Ive never tried programming any SmartArt objects, and I only rarely program shapes. Your syntax seems okay,
but the Office object model is full of holes.

Bill Benson says:


Friday, May 24, 2013 at 8:58 pm

Hi Jon, good to see your articles are still making the Excel working world go around. I have a question related to
chart/shape formatting which someone recently asked in another forum and indeed it is a little puzzling. The font
choices for shapes are slicker than those for normal cells. So this party was asking if there were a way to get the
same font dialog choices that Ctrl-Shift-P offered for cells, as one might see when doing so for shapes. I hunted
around in the object model for dialog constants which contain the word font, I found the below, none of which
seem to be the one that fires up when trying to alter the fonts of a shape:

xlDialogActiveCellFont, xlDialogFont, xlDialogFontProperties, xlDialogFormatFont, xlDialogReplaceFont,


xlDialogStandardFont, xlDialogWebOptionsFonts

Any ideas where to look for the object (ie, is it callable from VBA for use in other situations than for shapes)?

Jon Peltier says:


Friday, May 24, 2013 at 10:33 pm

The formatting commands and options for shapes are similar to but not the same as those for worksheet cells and
for charts.

Sbastien Daviet says:


Saturday, May 25, 2013 at 9:12 pm

Hi Jon
I was wondering how I can disable Right Click on shapes. First of all, is it possible with Excel 2010 ?
Regards
Sbastien

Jon Peltier says:


Sunday, May 26, 2013 at 11:50 am

According to Customizing Context Menus in All Versions of Microsoft Excel (MSDN), it is not possible.

GSM says:
Thursday, June 27, 2013 at 7:58 am

Hi Jon,
Using VBA to change the properties of a toggle button with the name of Abcde in Excel 2007 I got e.g. this
example to work for changing the width:

14 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

ActiveSheet.Shapes(Abcde).Width = 100
I cannot get the coding right though to change the Value property of the button from True to False or vice
versa with eg.
ActiveSheet.Shapes(Abcde).Value = False (to indicate that the button is on or off)
What is the correct code? I would appreciate your help tremendously.
Regards

Jon Peltier says:


Thursday, June 27, 2013 at 8:50 am

The shape doesnt have any value. But the shape is the container for the toggle button, which is an OLE object.
The syntax is a bit obscure, but heres how you change its value to True:

activesheet.shapes(abcde).oleformat.object.object.value = true

GSM says:
Thursday, June 27, 2013 at 9:18 am

Thanks a lot, Jon for making my day. It has removed a major stumbling block in my design.

DV says:
Monday, September 30, 2013 at 2:09 pm

I opened the fileenabled Macros and Nothing on clicking the command buttons excel 2010 ..Why is that??
Any idea friends??

K.S.Narasimhan says:
Friday, November 1, 2013 at 7:49 am

It is a Great Blog. I want to develop some shapes which are used in Bar Bending normally of Lines and angles.I
am not able to record the macro in Excel2007. If it is not inconvenient Could you please guide me with the code
for a straight line for 2007

Jon Peltier says:


Friday, November 1, 2013 at 10:05 am

KSN

In brief, the answer is in the section Adding an AutoShape:


Worksheet.Shapes.AddShape(AutoShapeType, Left, Top, Width, Height)
Use the Object Browser to find the AutoShapeType, which for a line is msoConnectorStraight (I dont know why it
isnt msoLineStraight, because there is a whole set of Connector shapes, but this is how Microsoft works).
Excel 2007 has a macro recorder, but it doesnt work with charts and shapes. The macro recorder in earlier and
later versions of Excel do work with charts and shapes. You should investigate upgrading (or if all else fails,
downgrading) Excel.
In the future, you should follow the advice in this article: Getting Answers For Your Excel Questions.

Marko says:
Saturday, November 30, 2013 at 12:54 pm

What about shapes for dimensioning of technical drawings (like http://goo.gl/MziSsQ or http://goo.gl/BEkTuO). We
can draw it with lines, but if I want to enable user to move it later on, they should be grouped.

How to make group of shapes?

Or any other ideas for this? Problem could be if user must resize it in one direction (strech) :=(

15 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Jon Peltier says:


Wednesday, December 4, 2013 at 8:32 am

Marko

ActiveSheet.Shapes.Range(Array("Rectangle 1", "Oval 2")).Group

traveller says:
Sunday, December 29, 2013 at 5:46 pm

If a textFrame has been autosized, is it possible to determine the cell row beneath a textFrame2 shape?
This will allow me to scroll the depth of a textFrame.

Jon Peltier says:


Monday, December 30, 2013 at 11:45 am

Look into the .TopLeftCell (and .BottomRightCell) property of the particular shape to see where it is located with
respect to the grid.

Iboro says:
Sunday, January 26, 2014 at 4:45 am

Mr. Peltier sir, I must thank God for you. No, really, your tutorial on how to work with shapes in excel is amazing.
Thanks a lot and remain blessed.

Neil de Villiers says:


Monday, February 17, 2014 at 7:47 am

Hi Jon.

Please assist if possible. Im writing a Cutting List program in Excel 2010. It takes sizes from exce cellsl then
creates the shapes based on that. The problem is that creating the shapes in VBA code, creates the shapes all on
top of 1 another, (I generate between 4 to 200 shapes per code run).

So here comes the issue: Selecting all shapes and then trying to distribute it (Hor) or (Ver) keeps the shapes
connected in some way because my shapes, although distributing, still overlaps 1 another.

Is there a way in vba to distribute shapes to sit side by side, ie connect the left side of 1 shape to the right side of
the next shape?

Your assistance would be highly appreciated, as I have been spending hours Googling this with no success.

Neil de Villiers says:


Monday, February 17, 2014 at 8:12 am

Sub LeftAlignAllObjects()
Dim i As Integer
Solved thx to http://www.tushar-mehta.com/excel/vba/vba-embedded%20or%20linked%20objects.htm Example 3.

Cade that allows this is posted here.

With ActiveSheet.Shapes
For i = 2 To .Count
.Item(i).Left = .Item(1).Left
.Item(i).Top = .Item(i 1).Top + .Item(i 1).Height
Next i
End With
End Sub

Thanking you for your blog. It seems that the error is a universal problem and only way to solve it is manually
moving the Shapes or using the above code.

M. Klein says:
Monday, August 24, 2015 at 7:02 am

Hi Jon,

16 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

how can I draw multiple shapes in a row, without them overlaping and without defining a fixed point for all of them?
I want to draw the first shape with a fixed reference and draw the next shapes in a sequence one after the other
one. Is this possible?
Thanks!

Jon Peltier says:


Monday, August 24, 2015 at 8:21 am

If youve drawn one shape, you know its coordinates, so you can pick coordinates for the next shape that are
offset far enough not to overlap.

Mon says:
Monday, September 21, 2015 at 5:34 am

Hello Jon,

I am writing a macro in which for every row in TableX an Autoshape is inserted in another worksheet, additionally I
would like to link the information in column M (each row a new shape) to the last inserted autoshape.
Is it possible to do this, by using this:
shp.TextFrame.Characters.Text = SomeWorksheet.Range(A, 14).Value

If so, how can I make the row reference variable? I was thinking about a sort of loop in which a counter sets the
value of the row. But I cant figure out how to make it work. Or are there any other easier alternatives?

Thank you.

Ron MVP says:


Sunday, June 19, 2016 at 4:25 pm

I am trying to use .AddShape in this macro. It works in Excel 2016, but I keep getting a syntax error in 2010

Sub Fill2Colors()
' based on code by Hctor Miguel
' Works in 2016, does not work in 2010 ...
Dim sL As Single
Dim sT As Single
Dim sW As Single
Dim sH As Single
Dim sN As String
Const vbGrey = &H808080
With Range("C30:Y30")
sL = .Left
sT = .Top
sW = .Width
sH = .Height
sN = .Address(False, False)
With ActiveSheet.Shapes
On Error Resume Next
.Range(Array(sN & "1", sN & "2", "grp" & sN)).Delete
On Error GoTo 0
With .AddShape(msoShapeRectangle, sL, sT, sW, sH / 2)
.Name = sN & "1"
.Line.Visible = msoFalse
.Fill.Visible = msoTrue
.Fill.Transparency = 0.75
.Fill.ForeColor.RGB = vbBlue
End With
With .AddShape(msoShapeRectangle, sL, sT + sH / 2, sW, sH / 2)
.Name = sN & "2"
.Line.Visible = msoFalse
.Fill.Visible = msoTrue
.Fill.Transparency = 0.75
.Fill.ForeColor.RGB = vbGrey
End With
With .Range(Array(sN & "1", sN & "2")).Group
.Name = "Grp" & sN
.Placement = xlMoveAndSize

17 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

End With
End With
End With
End Sub

On this line

With .AddShape(msoShapeRectangle, sL, sT, sW, sH / 2)

I get a run-time error 1004: Application-defined or object-defined error.

But I dont see anything wrong with it.

This is on Win 10 and I have both Office 2016 Pro Plus (legal license) and 2010 Home and Student. I wonder if
this dual install is somehow causing this issue.

pete says:
Monday, June 27, 2016 at 10:19 am

I have a question that seems un-answered:

I have a shape.
say a rectangle AutoShape: Rounded rectangle 1
Its text it set say a formula =sheet1!$a$
A1 has a value of hello,
So does the Rectangle

Now I was the change the formula to B1 which says goodbye

shapes(Rounded rectangle).Formula does not work. But if I select the shape, then selection.Formula = B1
does.
so why question is in the expression
shapes(name).???.formula

what is ???

Jon Peltier says:


Monday, June 27, 2016 at 11:19 am

Hi Pete

This is an inconsistency in Excels object model. I dont think you can access the .Formula property of a shape
object. If you record a macro, its

ActiveSheet.Shapes.Range(Array("Rounded Rectangle 1")).Formula = "=Sheet1!$B$1"

but if you play it back, you get an error. The only way to access the formula is by selecting the shape first, and
getting the .Formula property of the Selection object.

Jon Peltier says:


Monday, June 27, 2016 at 12:07 pm

Ron

I ran this abbreviated bit of your code, and had no such error. Windows 10, Office 2016 (with 2013, 2010, 2007,
and 2003 also installed on this machine).

Sub MyMacro()
Dim sL As Double, sT As Double, sW As Double, sH As Double, sN As String
sL = 150: sT = 100: sW = 250: sH = 150
sN = "MyName"
With ActiveSheet.Shapes
With .AddShape(msoShapeRectangle, sL, sT, sW, sH / 2)
.Name = sN & "1"
End With
End With
End Sub

Jon Peltier says:

18 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Monday, June 27, 2016 at 12:17 pm

Pete

Here is a summary of VBA code that can access the formula of the text in a shape:

' macro recorded, doesn't work


ActiveSheet.Shapes.Range(Array("Rounded Rectangle 1")).Formula = "=Sheet1!$B$1"

' seems like it should work, doesn't


ActiveSheet.Shapes("Rounded Rectangle 1").Formula = "=Sheet1!$B$1"

' deprecated, but works like a charm


ActiveSheet.DrawingObjects("Rounded Rectangle 1").Formula = "=Sheet1!$B$1"

' obscure, but works


ActiveSheet.Shapes("Rounded Rectangle 1").OLEFormat.Object.Formula = "=Sheet1!$B$1"

' also obscure, also works


ActiveSheet.Shapes("Rounded Rectangle 1").DrawingObject.Formula = "=Sheet1!$B$1"

' awkward, works but requires selection of the shape


ActiveSheet.Shapes.Range(Array("Rounded Rectangle 1")).Select
Selection.Formula = "=Sheet1!$B$1"

Sonny Day says:


Thursday, February 16, 2017 at 5:11 pm

I have created a line on a spreadsheet in Excel 2010, with the vba command AddLine(Beginx, Beginy..). Now I
want to change the position of this line, without deleting it and drawing another line with all of the same properties.
Is this possible? Can I access [beginx, beginy] and change them?

Jon Peltier says:


Friday, February 17, 2017 at 9:15 am

Sonny

You cant use VBA to get BeginX, BeginY, EndX, and Endy from the line, all you can get is the Left, Top, Width,
and Height properties of the rectangle whose diagonal corners are defined by the line. You also cant use VBA to
tell whether the line follows the upward or downward sloping diagonal of the bounding rectangle, nor can you tell
which end of the line is the beginning and which is the end. To move and resize the line, you can use
IncrementLeft, IncrementTop, ScaleWidth, and ScaleHeight (which I dont like doing), or you can provide new Left,
Top, Width, and Height properties.

The easiest way to get another line with the same properties is to make a copy of the first, but again, VBA cant
tell you its orientation, if youre trying to point the line at something. So if you want to ensure that your line has the
intended orientation, you should figure out the BeginX, BeginY, EndX, and Endy that you need, then pick up and
apply formats just like using the Format Painter:

ActiveSheet.Shapes(1).PickUp
ActiveSheet.Shapes(2).Apply

Sonny Day says:


Friday, February 17, 2017 at 1:12 pm

Perfect, thank you. The new Left, Top, Width, and Height properties were exactly what I was looking for. Works
fine.

Trackbacks

19 of 20 3/20/17, 11:47 PM
Programming Excel 2007 and Excel 2010 AutoShapes with VBA ... http://peltiertech.com/programming-excel-2007-2010-autoshapes-...

Data Visualization: How (2 of 2) | cazh1 says:


Sunday, August 1, 2010 at 8:43 pm

[] Excel comes with an ever growing list of graph types. Cant find the one you want? Try to hack at the
standard stuff using []

Create reusable custom shapes in Microsoft Excel or even Office in general says:
Sunday, May 6, 2012 at 5:01 pm

[] is not possible in Excel 2007/2010. This article describes what you can and cannot do with shapes in
VBA and nowhere is there VBA that will allow us []

Presenting msgbox text within a shape. says:


Thursday, July 25, 2013 at 4:53 pm

[] Take a look at this site. Specifically Adding an Autoshape. It shows how to have text inside the shape.
Programming Excel 2007 and Excel 2010 AutoShapes with VBA (Guest Post) Peltier Tech Blog []

macro recorder not working for creating shapes says:


Wednesday, August 7, 2013 at 11:24 am

[] From Programming Excel 2007 and Excel 2010 AutoShapes with VBA (Guest Post) Peltier Tech
Blog []

Creating Shapes (Rectangles and Shapes) from input cells says:


Friday, August 30, 2013 at 9:13 am

[] Check out this page. They have a lot of great code for the autoshapes and you should be able to
modify the code that they have to get what you need. Programming Excel 2007 and Excel 2010
AutoShapes with VBA (Guest Post) Peltier Tech Blog []

Speak Your Mind

Name *

Email *

Website
Post Comment

Notify me of follow-up comments by email.


Notify me of new posts by email.

20 of 20 3/20/17, 11:47 PM

You might also like