Hi there,
Hoping to find some help, I have a rectangular shape with connection points on either side of it and text in the middle. I am struggling to find any information on how to tell, within the ShapeSheet, whether a connection point has a connector connected to it. Ideally, I would like to be able to tell whether a connector is connected to connection points Connections.A or Connections.B and then change the horizontal alignment of the text accordingly. I'm fairly certain that, if this is something accessible from the ShapeSheet, that would be the easiest route - I have some custom C programming but would prefer this to be automated and not require any clicking to adjust the alignment. I'm hoping it's just a simple attribute that I'm missing.
Thanks in advance for any and all help with this!
The object connecting to another has some information about the connection. The object connected from hasn't. So basically you could use the connector, not the rectangle.
But even this information is not trivial to extract.
I recommend using code (VBA or C#)
The are lots of posts to this subject. From memory some are from our host Visio Guy, but Wapperdude has also done a lot.
Hi,
This is not possible with ShapeSheet.
Thus, automation must be done with code.
You could trigger the code from ShapeSheet cell "EventXFMod" in the connector or listen to Page.ShapeAddded/Changed events.
I guess what Yacine means is:
Only the connector knows to / from what cell it is connected.
And this is required to identify the glued connection points (Top, Bot, Left, Right).
From a rectangle you can only get the connector and the other rectangle, but not the connection point.
Here some demo code for your experiments.
* Add a rectangle
* Add connection points to each side
* Open the ShapeSheet and give the connection points row names: Top, Bot, Left, Right
* Copy the rectangle
* Connect both rectangles
* Select a rectangle and run StartFromShape()
* Select the connector and run StartFromConnector()
* See results in Immediate window
Public Sub StartFromShape()
Dim pge As Visio.Page
Dim shpSelected As Visio.Shape
Dim shp As Visio.Shape
Dim iDs() As Long
Dim i As Integer
Set pge = ActivePage
Set shpSelected = ActiveWindow.Selection.PrimaryItem
iDs = shpSelected.GluedShapes(visGluedShapesAll1D, "")
For i = 0 To UBound(iDs)
Set shp = pge.Shapes.ItemFromID(iDs(i))
Debug.Print shp.Name
Next
iDs = shpSelected.ConnectedShapes(visConnectedShapesAllNodes, "")
For i = 0 To UBound(iDs)
Set shp = pge.Shapes.ItemFromID(iDs(i))
Debug.Print shp.Name
Next
End Sub
Sub StartFromConnector()
Dim shp As Shape
Dim con As Connect
Set shp = ActiveWindow.Selection.PrimaryItem
For Each con In shp.Connects
Debug.Print con.ToSheet.Name & " -> " & con.ToCell.RowName
Next con
End Sub
Quote from: Yacine on March 04, 2024, 08:48:48 PM
The object connecting to another has some information about the connection. The object connected from hasn't. So basically you could use the connector, not the rectangle.
But even this information is not trivial to extract.
I recommend using code (VBA or C#)
The are lots of posts to this subject. From memory some are from our host Visio Guy, but Wapperdude has also done a lot.
Thank you! I will look into them, I appreciate the suggestion on an alternative way to accomplish this, I'll look at that route too
Quote from: Thomas Winkel on March 04, 2024, 09:45:32 PM
Hi,
This is not possible with ShapeSheet.
Thus, automation must be done with code.
You could trigger the code from ShapeSheet cell "EventXFMod" in the connector or listen to Page.ShapeAddded/Changed events.
I guess what Yacine means is:
Only the connector knows to / from what cell it is connected.
And this is required to identify the glued connection points (Top, Bot, Left, Right).
From a rectangle you can only get the connector and the other rectangle, but not the connection point.
Here some demo code for your experiments.
* Add a rectangle
* Add connection points to each side
* Open the ShapeSheet and give the connection points row names: Top, Bot, Left, Right
* Copy the rectangle
* Connect both rectangles
* Select a rectangle and run StartFromShape()
* Select the connector and run StartFromConnector()
* See results in Immediate window
Public Sub StartFromShape()
Dim pge As Visio.Page
Dim shpSelected As Visio.Shape
Dim shp As Visio.Shape
Dim iDs() As Long
Dim i As Integer
Set pge = ActivePage
Set shpSelected = ActiveWindow.Selection.PrimaryItem
iDs = shpSelected.GluedShapes(visGluedShapesAll1D, "")
For i = 0 To UBound(iDs)
Set shp = pge.Shapes.ItemFromID(iDs(i))
Debug.Print shp.Name
Next
iDs = shpSelected.ConnectedShapes(visConnectedShapesAllNodes, "")
For i = 0 To UBound(iDs)
Set shp = pge.Shapes.ItemFromID(iDs(i))
Debug.Print shp.Name
Next
End Sub
Sub StartFromConnector()
Dim shp As Shape
Dim con As Connect
Set shp = ActiveWindow.Selection.PrimaryItem
For Each con In shp.Connects
Debug.Print con.ToSheet.Name & " -> " & con.ToCell.RowName
Next con
End Sub
Thanks a ton, this was super helpful to envision what you were thinking - just so I'm following your StartFromShape() Sub, does that actually look for the connected shape? So if I were to connect shape B to shape A and select shape A, running StartFromShape(), it would print out Shape B, is that right?
You may find this interesting/helpful...
http://visguy.com/vgforum/index.php?topic=8701.msg38015#msg38015 (http://visguy.com/vgforum/index.php?topic=8701.msg38015#msg38015).
Other related links:
http://visguy.com/vgforum/index.php?topic=8912.msg39138#msg39138 (http://visguy.com/vgforum/index.php?topic=8912.msg39138#msg39138)
http://visguy.com/vgforum/index.php?topic=10263.msg47877#msg47877 (http://visguy.com/vgforum/index.php?topic=10263.msg47877#msg47877)
http://visguy.com/vgforum/index.php?topic=5844.msg23444#msg23444 (http://visguy.com/vgforum/index.php?topic=5844.msg23444#msg23444)
Visio connectivity background: connectivity information is contained in the connectors. It is not contained in the shapes glued to the connector ends. Connectivity information is not provided in any shapesheet. Such information must be extracted using code. Depending upon needs, connectivity can determine if connector is fully connected, has a floating end, what shapes are connected to it (thus, to each other), and what connection points are involved (and info about each point).
StartFromShape() returns both:
* The first for loop all glued connectors
* The second for loop all connected rectangles
For your application you will need StartFromConnector() to get the connection point information.
Hope the code in the attached document makes it more clear.
Quote from: wapperdude on March 05, 2024, 07:39:53 PM
You may find this interesting/helpful...
http://visguy.com/vgforum/index.php?topic=8701.msg38015#msg38015 (http://visguy.com/vgforum/index.php?topic=8701.msg38015#msg38015).
Other related links:
http://visguy.com/vgforum/index.php?topic=8912.msg39138#msg39138 (http://visguy.com/vgforum/index.php?topic=8912.msg39138#msg39138)
http://visguy.com/vgforum/index.php?topic=10263.msg47877#msg47877 (http://visguy.com/vgforum/index.php?topic=10263.msg47877#msg47877)
http://visguy.com/vgforum/index.php?topic=5844.msg23444#msg23444 (http://visguy.com/vgforum/index.php?topic=5844.msg23444#msg23444)
Visio connectivity background: connectivity information is contained in the connectors. It is not contained in the shapes glued to the connector ends. Connectivity information is not provided in any shapesheet. Such information must be extracted using code. Depending upon needs, connectivity can determine if connector is fully connected, has a floating end, what shapes are connected to it (thus, to each other), and what connection points are involved (and info about each point).
That sums things up perfectly, great info, thank you
Thomas' code has nice clean features, and is focused upon either a single selected shape or connector.
I drew from his code, and modified the above 1st referenced link, to provide additional, useful connector information. The code shows all connectors and attached shapes. It now includes any text, the connector row identity.
Attached is his file, updated.
For convenience, here's the code:
Public Sub ListGluedConnections()
'Code lists shapes attached to connectors on a page
'Original code developed by David Parker
'Code located @ https://blog.bvisual.net/2009/09/16/listing-connections-in-visio-2010/
'Minor code modification by Wapperdude, 2/4/2019
'Additional code changes based upon Thomas Winkel; http://visguy.com/vgforum/index.php?topic=10308.msg48165#msg48165
'Code 1st lists connector, then shows, if any, incoming and outgoing shapes
'
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
Dim vCon As Connect
Dim typeSkip As Boolean
typeSkip = False
For Each shp In Visio.ActivePage.Shapes
If shp.OneD Then
For Each vCon In shp.Connects
If Not typeSkip Then
Debug.Print "Connector", shp.Name, shp.Text, vCon.ToCell.RowName
arySourceIDs = shp.GluedShapes(visGluedShapesIncoming2D, "")
For i = 0 To UBound(arySourceIDs)
Set sourceShape = Visio.ActivePage.Shapes.ItemFromID(arySourceIDs(i))
Debug.Print "Src Shp: ", sourceShape.Name, sourceShape.Text
typeSkip = True
Next
Else
If shp.Connects.Count < 2 Then
Debug.Print "Connector", shp.Name, shp.Text, vCon.ToCell.RowName
End If
aryTargetIDs = shp.GluedShapes(visGluedShapesOutgoing2D, "")
For i = 0 To UBound(aryTargetIDs)
Set targetShape = Visio.ActivePage.Shapes.ItemFromID(aryTargetIDs(i))
Debug.Print "Tgt Shp: ", targetShape.Name, targetShape.Text
typeSkip = False
Next
End If
Next
Debug.Print ""
End If
Next
End Sub
Quote from: Thomas Winkel on March 05, 2024, 07:51:44 PM
StartFromShape() returns both:
* The first for loop all glued connectors
* The second for loop all connected rectangles
For your application you will need StartFromConnector() to get the connection point information.
Hope the code in the attached document makes it more clear.
Thanks Thomas, I appreciate you putting that into a file for me, that really does make it a whole lot clearer - this leads me to think that while I can't do what I originally intended on hoping to do, I might be able to use the concepts you have in your code for something... I'm just not quite sure what yet lol might have to sleep on it a couple of nights to see.
Thanks again for all of the help!
Quote from: wapperdude on March 06, 2024, 05:42:14 PM
Thomas' code has nice clean features, and is focused upon either a single selected shape or connector.
I drew from his code, and modified the above 1st referenced link, to provide additional, useful connector information. The code shows all connectors and attached shapes. It now includes any text, the connector row identity.
Attached is his file, updated.
For convenience, here's the code:
Public Sub ListGluedConnections()
'Code lists shapes attached to connectors on a page
'Original code developed by David Parker
'Code located @ https://blog.bvisual.net/2009/09/16/listing-connections-in-visio-2010/
'Minor code modification by Wapperdude, 2/4/2019
'Additional code changes based upon Thomas Winkel; http://visguy.com/vgforum/index.php?topic=10308.msg48165#msg48165
'Code 1st lists connector, then shows, if any, incoming and outgoing shapes
'
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
Dim vCon As Connect
Dim typeSkip As Boolean
typeSkip = False
For Each shp In Visio.ActivePage.Shapes
If shp.OneD Then
For Each vCon In shp.Connects
If Not typeSkip Then
Debug.Print "Connector", shp.Name, shp.Text, vCon.ToCell.RowName
arySourceIDs = shp.GluedShapes(visGluedShapesIncoming2D, "")
For i = 0 To UBound(arySourceIDs)
Set sourceShape = Visio.ActivePage.Shapes.ItemFromID(arySourceIDs(i))
Debug.Print "Src Shp: ", sourceShape.Name, sourceShape.Text
typeSkip = True
Next
Else
If shp.Connects.Count < 2 Then
Debug.Print "Connector", shp.Name, shp.Text, vCon.ToCell.RowName
End If
aryTargetIDs = shp.GluedShapes(visGluedShapesOutgoing2D, "")
For i = 0 To UBound(aryTargetIDs)
Set targetShape = Visio.ActivePage.Shapes.ItemFromID(aryTargetIDs(i))
Debug.Print "Tgt Shp: ", targetShape.Name, targetShape.Text
typeSkip = False
Next
End If
Next
Debug.Print ""
End If
Next
End Sub
This is slick, I think it's similar to the code you had in the other post, thanks for hooking me up with the file - just so I can understand, what is the line
For i = 0 To UBound(aryTargetIDs)
doing?
Before I answer your question, note that connectors may have 0, 1, or 2 connections. When VBA loops through a connector, it will get listed twice. Kinda annoying. Hence, the typeSkip parameter. Of course, that forces the code to handle special cases and things get a bet messy. That's a nice feature about Thomas' approach and not using glued shape construct.
But, now to your question. The preceding line, fills a 1 dimensional array with attached shapeIDs. The next line, your question, then steps thru these shapeIDs. This allows locating attachment points of both ends.
The code examines 1D shapes. These may be connectors or lines. It then checks for incoming (source) shapes, prints results. Loops thru, finds outgoint (target) shapes. Prints results, but doesn't duplicate printing the connector info.
A connector that only has 1 attached shape, may either be incoming or outgoing, hence, a special case for the code.
I did clean the code a smidge, and added a few more test conditions in the attached file. Note, gluing connector to connector still fails.
Public Sub ListGluedConnections()
'Code lists shapes attached to connectors on a page
'Original code developed by David Parker
'Code located @ https://blog.bvisual.net/2009/09/16/listing-connections-in-visio-2010/
'Minor code modification by Wapperdude, 2/4/2019
'Additional code changes based upon Thomas Winkel; http://visguy.com/vgforum/index.php?topic=10308.msg48165#msg48165
'Code 1st lists connector, then shows, if any, incoming and outgoing shapes
'
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
Dim vCon As Connect
Dim typeSkip As Boolean
typeSkip = False
For Each shp In Visio.ActivePage.Shapes
If shp.OneD Then
For Each vCon In shp.Connects
If Not typeSkip Then
Debug.Print "Connector", shp.Name, shp.Text
arySourceIDs = shp.GluedShapes(visGluedShapesIncoming2D, "")
For i = 0 To UBound(arySourceIDs)
Set sourceShape = Visio.ActivePage.Shapes.ItemFromID(arySourceIDs(i))
Debug.Print "Src Shp: ", sourceShape.Name, sourceShape.Text, vCon.ToCell.RowName
typeSkip = True
Next
Else
If shp.Connects.Count < 2 Then
Debug.Print "Connector", shp.Name, shp.Text
End If
aryTargetIDs = shp.GluedShapes(visGluedShapesOutgoing2D, "")
For i = 0 To UBound(aryTargetIDs)
Set targetShape = Visio.ActivePage.Shapes.ItemFromID(aryTargetIDs(i))
Debug.Print "Tgt Shp: ", targetShape.Name, targetShape.Text, vCon.ToCell.RowName
typeSkip = False
Next
End If
Next
Debug.Print ""
End If
Next
End Sub
Well, decided to see if there was a more efficient form for the code. Turns out yes. This is major update to last posted reply:
Public Sub ListGluedConnections()
'Code 1st lists connector, then shows, if any, incoming and outgoing shapes
'
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
Dim vCon As Connect
Dim typeSkip As Boolean
typeSkip = False
For Each shp In Visio.ActivePage.Shapes
If shp.OneD Then
For Each vCon In shp.Connects
If Not typeSkip Then
Debug.Print "Connector:"; shp.Name, shp.Text 'vCon.FromSheet, vCon.FromSheet.Text
Debug.Print vCon.ToSheet.Text, vCon.ToCell.RowName
typeSkip = True
Else
If shp.Connects.Count < 2 Then
Debug.Print "Connector", shp.Name, shp.Text
End If
Debug.Print vCon.ToSheet.Text, vCon.ToCell.RowName
typeSkip = False
End If
Next
Debug.Print ""
End If
Next
End Sub
Wow, this thread is becoming a real connector knowledge base 8)
But, coming back to the original question this is really simple using the techniques described above.
See attached document.
Comments:
* Code triggered from ShapeSheet cell "EventXFMod" in the connector
-> Thus the connector shapes must be prepared. This proceeding may be helpful:
https://support.microsoft.com/en-us/office/create-a-custom-connector-48f47591-b9d5-4e6f-9203-5b34ce09a5e9
* Used Macro Recorder to quickly find the align code.
* Avoid Code in Documents, better store it central in a stencil.
Fascinating. Interesting that it precludes doing a walking glue connection and only allows connection points.
Quote
Interesting that it precludes doing a walking glue connection and only allows connection points.
I've set GlueType to NoWalkingTo.