Select shapes by their (x,y) coordinates

Started by Abeiis, May 08, 2017, 04:20:03 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Abeiis

Dear ALL,
I need a code to allow me to Select shapes that are within a specific x,y coordinates. I tied to record a macro, but macros does not log selection as I draw the selection rectangular on the shapes; instead, it logs their names - this will not work consistently as you know.
So, to simplify this issue, I like to supply the x,y coordinates, and the code would select all shapes touching that area, Thanks!

Regards,
Abe

Yacine

#1
Hello Abe,
this only true with the macro recorder.
Here's the solution when working with the mouse.
dim shp as shape
for each shp in activewindow.selection
  debug.print shp.cells("pinx").resultstr(""); ... same for piny
next shp


When working with code you could draw a temporary rectangle and ckeck for its spacialneighborhood.

Yacine

Abeiis

Hi Yacine,
Thank you for your prompt reply,

I am not sure if I understand - I did try recording a macro but the recorder did not record the selection I made.
I am still working with List-Controls, and you know, each added List shape, the shape takes additional number. Said that, in my reading I found "vsoSelect.BoundingBox" that others seams to use to identify the selection box. Either way, please provide me with working code so I can view the full picture of how it is done, Thanks!

Reference Link:
https://answers.microsoft.com/en-us/msoffice/forum/msoffice_visio-mso_winother/how-to-select-all-visio-shapes-contained-within/7c947f89-a6c7-441d-a4a0-c6d35e4f1241


PS: did you check out my file attachment in our last discussion?

Regards,
Abe

Nikolay

#3
Visio does not have API to do that directly (programmatically select shapes by specifying a rectangle)
selection.BoundingBox returns the bounding box of the current selection!

I believe I saw it mentioned somewhere here on the forum, but was unable to find now. Anyways:

One way is to iterate over all shapes to see if they intersect with your target rectangle.
That's fine if your shapes are rectangles, or if you don't care about the form of the shapes and it's okay to think of them as rectangles for that check.

If you do care about the form of the shapes (e.g. have something like ellipses or some complex-formed shapes, so shape shape's bounding box cannot be used as a criteria for inclusion),
then you could really put a transparent rectangle on the page (or have it already on the page, if the position is fixed) and then use it's .SpatialSearch method to find intersecting shapes.
.SpatialSearch is rather slow if you have many complex shapes, but anyways it's easier than anything else for this case.

Yep, sorry, there is no one-line code to accomplish that.

As for the lists/containers, there are special functions to check if some shape is a member of a list/container, both for ShapeSheet (formula) and VBA, coordinates are not needed.
Means, in case you use lists/containers you don't even need to calculate anything - all parents are already available.

Abeiis

Thanks Nikolay,
What I am deal with is this:
I have 7 columns of List-Controls, each column have 5-10 shapes - I insert a ListBox above each column. I need to select the shapes in the 1st column and place them into the 1st SelectBox, and so forth for the 2nd column and so on.
If I can (programmatically) rename the shapes so I can cycle through them and select the shapes in the 1st column by their x coordinate, then I am halfway there. I appreciate any help doing that, Thanks!

Regards,
Abe


wapperdude

#5
@Abe:  in your post, Visio Proximity Movement, reply #12, the code will select the desired shapes in a column.  You also need to set the horizontal "spread" for the columns.  In the example, I based the column on the position of the selected shape, but the Xmin and Xmax could be literal values that you supply.

Since, the shapes are not grouped or in a container (yet), the code should work as constructed.

You need to change the distribution statement to become:  ActiveWindow.Selection.Move 0#, 5  This will move the selection and place inside the container you've placed above the column.  The "5" is the amount of vertical movement.  You will have to set value as needed. 

Oh, you could also add Ymin, Ymax to limit the range of the vertical search.

As Yacine mentioned, you could draw a rectangle and use spatial neighbor to find all shapes that are enclosed by the rectangle.  This would be a variation to specifying the x- and y- limits.

Wapperdude
Visio 2019 Pro

wapperdude

#6
For example, with a wee bit of searching, you can find code to do the rectangle search, such as this posted by Nikolay:
You could actually draw a rectangle with those coordinates and then use Shape.SpatialNeighbors to find out all shapes in that rectangle.. Something like this (VBA):


Function SelectByRectangularCrossingBox(page, _
    lowerleftX, lowerleftY, upperrightX, upperrightY) As Selection

    scopeId = page.Application.BeginUndoScope("try")

      Set rc = page.DrawRectangle(lowerleftX, lowerleftY, upperrightX, upperrightY)
      Set SelectByRectangularCrossingBox = rc.SpatialNeighbors(visSpatialContain, 0.01, 0)

    page.Application.EndUndoScope scopId, False

End Function
'The code is wrapped around with BeginUndoScope/EndUndoScope to cancel changes.


Wapperdude
Visio 2019 Pro

Abeiis

Thanks Wapperdude,
This is great; I will get to work on that and let you know.

Regards,
Abe