Help With Connect All Shapes to Each Other VB Script

Started by oompa_l, May 17, 2008, 05:13:58 PM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

oompa_l

hi

the script I am having trouble with can be found here - http://www.visguy.com/2008/03/17/connect-all-shapes-to-each-other/ .

I have attached the file I am trying to apply it to. I am not literate in VB so I can't seem to find the problem. I have been pasting the code into a new macro under the thisdocument module and then running it, but nothing appears to be happening. I don't know if it's my file or the script which needs to be tweaked.

any advice is really appreciated.
thanks
o

Lars-Erik

Nasty ;)
It seems to give an error and immediately jump to the "Err:" as per command.

"Error 91: Block or object variable With is not configured"

Let's hope that Chris his Visiscense is ringing and he will get over here to comment (Spiderman instead of batman reference this time...)

- Lars


oompa_l

Lars Erik

visGuy isn't responding, for whatever reason...Do you have any ideas how I might take a series of shapes and connect them all to each other? I have a group of about 70 that needs to be connected to each other in various configurations - each configuration I can separate on different pages. In any case manually tying them all together would be a nightmare...I'm sort of in a bind here...

thanks!

Lars-Erik

I'm afraid i can't help you :(
I tried the macro, but it doesn't seem to run for me either. The comments at the post seem to indicate more people cant get it to run.
I don't know why its not working :( you really need Chris to help you here...

- Lars

Visio Guy

Hi Guys,

There were a number of problems with the code. As the article stated, the code was written in VB.NET, so a few changes need to be made:


  • A lot of spacing problems were messing up the line continuations. Ie: where " _" occurs at the end of a line
  • The "Set" keyword was missing from object assignments

The last problem was specific to oompa_l's situation. He had turned off connector-gluing at the top-level, so the actual code needed to glue the connectors to sub-shapes of his circles. I did this by identifying instances of "Master.0" (his particular shape)

If a shape is an instance of Master.0, then we get the first sub-shape instead, and glue the connector to that. This is a hack-fix, and won't handle modifications to shapes very well. But, well, I get paid the big bucks for that kind of stuff.

Here's the interesting code, inside of Sub m_connectShapes:


Private Sub m_connectShapes(ByRef shpFrom As Visio.Shape, ByRef shpTo As Visio.Shape)

   ...
   
    '// Check for oompa_l special case:
    If Not (shpFrom.Master Is Nothing) Then
      If shpFrom.Master.Name = "Master.0" Then
        '// Connect its Begin to a sub-shape 'From' shape:
        Call shpConn.CellsU("BeginX").GlueTo(shpFrom.Shapes(1).CellsU("PinX"))
      End If
    Else
      '// Connect its Begin to the 'From' shape:
      Call shpConn.CellsU("BeginX").GlueTo(shpFrom.CellsU("PinX"))
    End If
   
    If Not (shpTo.Master Is Nothing) Then
      If shpTo.Master.Name = "Master.0" Then
        '// Connect its End to a sub-shape 'From' shape:
        Call shpConn.CellsU("EndX").GlueTo(shpTo.Shapes(1).CellsU("PinX"))
      End If
    Else
      '// Connect its End to the 'To' shape:
      Call shpConn.CellsU("EndX").GlueTo(shpTo.CellsU("PinX"))
    End If

End Sub


You can see, I just repeated the "fix" code twice in the If-Then-Else clauses. This is kind of sloppy, and if oompa_l will be making lots of changes, this needs to be compartmentalized and more robust.


Here's the whole updated listing:


Public Sub ConnectAllShapes()

    On Error GoTo Err

    '// Create an undo-scope, so that we can undo all the
    '// connections with just one Ctrl + Z:
    Dim UndoID As Long
    UndoID = Visio.Application.BeginUndoScope("Connect All Shapes to Each Other")

    '// This is where we really get the connecting done:
    '// Get a Visio Page object:
    Dim pg As Visio.Page
    Set pg = Visio.ActivePage

    '// Connect all shapes on the page:
    Call m_ConnectAllShapes(pg)

    Call Visio.Application.EndUndoScope(UndoID, True)

    Exit Sub

Err:
    Debug.Print "An error occurred! " & vbCrLf & Error$
    Call Visio.Application.EndUndoScope(UndoID, False)
End Sub

Private Sub m_ConnectAllShapes(ByRef visPg As Visio.Page)

    Dim shpFrom As Visio.Shape, shpTo As Visio.Shape, shpConn As Visio.Shape, shp As Visio.Shape
    Dim collShapes As Collection
    Dim i As Integer, j As Integer

    '// Set the page-layout settings for routing-style,
    '// jump-style, etc.
    Call m_setPageLayoutSettings(visPg)

    '// Add all the non-connector shapes to a VB collection:
    Set collShapes = m_getShapesToConnect(visPg)

    '// Loop through the shapes in the shapes collection:
    For i = 1 To collShapes.Count

        Set shpFrom = collShapes.Item(i)

        '// Connect to all the other shapes:
        For j = i + 1 To collShapes.Count

            Set shpTo = collShapes.Item(j)

            Call m_connectShapes(shpFrom, shpTo)

        Next j

    Next i

End Sub



Private Sub m_connectShapes(ByRef shpFrom As Visio.Shape, ByRef shpTo As Visio.Shape)

    '// Visio 2007 introduced a new method for connection
    '// shapes. This proc looks at the Visio version and
    '// decides whether to use the old way or the new way.

    Dim pg As Visio.Page
    Set pg = shpFrom.ContainingPage

    '// Note: if you're not running Visio 2007, this might not
    '// even compile -- you'll have to comment-out the first part
    '// of the If-Then block...

    '// Drop the built-in connector object somewhere on the page:
    Set shpConn = pg.Drop(pg.Application.ConnectorToolDataObject, 0, 0)
   
    '// Check for oompa_l special case:
    If Not (shpFrom.Master Is Nothing) Then
      If shpFrom.Master.Name = "Master.0" Then
        '// Connect its Begin to a sub-shape 'From' shape:
        Call shpConn.CellsU("BeginX").GlueTo(shpFrom.Shapes(1).CellsU("PinX"))
      End If
    Else
      '// Connect its Begin to the 'From' shape:
      Call shpConn.CellsU("BeginX").GlueTo(shpFrom.CellsU("PinX"))
    End If
   
   
    If Not (shpTo.Master Is Nothing) Then
      If shpTo.Master.Name = "Master.0" Then
        '// Connect its End to a sub-shape 'From' shape:
        Call shpConn.CellsU("EndX").GlueTo(shpTo.Shapes(1).CellsU("PinX"))
      End If
    Else
      '// Connect its End to the 'To' shape:
      Call shpConn.CellsU("EndX").GlueTo(shpTo.CellsU("PinX"))
    End If

End Sub

Private Function m_getShapesToConnect(ByRef visPg As Visio.Page) As Collection

    Dim shp As Visio.Shape
    Dim collShapes As Collection

    Set collShapes = New Collection

    '// For this example, we will get all shapes on the page
    '// that ARE NOT of these:
    '//
    '//  1. Connectors
    '//  2. Foreign objects (like Buttons)
    '//  3. Guides

    For Each shp In visPg.Shapes

        If (shp.OneD = False) And _
           (shp.Type <> Visio.VisShapeTypes.visTypeForeignObject) And _
           (shp.Type <> Visio.VisShapeTypes.visTypeGuide) Then

            Call collShapes.Add(shp)

        End If

    Next

    Set m_getShapesToConnect = collShapes

End Function



Private Sub m_setPageLayoutSettings(ByRef visPg As Visio.Page)

    '// We can set layout and routing options for the page by
    '// accessing the ShapeSheet for the page, and setting cells
    '// in the Page Layout section.
    '//
    '// You can see the PageSheet by deselecting all shapes on the
    '// page, and choosing Window > Show ShapeSheet.



    '// Set page routing style to center-to-center:
    visPg.PageSheet.CellsSRC(Visio.VisSectionIndices.visSectionObject, _
                             Visio.VisRowIndices.visRowPageLayout, _
                             visPLORouteStyle).ResultIUForce = 16


    '// Set to connector intersection to 'gap':
    visPg.PageSheet.CellsSRC(Visio.VisSectionIndices.visSectionObject, _
                             Visio.VisRowIndices.visRowPageLayout, _
                             Visio.VisCellIndices.visPLOJumpStyle).ResultIUForce = 2


    '// Note: another way to access the PageSheet cells is by name, ie:
    '// visPg.PageSheet.Cells("RouteStyle").ResultIU = 16
    '// visPg.PageSheet.Cells("LineJumpStyle").ResultIU = 2


End Sub

For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010

oompa_l

thanks so much chris. looks like alot of little tinkering to get it done...

the only problem is, it's still not working for me over here. Is it for you?

I made sure that my shape's master matched the "special" case you made for me, and I even tried a brand new file with visio-equipped boring shapes, but still nothing. Interesting enough on one of the first tries I got a connector whose midpoint was the lower left hand corner of my page!?

anyways, I appreciate the effort...

Lars-Erik

Quote from: Visio Guy
VB code

Below is the VBA code to get the job done. You can copy the code and directly paste it into the ThisDocument module of any document's VBA project.

The code is easily converted to VB.NET. However, you'll need to do the following:

   1. Add a reference to the Visio 12.0 Type Library (or Visio 11.0, or...)
   2. Add the line: Imports Visio = Microsoft.Office.Interop.Visio.

To connect the shapes, simply run the ConnectAllShapes subroutine.

It gave me the idea the code was VB, and could be made into VB.NET. O well.

Oompa, ive tried the "whole updated listing" and it works great for me out of the box.
I drew a bunch of random circles, ran the ConnectAllShapes() macro and voila.
Added my test file so you can try it aswell.

Nice one Chris!

- Lars


oompa_l

yes, thank for showing me that...BUT - try and make one of those circles a master shape and then replicate on the page and neither the new instances of the master, nor the circles as you drew them work .... check it for yourself

Lars-Erik

A yes, it seems to just drop an amount of connection lines on the page (without connecting them to the shapes)

Visio Guy

Quote from: Visio Guy on May 20, 2008, 09:35:12 PM
...
The last problem was specific to oompa_l's situation. He had turned off connector-gluing at the top-level, so the actual code needed to glue the connectors to sub-shapes of his circles. I did this by identifying instances of "Master.0" (his particular shape)

If a shape is an instance of Master.0, then we get the first sub-shape instead, and glue the connector to that. This is a hack-fix, and won't handle modifications to shapes very well. But, well, I get paid the big bucks for that kind of stuff.
...

As I said before, the updated code was made to specifically work with the "Master.0" that oompa_l is using in his original drawing, and having problems with. To make it work for the general case will take some parameterization, and some specific checking of each shape and its sub-shapes for the routing settings.

Unfortunately, this is a lot more work than can be accomplished in a few minutes in a discussion forum.
For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010

oompa_l

sorry about my own confusion...yes it does work on my Master.0 shape!!!

I owe you big time

oompa_l

it seems that if I go back to the master.0 shape and give the outer ring a solid fill and send it to the back (ordering) the connectors go back to being routed to the outside of the overall shape again...it's interesting. at every turn I seem to ask for something that Visio just doesnt want to give me...