In a macro I'm working on, I allow the user to "store" selected items in a Shaperange, and also to select and add additional items to that Shaperange.
This is done so that the items in the ShapeRange can then be used to create an active selection at a later time.
At some points in time, I want to check to see if all of the items in that Shaperange still exist in the document. Specifically, if all of the items that were stored in the Shaperange were later deleted, I want to be able to disable the "Restore saved selection" button on the form.
Is there a way to check whether one of those referenced items still exists? So that I can "clean up" the Shaperange so that it only contains items that exist?
I could record the active selection, use the Shaperange to create a selection, set the Shaperange to that selection, then restore that saved selection - but that would create problems with my "responsive" macro.
another thing I find useful (if a little defensive) is to test for a shaperange to actually exist
If not shaperange is nothing or shaperange.count > 0 then ... run code
you have to use the double negative to test for a strangeranges existence so it might require a little rejigging of your code but well worth it!
when you release macros to other users or want to reuse methods as much as possible it's a good idea to check both!
That's a very good suggestion!
In this case, I was checking the existence of the shaperange before calling this sub, but I see the wisdom of "build it right, build it once" to have something that will work reliably in more circumstances.
I broke out the two checks into two separate lines instead of using an "or", as I think that would still fail on the shaperange.count if the shaperange didn't exist.
Public Sub SR_remove_nonexisting(ByRef Shaperange As Shaperange)Dim lngSR_index As Long If Not Shaperange Is Nothing Then If Shaperange.Count > 0 Then lngSR_index = 1 Do If ShapeExists(Shaperange(lngSR_index)) = False Then Shaperange.Remove lngSR_index Else lngSR_index = lngSR_index + 1 End If Loop Until lngSR_index > Shaperange.Count End If End IfEnd Sub
I can't test this now as I am in the middle of decorating my house!
Though I've used that line a lot in my own codebase a lot so I assume 'if or' statements check in the sequence they're written in. So as long as you test for the shape for 'not' being nothing before using the 'or' for checking any properties of the range/shape it'll work fine.
It is essentially the same thing as you have above just comes downs to personal preference.
Does anyone have any further insight into how if/or statements work? and is it the same with compiled code like C#?
I tried the "or" version, and it failed if the shaperange didn't exist. When you have the opportunity, play with it a bit to see.
Trying to learn more (what I don't know about this would fill a book) I have read that VBA does not have "short-circuit evaluation".
Even when outright failure is not a consideration, some take that into account in order to avoid calling an "expensive" function when it isn't strictly necessary; e.g., can't use the first part of an "and" to avoid calling an expensive function in the second part.
I've just tested it and you sir are correct again! and that is a very helpful thing to know. Every day a school day with programming!
What programming I have been doing lately is with learning C# the proper way (using proper training resources as opposed to tinkering in the VBA) and it always amazes me how many assumptions I have about programming are incorrect.
Looking through my code I had actually used it like my suggestion but prior to using the function, I've used the old 'set SR = NEW SHAPERANGE' so testing it for nothing was completely redundant anyhow! I'll be fixing that right now! Thanks for the insight!