Loop through a sub-set of shapes using shape name, not shape ID?

Started by Zarty, August 02, 2010, 03:27:53 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Zarty

I am writing a subroutine in VBA, which is passed 1 parameter:-

rst - a recordset of a subset of shapes on the page

The recordset lists the Shape names eg. "Shape1", "Shape5", "Shape8"

What's the best way to change the properties of just the shapes in the recordset (eg. change lineweight)?  There are many more shapes on the page that I want to leave untouched.   I've already written another subroutine that loops through every shape on the page based on ID and sets them back to default settings so they all look the same.

So far, I have something like this...


Dim shape1 As Visio.Shape

Do While Not rst.EOF
    Debug.Print rst!RootName
    Set shape1 = Visio.ActivePage.Shapes(rst!RootName)
    Shape1.Cells("lineweight") = 0.1
    rst.MoveNext
Loop


The above doesn't work as it errors on the line:-

   Set shape1 = Visio.ActivePage.Shapes(rst!RootName)

with "Invalid Parameter"


It only seems to want a literal name as a parameter eg. "Shape5"

Thanks,
Zarty

Visio Guy

It's probably better to use Shapes.ItemByID(). Shape names are only good at the "same level", ie: shapes on the page can refer to each other by name, and names must be unique. Inside of a group, shape names are unique, inside a grouped sub-shape in a group, shape names are unique. Across these boundaries, shape names aren't unique.

Hard to describe, but easy to demonstrate. You could have ten groups on a page. Each group could contain a sub-shape named "Child 1", and they would all be named "Child 1", not "Child 1.1", Child 1.2", etc. But at the same level, such as on a page, or within a group, there could only be one shape named "Child 1".
For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010

Yacine

hi Zarty,
it's a quite common task you are looking for and depending on the complexity of your drawing and the number of times you want to perform such operations there are 2 main possibilities.
1) the fast one would be to use the selection object of your page. ie you select a number of shapes and run a certain macro
2) you select your group of shapes by defining a certain property unique to that group. That could be a layer. In bigger drawings, where you can lose your selection that's the better choice.
For both possibilities there are plenty of examples in the forum.
cheers.
Yacine

Zarty

Visio Guy... Thanks, I can see that using the shape id would be easier at the Visio level but I am working on a solution where the diagram is defined in a database table (SQL Server).   Because Visio generates the ID's, there is no practical mapping between these ID's and the Names.   I can enforce uniqueness on the names by using standard techniques employed in database design - primary keys, clustered indexes and other constraints.   Therefore, I am not concerned by the fact that Visio can't ensure uniqueness for shape names.   Also, if I reference Visio shape id's, there would have to be manual process to map these names to ID's in the database.   Every time I changed the diagram, I would have to manually update the table... Nightmare.   Also, I'm looking at a next step where I can programmatically generate the diagram from the database and it's easier just to let Visio create the ID's as it normally does and not try to record these in the database.   Does my reasoning seem correct?

I was thinking of another way to solve my problem.  I already have a section of VBA code that loops through all the shapes by ID (incrementing count).   If I have the subset of shapes I want to highlight in a recordset (reference by name), surely I should be able to compare the recordset name (string) with the collection object/shape name?   Perhaps you could advise?

Yacine, thankyou for your suggestions but they are probably too manual for what I want.  As I said above, I can define the hierchary of the diagram in terms of a small number of different kinds of shapes (Applications, Databases and links between them) but the Shape name is a lot more useful in this context than the Visio generated ID.   I just wouldn't have time to go through the diagram creating groups and saving macros - the diagram would be subject to regular change.  How wonderful it would be to define the diagram in a database, press a button to create the diagram and then be able to click on objects in the diagram to see related objects in the hierarchy!?

Regards,
Zarty

Zarty

Well, I've managed to find a solution.   As I mentioned, I already had a loop using the ID and I originally used this just to reset the lineweight property of every shape.  I modified it to include a nested loop that checked if the name of the name of the outer loop shape matched the name in the inner loop's shape name (loop on a subset of shapes read from the table in the database).   If they match, I set the lineweight a bit heavier/thicker to highlight it.   This way, all of the shapes in the rowset are highlighted, which is what I wanted.  The only problem I had was using movefirst on the rowset so I worked around this by assigning the rowset to an array and then just incremended a counter to reference the next array value.  I also found that using UBound was necessary so I didn't go out of bounds on the array.

   
Dim arData As Variant
arData = rst.GetRows
       
Dim i1, j1 As Integer
For i1 = 1 To Visio.ActivePage.Shapes.Count
  Set objshape = Visio.ActivePage.Shapes(i1)
 objshape.Cells("lineweight") = 0.025

 For j1 = 0 To UBound(arData, 2)
   If objshape.Name = arData(0, j1) Then objshape.Cells("lineweight") = 0.1
  Next

Next


Cheers,
Zarty