There was a recent question in the TechNet forum asking how you could have multiple instances of a shape that have both local (specific to each instance) and global (shared) fields. I thought I’d take a quick look at how you might achieve that.
A project legend shape example
By way of an example let’s say that you want a shape that contains a project name, which is same across all pages of the document, and a project phase name, which is particular to the page in which it sits. The broad steps here are to:
- create a document level cell to hold the project name
- add a Shape Data property to the master shape enabling any instance shape to set the above doc cell
- enable a local value to be easily set via normal text editing (F2) on each instance shape
The details
Just as shapes and pages in Visio have an accompanying ShapeSheet the document also has one of its own. You can get to it by right clicking to the document root node in the Drawing Explorer via the View tab / menu. [Note – you need to make sure you have Developer mode turned on in order to see the ShapeSheet option.]
The Document ShapeSheet is just the place to hold the project name as this will be available across all pages by using the “TheDoc!” reference syntax.
A walkthrough would look something like this:
- Open the document ShapeSheet as described above.
- If you can’t see a User-defined Cells Section you can add one clicking Insert Section from the ShapeSheet ribbon tab.
- If you created the section in step 2, you should now have a new (default) row named Row_1 and if not, you can click Insert Row. In either case you need to rename the new row to User.ProjectName.
- In the Value column of the new row add this string ="My project name” and close the ShapeSheet window. [Note that the equals and double quotes are part of the formula and tells Visio that this is a string value.]
- Now to create the shape, draw two rectangles and group them together:
- Sub-select the top rectangle and hit the F2 key to edit the text. While in edit mode click Insert / Field and add the following custom formula:
- Now that the text for the upper rectangle is being read from the document user cell you can add the formula that will both set and read from the document user cell at the same time.
Select the new group shape and make a note of its shape ID. You can see this in the Shape Data window title. In my case the title reads Sheet.3 so my shape’s ID is 3.
Right click on the new shape and select Show ShapeSheet. - In the ShapeSheet, add new a Shape Data section and row (in a similar way that you added the User section in the document ShapeSheet).
- Rename the new row Prop.ProjectName
- Move along to the value cell of the Prop.ProjectName and add this formula:
=SETATREF(TheDoc!User.ProjectName)
I’ll come back to what this formula does in a minute. - Still in the group shape’s ShapeSheet, scroll down to the Miscellaneous section and set the HideText cell to TRUE, and close the ShapeSheet.
- Next sub-select the bottom rectangle and again hit the F2 key and this time insert the following formula in the Custom formula textbox:
=SHAPETEXT(Sheet.3!TheText)
This reads the text from the parent shape (remember, my shape’s ID is 3). - Finally, now the text fields are set, you need to lock down the sub-shapes so that users aren’t able to edit the text directly and thereby overwrite the inserted fields. To do this navigate to the Group Properties section of the shape’s ShapeSheet and set the SelectMode cell to 0 (which equates to the enumeration visGrpSelModeGroupOnly).
- You can now create a master shape. Close any open ShapeSheets and drag the new shape into the document stencil (Shapes [window] / More shapes / Show Document Stencil). You can then either save the whole document as a new stencil (.vss) or copy it across to another stencil that you work with regularly.
Hopefully the above fairly self explanatory, but I’ll highlight a couple of points.
Diverting values
The key problem here, is trying to get a cell that both reads the global value and at the same time, is able to set that value.
The formula that you added to Prop.ProjectName in the group shape is designed to solve this problem, using the SETATREF function, by diverting the incoming value to the global (document) cell. At the same time it also evaluates to the value of the target cell and so the changes are reflected across all shapes that use the same formula.
Text edit proxy
For the local value you might elect to have another Shape Data row and inserted field for consistency, however I thought I’d try a more direct text edit approach on the basis that you’re more likely to want to set the local value in each instance shape where the global value might only be changed occasionally. Since the local shape is a sub-shape I’m using the group shape’s text as a proxy for editing purposes and passing this on the sub-shape by referencing it as per step 12 above. Even though you set the group shape’s HideText cell to true, it is still available to edit via the usual F2 keyboard shortcut.
An alternative might be to edit the group shape’s text block, but I think this will do for demonstration purposes.
If you want to read more about inserted fields then here are a few links:
- Creating text fields to display information in Visio – Microsoft
- Title Blocks #1: How to Display Existing Document Information – VisGuy.com
- Title Block #2: Let’s Make a Multi-field SmartShape – VisGuy.com
and for more on the SETATREF family of functions: