Design-Drawing Home  
Drawing Program
ISSN 1441-5585

Search...

Home
Articles
Software Catalog
Book Store
About
Advertising
Newsletter

Pearls from the auld Scotsman
Few people know Visio software and communicate their knowledge as well as Dave Edson. In this regular column Dave dispenses pearls of wisdom in his own inimitable style.

Association: Glue Wi'oot Gluin' in Visio

Part II

David A Edson

VBA can be used to positionally relate two Visio shapes to each other without having to be glued together. Dave got us started in Part I. Now lets go the full distance in the final part of this article.

Now that we have a mechanism for actually showing the Dialogue on screen, we want to write a procedure to take care of any initialisation as the form loads and displays. This includes checking to see if the user has actually selected two and only two shapes. If that condition is true then we want to find the two selected shapes and place their names in the two Text Box controls at the top of the dialogue. We also want to enable the user to select the APPLY and OK buttons as well. Remember all of this is predicated on ensuring that only two shapes have been selected. A’richt… tae do this, double-click on the UserForm1 item in the Project window. This will restore the dialogue you just designed onto the screen in the VBA IDE. Now select just the form itself, ensuring that you do not have any of the controls selected. Now Right-Click. From the menu select View Code. This will launch the Code Window for the form and its associated controls. You will notice two drop-down lists at the top of this window. The left list is a listing of the form object and it’s associated control objects, the right list is a listing of the available procedures for these objects. Ensure that the lists show UserForm and Initialize. You will see the procedure framework already set up for you. We will need to write the following code exactly as I have listed it below:

Private Sub UserForm_Initialize()
Dim VisSelSet As Visio.Selection
Dim VisLeader As Visio.Shape
Dim VisFollow As Visio.Shape
BuApply.Enabled = False
BuAlright.Enabled = False
BuCxl.Enabled = True
Set VisSelSet = Visio.ActiveWindow.Selection
If VisSelSet.Count <> 2 Then
MsgBox "You Must Have Exactly 2 Shapes Selected"
Unload UserForm1
Else
Set VisLeader = VisSelSet.Item(1)
LeaderShape.Text = VisLeader.Name
Set VisFollow = VisSelSet.Item(2)
FollowShape.Text = VisFollow.Name
BuApply.Enabled = True
BuAlright.Enabled = True
End If
End Sub

Sae… lets stroll thruu this procedure and do a wee bit o’ analysis. Within the procedure framework we first find 3 Dim statements. You, of course, know that to Dim means to declare the usage and data type of the variables in your code. This is mandatory when working with Objects. So we declare VisSelSet as type Visio.Selection, VisLeader as type Visio.Shape, and VisFollow as type Visio.Shape. These three objects will hold the current selected items and two Visio shapes. The next two lines initialise the APPLY and OK buttons to disabled. We do this to insure that they can not be pressed unless the conditions in the IF statement to follow are met. This is just a bit of user error trapping.

Next we go find the current selection set in the Visio drawing. Note the use of the keyword Set. Set is required whenever you work with objects and explicitly NOT used when dealing with anything OTHER than an object. We therefore find Visio, find the active window, and then find the selected shapes in that window. We bind this to the variable VisSelSet. Now we begin our test. If there are not exactly 2 items in our selection set, one for the leader shape and one for the following shape, we display a message to the user informing them of their mis-deed and jump out of the IF statement and then end. If, however, exactly 2 items are selected, we find the first item in the selection set and assign it’s name to the text box displaying the Leader shape and find the second and assign it’s name to the text box displaying the Follow shape. We then enable the previously disabled controls and end the procedure. This is the full initialisation procedure.

Now with the form initialised and displayed we turn our attention to the four button controls at the right of the dialogue. We will work from top to bottom here beginning with the APPLY button. When the user presses the APPLY button he/she triggers the click event for that control. In this case we will want to modify the follow shape’s PinX and PinY so that they reference the Leader’s PinX and PinY with the additional offset as specified in the OffsetX and OffsetY Text Box controls. Ensure that the lists in the code window show BuApply and Click. You will see the procedure framework already set up for you. We will need to write the following code exactly as I have listed it below:

Private Sub BuApply_Click()
Dim VisFollow As Visio.Shape
Dim VisFollowPinX As Visio.Cell
Dim VisFollowPinY As Visio.Cell
If OffsetX.Value <> "" Then
If OffsetY.Value <> "" Then
Set VisFollow =_ Visio.ActivePage.Shapes.Item(FollowShape.Value)
Set VisFollowPinX = VisFollow.Cells("PinX")
VisFollowPinX.FormulaForce = "GUARD(" & LeaderShape.Value_ & "!PinX + " & OffsetX.Value & ")"
Set VisFollowPinY = VisFollow.Cells("PinY")
VisFollowPinY.FormulaForce = "GUARD(" & LeaderShape.Value_ & "!PinY + " & OffsetY.Value & ")"
Else
MsgBox "You Must Enter A Value For The Y Offset"
End If
Else
MsgBox "You Must Enter A Value For The X Offset"
End If
End Sub

