Selection by P

Started by standardlaw, May 21, 2020, 06:33:12 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

standardlaw

I'm looking to programmatically select shapes based within a region/area given coordinates x1, y1, x2, y2 and then change fill properties. The master i am working on has all the shapes fragmented. I can do what i'm asking by just selecting the region (press and hold the left mouse button, drag to second position, release and then hit the fill button).

standardlaw

http://visguy.com/vgforum/index.php?topic=7868.msg33722#msg33722

Looks like this is the best way to go. Can someone show me an example where the Sub calls the function and fills the shapes that are selected by the function?

vojo

need to be care around formatting
while earlier versions of Visio handled formatting correct, latest 2 generations have side effects
(take group of shapes and adjust transparency = all colors blown away to white....solution:  adjust on each child shape).

I guess all I am saying its this sort of macro should be tested with all kinds of formatting tasks or assume need to do each shape explicitly

standardlaw

Quote from: vojo on May 22, 2020, 12:01:39 AM
need to be care around formatting
while earlier versions of Visio handled formatting correct, latest 2 generations have side effects
(take group of shapes and adjust transparency = all colors blown away to white....solution:  adjust on each child shape).

I guess all I am saying its this sort of macro should be tested with all kinds of formatting tasks or assume need to do each shape explicitly

Makes sense. If the spatialneighborhood returns a list of shape ids in the selection then i can just iterate through the individual shapes. I'm having trouble getting that far though.

Nikolay

#4
Can't you just iterate over ALL shapes and check if they are inside the rectangle?

The "SpatialNeighbors" is rather slow (as it is designed to work with non-rectangular complex regions, taking into account all geometries). If your shapes are simple, it may not worth it.
And second, dropping a "temporary" rectangle may have some undesired side effects like shapes or connectors moving around because of auto-placement or auto-routing.

I mean, maybe you could use something as simple as this (x1 < x2, y1 < y2)?

Sub Iterate(rx1, ry1, rx2, ry2)

Dim s As Shape
For Each s In ActivePage.Shapes
    Dim sx1 As Double, sy1 As Double, sx2 As Double, sy2 As Double
    s.BoundingBox 1, sx1, sy1, sx2, sy2
    If sx1 <= rx2 And sx2 >= rx1 And sy1 <= ry2 And sy2 >= ry1 Then
        Debug.Print s
    End If
Next

End Sub

standardlaw

Quote from: Nikolay on May 22, 2020, 05:52:45 PM
Can't you just iterate over ALL shapes and check if they are inside the rectangle?

The "SpatialNeighbors" is rather slow (as it is designed to work with non-rectangular complex regions, taking into account all geometries). If your shapes are simple, it may not worth it.
And second, dropping a "temporary" rectangle may have some undesired side effects like shapes or connectors moving around because of auto-placement or auto-routing.

I mean, maybe you could use something as simple as this (x1 < x2, y1 < y2)?

Sub Iterate(rx1, ry1, rx2, ry2)

Dim s As Shape
For Each s In ActivePage.Shapes
    Dim sx1 As Double, sy1 As Double, sx2 As Double, sy2 As Double
    s.BoundingBox 1, sx1, sy1, sx2, sy2
    If sx1 <= rx2 And sx2 >= rx1 And sy1 <= ry2 And sy2 >= ry1 Then
        Debug.Print s
    End If
Next

End Sub


Excellent idea. I will look to implement that in my code.
I would be able to do this on shapes within a master, correct?
Can a modified version of this code work for shapes partially within the bounding box?

Nikolay

#6
Within a master - you probably mean, within a group (that can be produced as a result of dropping a master from a stencil)?
Now it iterates over the top-level shapes only, but you can modify it to iterate over all shapes, including those which are parts of the groups.
Either by recursion or using .CreateSelection method instead of .Shapes method with "include sub" flag.

Please note that this code already will include shapes that are only partially within the bounding box.
You'll need to modify the inclusion logic ("if" statement) it to change this behavior.

standardlaw

I'm editing a master within a stencil. All of the shapes are on the page (not grouped, etc.).
Seems that activepage or activewindow does not work.

Nikolay

Ah I see. Master is a special case. You could try something like this:


Set m = ActiveDocument.Masters("Rectangle")
Set mc = m.Open
    For Each s In mc.Shapes
     ....
    Next
mc.Close


More details here:
http://www.visguy.com/2008/02/25/edit-visio-masters-programmaticallythe-right-way/