Calling VBA Code from a SmartShape
Now that you’re familiar with the VBA environment
and basic subroutines, it’s time to connect the notes shape with some
useful code.
Creating a VBA Subroutine That Can Be Run from a Shape
1. | Start with a new page, and copy a finished notes shape to it.
|
2. | If you look at the ShapeSheet for the notes shape, you see that the second Action row looks like this:
Actions.CreateNewNote.Action=CALLTHIS("ThisDocument.CreateNewNote")
The CALLTHIS
ShapeSheet function looks for the sub CreateNewNote in the ThisDocument
VBA module. We know where ThisDocument is, we just need to add
CreateNewNote to it. |
3. | Open the VBA interface and bring up the ThisDocument code module.
|
4. | Create the declaration of a sub that can be accessed from a shape. Subs that work with CALLTHIS need to have a shape variable as an argument. Type this code:
Public Sub CreateNewNote(ByRef shp As Visio.Shape) End Sub |
5. | You can quickly test if the shape is successfully getting to the sub by adding a simple message box line:
Public Sub CreateNewNote(ByRef shp As Visio.Shape) MsgBox "Hi, my name is CreateNewNote!" End Sub
Now you can test the code from the shape. Don’t run this sub from VBA,
as you did previously. Instead, return to Visio, right-click the notes
shape, and choose the second item. The message box appears, showing the
test message you just coded. |
6. | Now you’re ready to code the full CreateNewNote
sub. It’s not a lot, just 15 lines, including five comments. Pay
attention to the comments because they explain the purpose of each code
block.
Public Sub CreateNewNote(ByRef shp As Visio.Shape)
' Get the location and height of the existing shape: Dim shpNew As Visio.Shape Dim px As Double, py As Double, h As Double px = shp.Cells("PinX").ResultIU py = shp.Cells("PinY").ResultIU h = shp.Cells("Height").ResultIU
' Drop a copy of the shape onto the page: Set shpNew = shp.ContainingPage.Drop(shp, px, py - h)
' Increment the number field: Dim n As Integer n = shp.Cells("Prop.Number").ResultInt(Visio.VisUnitCodes.visNoCast, 0)
' Set the new shape's number to be one more than the old: shpNew.Cells("Prop.Number").ResultIU = n+1
' Set the new shape's text: shpNew.Text = "Notes shape, number = " & n+1
End Sub |
7. | Return
to Visio and run the code by right-clicking the notes shape. You should
get a new copy of the shape directly below the shape you clicked. The
Number field should be incremented by one, and the text should be
changed to reflect the new index.
|
An interesting feature of the CreateNewNote
subroutine is the code used to get and set values from the ShapeSheet.
The Cells method takes a string argument that matches the name of a
cell in the ShapeSheet. In this way, shp.Cells gives you access to the
entire ShapeSheet.
Many budding Visio developers scour the SDK documentation looking for the properties Width, Height, Geometry1X1,
to no avail. Cells is the key they miss. When you have a cell object,
you can ask for its value in “internal units” by using ResultIU.
Internal units in Visio are inches. If you use a different measurement
system, you can use Result instead. For example, shp.Cells(“Width”).Result(“cm”). You can also get a cell’s formula—for example, shp.Cells(“Geometry1.X1”).Formula.