I reader of one of my earlier posts, Copy Data from one Shape to Another ( see http://davidjpp.wordpress.com/2009/02/02/copying-data-from-one-shape-to-another/ ) asked how a cow can inherit the field number of from the field that it in. I think that this is just an example of how you can automatically update any Shape Data value from an underlying container, but I will use a cow in a field example anyway. This example uses VBA code, but should be good to use in any version of Visio since Visio 2000.
Coding
How to Run VBA Macros from a Ribbon Button in Visio 2010
A colleague, who is an experienced Visio tutor, asked me how to hook VBA macros to the Fluent UI Ribbon. He figured that it must\should be easy, but he can’t see where it is done. Well, this question has resonance because a plea was made to the Microsoft Visio team at our recent MVP Conference that this often asked for feature should be made easy for the macro developer. Now, I must admit that I have been so busy writing .Net Visio Add-Ins and following the pattern for the Fluent UI in VSTO C# code, that I had not appreciated just how convoluted the calling of VBA from a Ribbon button is. So, I thought I would offer a way of doing this in a simple (I hope!) way.
I will show how this can be done for a Visio drawing or template that contains VBA macros, and how this can be also be used for a Visio stencil that contains the code. I know that some macro developers put their code into drawings, but I would always recommend putting the code into a stencil, if the code is to be used by multiple drawings.
The Visio team’s Insight Blog has some useful background at http://blogs.msdn.com/b/visio/archive/2010/02/24/user-interface-extensibility-in-visio-2010.aspx , but it only has one fleeting mention of VBA macros:
For VBA, you simply provide the contents of a RibbonX XML as a string directly to Visio through the CustomUI property.
So, what does that mean? How do you actually do it?
Well, there is some sample code in the Visio 2016 SDK.
[Read more…] about How to Run VBA Macros from a Ribbon Button in Visio 2010A Patch Panel that can be 1U too
Microsoft Visio 2007 Professional and 2010 Professional and Premium includes the Network / Rack Diagram template, which opens the Rack-mounted equipment stencil. This stencil includes the Patch Panel master which can be stretched from 2U to 25U high. However, I have often required a 1U patch Panel, so I decided to look into the Microsoft shape to see if it could be modified to allow it to be reduced to 1U without looking ridiculous.
Displaying the RGB values of Shapes
Everyone knows that you can change the colour of Visio shapes. Most people know that you can also change the fill pattern too.
Automating Area and Perimeter Length Shape Data
[UPDATE: Microsoft introduced a new function into Visio 2010 called PATHLENGTH(…), so some of the following is now not required. See Automatic Line and Segment Lengths in Visio )
Another newsgroup question has asked about automating the update of shape area and perimeter lengths. Now, this is an area (no pun intended) that I am most interested in because I used to do a lot of space planning. Visio Professional does include Space and Boundary shapes on the Resources stencil that use an add-in to update the area, but does nothing about the perimeter length. These shapes do highlight some of the issues to be considered though…
- Visio pages can be scaled, and indeed the various floor plan and site layout templates in Visio are pre-scaled. Most templates are not scaled, and therefore default to 1:1 scale.
- Visio measures everything internally in inches, although you can display in almost whatever units you choose.
- The Visio Application object has a handy ConvertResult (StringOrNumber, UnitsIn, UnitsOut) method, which can be used for linear and area measurements … and can also be used for date and times.
- Visio can store decimal numbers to a very high degree of precision (I counted 14 decimal places), but you almost always want to format the display.
- Visio can call a method in a VBA project when the values in specified cells are changed.
- It is easy to display Shape Data in a shape, either by using Data Graphics or by Insert Field
[Read more…] about Automating Area and Perimeter Length Shape Data
Listing Connections in Visio 2010
One of the best bits of Visio is the connections between shapes, but it has always been difficult to understand these connections in code. There are connections to and from shapes, which require you to understand where you are and which way to look … at the beginning or the end of a 1D connector. Visio 2010 has added some useful extra methods to the shape object which makes understanding connections much easier. This post will show you how you can use the new GluedShapes() and ConnectedShapes() methods.
Take, for example, a network diagram where there are connections between servers and routers:
You may wish to list the connections at the start and end of each cable. Previously, this would have meant inspecting the connected cell to see if was at the beginning or end of the line, but now you can use the GluedShapes() method of a shape to retrieve an array of the 2D shapes connected at one end or another with the relevant arguments, visGluedShapesIncoming2D or visGluedShapesOutgoing2D. The ListGluedConnections macro below displays the following in the immediate window:
Connector Dynamic connector
> Router.45 router-02
< Server server-01 Connector Dynamic connector.107 > Router.45 router-02
< Server.30 server-02 Connector Dynamic connector.108 > Router router-01
< Server.75 server-03 Connector Dynamic connector.109 > Router.91 router-03
< Server.30 server-02 Connector Dynamic connector.110 > Router.91 router-03
< Server server-01
Public Sub ListGluedConnections() Dim shp As Visio.Shape Dim connectorShape As Visio.Shape Dim sourceShape As Visio.Shape Dim targetShape As Visio.Shape Dim aryTargetIDs() As Long Dim arySourceIDs() As Long Dim targetID As Long Dim sourceID As Long Dim i As Integer For Each shp In Visio.ActivePage.Shapes If shp.OneD Then Debug.Print "Connector", shp.Name arySourceIDs = shp.GluedShapes(visGluedShapesIncoming2D, "") For i = 0 To UBound(arySourceIDs) Set sourceShape = Visio.ActivePage.Shapes.ItemFromID(arySourceIDs(i)) If sourceShape.CellExists("Prop.NetworkName", Visio.visExistsAnywhere) Then Debug.Print , ">", sourceShape.Name, sourceShape.Cells("Prop.NetworkName").ResultStr("") End If Next aryTargetIDs = shp.GluedShapes(visGluedShapesOutgoing2D, "") For i = 0 To UBound(aryTargetIDs) Set targetShape = Visio.ActivePage.Shapes.ItemFromID(aryTargetIDs(i)) If targetShape.CellExists("Prop.NetworkName", Visio.visExistsAnywhere) Then Debug.Print , "<", targetShape.Name, targetShape.Cells("Prop.NetworkName").ResultStr("") End If Next End If Next End Sub
Similarly, you may want to simply list the next connected 2D shape, effectively ignoring the cable. In this case, you can use the new ConnectedShapes() method, with the relevant arguments visGluedShapesIncoming2D or visGluedShapesOutgoing2D, to produce an output like the following ( using the ListNextConnections macro below):
Shape Server server-01
> Router.45 router-02
> Router.91 router-03
Shape Router router-01
< Server.75 server-03 Shape Server.30 server-02 > Router.45 router-02
> Router.91 router-03
Shape Router.45 router-02
< Server server-01
< Server.30 server-02 Shape Server.75 server-03 > Router router-01
Shape Router.91 router-03
< Server server-01
< Server.30 server-02
Public Sub ListNextConnections() Dim shp As Visio.Shape Dim connectorShape As Visio.Shape Dim sourceShape As Visio.Shape Dim targetShape As Visio.Shape Dim aryTargetIDs() As Long Dim arySourceIDs() As Long Dim targetID As Long Dim sourceID As Long Dim i As Integer For Each shp In Visio.ActivePage.Shapes If Not shp.OneD Then If shp.CellExists("Prop.NetworkName", Visio.visExistsAnywhere) Then Debug.Print "Shape", shp.Name, shp.Cells("Prop.NetworkName").ResultStr("") arySourceIDs = shp.ConnectedShapes(visConnectedShapesOutgoingNodes, "") For i = 0 To UBound(arySourceIDs) Set sourceShape = Visio.ActivePage.Shapes.ItemFromID(arySourceIDs(i)) If sourceShape.CellExists("Prop.NetworkName", Visio.visExistsAnywhere) Then Debug.Print , "<", sourceShape.Name, sourceShape.Cells("Prop.NetworkName").ResultStr("") End If Next aryTargetIDs = shp.ConnectedShapes(visConnectedShapesIncomingNodes, "") For i = 0 To UBound(aryTargetIDs) Set targetShape = Visio.ActivePage.Shapes.ItemFromID(aryTargetIDs(i)) If targetShape.CellExists("Prop.NetworkName", Visio.visExistsAnywhere) Then Debug.Print , ">", targetShape.Name, targetShape.Cells("Prop.NetworkName").ResultStr("") End If Next End If End If Next End Sub
I think this makes interrogation of connected diagrams, of all flavours, much simpler, though I would love to have similar ShapeSheet functions too!