Here we declare VisFollow as type Visio.Shape, VisFollowPinX as type Visio.Cell, and VisFollowPinY as type Visio.Cell. The two nested If statement blocks check to see if a value has been entered into the X and Y offset Text Box controls. If either is blank then we display a message box to let them know the error of their ways. If values are, in fact, there, then we get the name of the Follow shape and pass that as an argument to the Item property of the shapes collection on the Active Page of the Visio document. This will get a proper reference to the Follow shape. Next we bind the PinX and PinY values of that follow shape to a concatinated string. The string consists of the Visio Keyword GUARD, which is a Visio function to protect the contents of the cell in question, along with the name of the Leader shape and the proper reference to it’s PinX or PinY cell. The concatinated string is fed back to the cell reference using a FormulaForce function to overwrite any value that might already be present there. The resultant string looks something like:

GUARD(Sheet.1!PinX + 2.125 in.)

This is the workhorse Subroutine for the code. It does all of the building of the proper string from the constituent components and feeds it back to the proper shape. OOch!!! Sae brilliant, aye?

Remember that the APPLY button leaves the user still active in the dialogue. In a moment we will re-use this routine as part of the OK button’s Click event. Next we turn our attention to the RESET button. When the user clicks the RESET button, we want t o remove any guarded formula and let the user then move the following shape anywhere he/she wants to. To create this procedure, ensure that the lists in the code window show BuReset and Click. You will see the procedure framework already set up for you. We will need to write the following code exactly as I have listed it below:

Private Sub BuReset_Click()
Dim VisFollow As Visio.Shape
Dim VisFollowPinX As Visio.Cell
Dim VisFollowPinY As Visio.Cell
Set VisFollow = Visio.ActivePage.Shapes.Item(FollowShape.Value)
Set VisFollowPinX = VisFollow.Cells("PinX")
VisFollowPinX.FormulaForce = VisFollowPinX.Result("")
Set VisFollowPinY = VisFollow.Cells("PinY")
VisFollowPinY.FormulaForce = VisFollowPinY.Result("")
Unload UserForm1
End Sub

I’ll not belabour the point about Dim nor other matters that I have discussed previously. However, note that in each case, both the PinX cell and the PinY cell of the follow shape, we use the FormulaForce function to push the new value to the cell. The value that we push to the cell is, in fact, the current evaluated position of the shape in Visio’s internal units; inches. Because no guard is placed on the cell, the user is then freed to relocate the shape anywhere he/she desires. Note also, the last line within the procedure where we Unload the User Form. This puts the dialogue away and terminates the procedure.

The CANCEL procedure is very simple. This is designed to just close the dialogue and terminate the procedure. To create this procedure, ensure that the lists in the code window show BuCxl and Click. You will see the procedure framework already set up for you. We will need to write the following code exactly as I have listed it below:

Private Sub BuCxl_Click()
Unload UserForm1
End Sub

This single line procedure does just what it did in the CANCEL procedure above, it puts the dialogue away and terminates the procedure.

I stated a moment ago that the APPLY and the OK procedures were the same with the exception that the OK procedure closed the dialogue. Weel… there is certainly no reason to either create a new process for this nor duplicate existing code, so to expedite this we will simply call the APPLY procedure and then unload the dialogue. To create this calling procedure, ensure that the lists in the code window show BuAlright and Click. You will see the procedure framework already set up for you. We will need to write the following code exactly as I have listed it below:

Private Sub BuAlright_Click()
Call BuApply_Click
Unload UserForm1
End Sub

The Call function, calls the Bu_Apply procedure and when finished returns to the point immediately below the calling point. It then unloads the form and terminates. Couldnae be easier, aye?

To test your hard work you will now want to close out the VBA IDE. Don’t worry, when you close it your changes and all your hard work are being stored with the document. Now select a shape, next shift + select another shape. With these shapes selected select Tools > Macro > Module 1 > Associate. The dialogue will appear with the two shape names entered. Enter offset values for X and Y and click OK. Well… I told you above how all of this works. It’s now up to you to expand on all of this and build world class applications that can take advantage of this associative technology.

I’ll take a wee moment here to toss oot an idea oor twa aboot considerations when building associativity applications. One drawback in the solution you have just built is that you have no visual clue that the two shapes are associated other than to start moving them aboot pall-mall. An alternative to this might be to additionally add an additional geometry section for a single line, add a Controls section, wire one endpoint of the line to the pin of the following shape to it’s Pin and the other end to the Control handle, glue the Control handle to the pin of the other, and make the line visible or invisible based on a page setting. Whew!!! Remember that you would also need to check for the existence of the control handle and the geometry section, reuse or create as necessary, and destroy on a RESET operation. This adds a greater level of complexity to your coding and your solution, however in a "world-class" solution, ensuring the user can intuitively understand it is job one, aye?

Weel… thar ye have it lads an’ lassies!!! I’ve put enough power intae yer hands to make ye quite dangerous (huge Celtic grin). I’ll be back next month with more insight and techniques into extending Visio and making it the best development platform for all of your graphics needs and a the true graphics component to your MS Office work environment.

"Haste ye back"

Dave "The Auld Scotsman" Edson

Download all the VBA in ASSOCIATE.VSD (27Kb)

 

 
Rate this article...
Hmmm  OK  Good  Yes! Brilliant
Your a friend about this article.

Copyright © 1998-2007 DBM & others | Disclaimer | Privacy | Re-publication | Trademarks | Webmaster | Home