If you are busy developing a Visio solution, you might run into the situation where you need to edit a Visio master using code.
Like any application that has survived the ages, Visio has its share of black-magic techniques that lurk in dusky corners of the netherworld. And if you need to edit masters programmatically, be warned! You’re heading down a dark alley…
If you’ve already run into problems with this, don’t feel bad. Even experienced Visio developers get tripped-up by this one! And that’s because the correct way to do this isn’t obvious, and the obvious way to do it isn’t correct!
The Obvious Way Doesn’t Work…Kind-of
When you peruse the Visio object model, you’re likely to think that the obvious way to edit a master shape is something like this:
Dim mstCopy As Visio.Master
Dim shp As Visio.Shape
'// Get a master named "Bob" from our Document stencil:
Set mst = Visio.ActiveDocument.Masters.Item("Bob")
'// Get the shape inside of the master:
Set shp = mst.Shapes.Item(1)
But what happens when you run this code? Your masters change, but those changes don’t seem to percolate down to shapes on the page!
If you are programmatically altering the masters in the Document Stencil of a Visio drawing, then the instances of those masters (ie: the shapes dropped on the page) won’t reflect your changes!
However, if you save your drawing, close it, then re-open, you’ll see that your changes did indeed take effect. Yes something is happening, but not in an ideal way.
Create a Master Editing Session…duh!
Now, we don’t want to edit masters, then programmatically close and open the drawing. That just wouldn’t do! So…
The proper way to get the job done is to start an editing session. The situation is very similar to what you do when you edit a master by hand:
- Open a master window (double-click a master, or right-click and choose Edit Master > Edit Master Shape)
This creates a temporary copy of the master - Make your changes manually: format, resize, edit text, etc.
- Close the master window
- Accept your changes by responding Yes to the prompt: Update master and all of its instances?
Step 4 is the key for manual editing. You consciously must push the changes to the instances.
This is missing from our code above. It never tells Visio to push the changes to the instances in the drawing. For that matter, that simple code never really creates a copy to fiddle with in the first place!
And that’s because the right way is all very, very non-obvious!
So we mimic the manual sitaution by using the Master.Open method to create a copy of our original master, then we push the changes to the drawing by calling Master.Close. The sample code below says it all:
Sub EditMaster( ByRef mst As Vis.Master )
Dim mstCopy As Visio.Master ' an object to hold a copy of mst...
Dim shp As Visio.Shape
Set mstCopy = mst.Open
Set shp = mstCopy.Shapes(1)
'// Do stuff to shp here...
shp.Text = "Example stuff"
Set shp = Nothing
mstCopy.Close()
Set mstCopy = Nothing
Set mst = Nothing
End Sub
The code above works for VB6 and VBA. Dot-netters can just remove all of the Set statements, and probably don’t really need the = Nothing stuff either, since .NET is supposed to handle clean-up all by itself.
So make use of those Master.Copy and Master.Close methods to create a master editing session. Your on-the-fly programmatic changes to Visio masters will then work just fine, and you’ll be a hero at that next status meeting!