Collection of shapeID's based on specific master without cycling/looping

Started by Noisy Cricket, February 10, 2016, 06:19:05 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Noisy Cricket

Hi all,

I was wondering whether it's possible to obtain a collection of shapeID's without first cycling through all shapes on the page and determining whether the shape is based on a specific master before it gets added to the collection.

Basically something similar to the getcontainerID's method...... but for masters.

Secondly, say I want to "store" that array once obtained to re-use it for several other procedures.... how to go about that?!
(or would it be a matter of restructuring code?)

Looking forward to hear!







Yacine

Hi Gijs,
I don't know what you problem is with cycling over all the shapes of the drawing.
I do this commonly in my code, parsing over several hundred shapes and speed is acceptable.
I wouldn't know of another way to get the right shapes.

As for the array where to store them, use a selection.
Dim Sel as selection
for each shp in activepage.shapes
  if criterium then
    sel.add shp, visselect (or similar, sorry for that)
  endif

Now you can use sel as variable to pass to other procedures and access the shapes with a for-each loop.

HTH,
Y.
Yacine

Noisy Cricket

Hi Yacine,

Thanks for the prompt response.

My problem with looping/cycling is that I'm using a procedure to present "live" results of a series of calculations made based on that particular set of master instances.

The procedure fires on eventxy (so whenever this set of shapes moves, the calculation needs updating
This works ok for a small number of shape but speed degenerates rapidly if either A) more of the master instances are present or B) a lot more shapes are on the page require cycling.

I can think of three improvements
1) Prepopulate a user.data field to contain all the shape-id's once.
This can then be accessed directly by code reducing the need for cycling through the shapes.
2) Have the master instances on a specific layer and cycle through the shapes on that layer instead of all the shapes on the page.
I think (not sure) that's how visio handles the get container
3) Repopulate the whole calculation table in user data fields (loads, distances, X's, Y's etc) to allow a relatively simple "lookup" to retrieve the numbers (although this could get cumbersome as well).

A typical series of calculations would be at least:
20 steps, 4 masters/shapes
6 if statements to determine which formula's to use (transfers to select cases)
returning an array of 8 numbers (forces/X,Y's) for each support and a summary array of the combined forces and X's and Y's.

Could be up to 1000's of steps and say 100 masters/shapes.
Just trying to make the perceived speed as fast as possible to avoid people from wanting to use the sheet (people are spoiled with Apple's interface and processing speeds of phones nowadays...)

Come to think of it, there's quite some values being intermediately stored in arrays and such, maybe there's something to gain there.

Again, all suggestions are welcome.

I'll try option 1 and 2 and have another look at the procedures to "trim excess fat" :)
Will report speed gain in milliseconds :)





AndyW

Performance should be fine going through a few hundred shapes in a collection, although if I have lots of shapes to work with I end up using a VBA collection or dictionary.

As for a solution, that really depends on what changes are being made to your diagram. Are more shapes being added or just existing shapes being moved. If existing shapes are just being moved, then when you open the document you could store the shapes in a dictionary, look up by master name and store a collection of the shapes for that entry.

One other thing to consider is thet if several shapes are being moved, is this causing you to repeat the same calculations multiple times. If so, I would suggest the event just sets a flag and a timer event checks the flags and then processes the calculations once. If the calculations are really simple, you could just precess them at a set time interval.

I'm modelling electrical networks with with hundred of shapes tht can be updated following a change.
Live life with an open mind

Noisy Cricket

Hi Andy,

Thanks for the thoughts.
The movement of the supports is linked to a single shape which in turn is linked to a pulldown list which contains the respective movement values and updated the single shape location. No shapes are added but the "state" of a support may change and subsequently resulting values are calculated in a different way.

Not sure how to work with dictionaries yet (i'm learning as I go).

As for the calculations being repetitive, it will fire only if the "master" (single shape) received a new value from the pulldown.
The calculations are relatively simple but require some storage of the results to an array/excel sheet, whichever is easier (Suppose first storing in array and then write array to excel in one go.

There might be some improvement in dimensioning and re-dimensioning the arrays.... this is done every time the shape moves but most don't change in size during the process.




georgejost

Quote from: Noisy Cricket on February 11, 2016, 07:17:03 AM
Hi Yacine,

Thanks for the prompt response.

My problem with looping/cycling is that I'm using a procedure to present "live" results of a series of calculations made based on that particular set of master instances.

The procedure fires on eventxy (so whenever this set of shapes moves, the calculation needs updating
This works ok for a small number of shape but speed degenerates rapidly if either A) more of the master instances are present or B) a lot more shapes are on the page require cycling.

I can think of three improvements
1) Prepopulate a user.data field to contain all the shape-id's once.
This can then be accessed directly by code reducing the need for cycling through the shapes.
2) Have the master instances on a specific layer and cycle through the shapes on that layer instead of all the shapes on the page.
I think (not sure) that's how visio handles the get container
3) Repopulate the whole calculation table in user data fields (loads, distances, X's, Y's etc) to allow a relatively simple "lookup" to retrieve the numbers (although this could get cumbersome as well).

A typical series of calculations would be at least:
20 steps, 4 masters/shapes
6 if statements to determine which formula's to use (transfers to select cases)
returning an array of 8 numbers (forces/X,Y's) for each support and a summary array of the combined forces and X's and Y's.

Could be up to 1000's of steps and say 100 masters/shapes.
Just trying to make the perceived speed as fast as possible to avoid people from wanting to use the sheet (people ar ...

you can get the master from the shape but to go from xy to the shape, do u need to loop through all shapes and use your hit test method

If you use a data structure, you could avoid looping if you can assign shapes dynamically. lots of nice collections.

AndyW

Do you need the data in Excel, performance wise I would go with VBA collections, dictionaries etc and keep it all within visio.
Live life with an open mind

Noisy Cricket

Data in Excel. Yes.

Eventually the date needs to find it's way to excel (export of the numbers) but I suppose temporarily storing everything in arrays and then stringing these together to form delimited strings which in turn can be indexed to show the correct values for a given step?!

This would be the "pre-populated" version of the sheet which runs a procedure once, takes a moment.

Hoping to be able to create a hybrid solution (that does a single step on the fly as well as the ability to prepopulate)