Visio Guy

Visio Discussions => ShapeSheet & Smart Shapes => Topic started by: MacGyver on April 23, 2024, 04:19:25 PM

Title: SETATREF(Height) / EventXFMod Behavior
Post by: MacGyver on April 23, 2024, 04:19:25 PM
I'm attempting to run a macro when height of a shape is changed to dynamically adjust connection points.  I'm running into an issue that appears others have run into (similar topic) (https://visguy.com/vgforum/index.php?topic=2760.0)

I've attempted using CALLTHIS in a user cell like such:
=SETATREF(Height,CALLTHIS("ConnPtAdjust"))And the ConnPtAdjust macro gets executed anywhere from 4-20 times.  I've attempted moving the code to the EventXFMod Behavior as well and same result - code is executed multiple times. 

The real oddity is if i toss a break in there for debug purposes, code functionality works exactly as expected.  If no break, it executes between 4 and 20 times.  Even adjusted my code so that called routine only debug prints the time to verify it wasn't my code causing the error and same results.

I changed from CALLTHIS to use RUNMACRO (and forgot to remove the visShape as input) and it errored out multiple times.  I have added various wait times to my code which also doesn't fix the issue.  Attached the drawing with shape in question, and included code that gets executed.

Any thoughts/tips would be greatly appreciated!
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: MacGyver on April 23, 2024, 05:14:48 PM
Another weird characteristic I've noticed is that when my macro is run multiple times. The various routine's appear to be running in parallel. As in one the first run of the routine may not have finished running before the second instance of the routine is executed.

I added code to debug.print start/stop times of an otherwise empty macro.  I then added some code that throws an intentional error.  The debug window shows that the macro started 6 times, and only ended once.  If the intentional error is removed, the macro was started some random number of times and ended some random number of times.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Yacine on April 23, 2024, 06:00:50 PM
Your observation is right. When you drag something (shape or size handle) the event gets fired multiple times. You can observe this if you run the events manager.

Why not put the macro on an action command (right button menu, then deliberately run the command)

Other option, but slightly more complex. Let the macro know that you've finished the resizing.
Define a general variable to hold the time. You're macro checks first the time between the current call and the value stored. If difference is small (threshold), it stores the current time in the global variable and leaves, otherwise it runs the actually intended code.

'*******************************
Public lastcall As Double
'*******************************

Sub ConnPtAdjust(shp As Visio.Shape)
    ' this will add remove conection points from some shapes - Box, Device, EGSE after shape is resized
    ' this macro is called from the shapesheet of the resized shape
    ' shp is passed into this routine from when it is called within the shapesheet
   
    ' connections points for these shapes are defined from the top down (connection point 1 and 2 are top/bot mid; cp3,4 is upper most left/right; cp5,6 are cps below 3,4
    ' additional connection points req to be added if last connection point Y value is >= 0.875 inches
    ' connection points req to be deleted if last connection point Y values is < 0.875 inches
   
    Dim connPtRow As Integer    ' row identifier of last connection point
    Dim UndoScopeID1 As Long
    Dim lastCPYVal As Single    ' y value of last connection point (zero based)
    Dim rowsToAdd As Integer    ' number of connection point rows we need to add to vba formula is 0 based. for shapesheet formulas it is one-based
    Dim rowNew As Integer      ' the row we just added
    Dim i As Integer
       
    Dim currentTime As Date
    Dim milliseconds As Double
    currentTime = Now()
'*******************************
    If Timer - lastcall < 100 Then
      lastcall = Timer
      Exit Sub
    End If
'*******************************
....

Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 23, 2024, 07:40:28 PM
Couple additional notes: 
>  Your usage of SETATREF is not correct.  The cell reference is intended to be the target for action, not the trigger.  Instead, use CALLTHIS("ConnPtAdjust")+DEPENDSON("Height").  For reference, see https://learn.microsoft.com/en-us/office/client-developer/visio/setatref-function (https://learn.microsoft.com/en-us/office/client-developer/visio/setatref-function) and https://visguy.com/vgforum/index.php?topic=6383.msg26308#msg26308 (https://visguy.com/vgforum/index.php?topic=6383.msg26308#msg26308)  This applies to all 3 of your SETATREF formulae.

>  I'm having trouble getting the code to run manually, but don't have time to investigate.  However, I recommend deconstructiong it, without the error stuff and without the auto-triggering.  Just add rows and delete.  You can step thru using <F8>, and you can set execution breakpoints.  There should not be any re-triggering.  Keep the control point count low.  I'm not convinced the code fully restricts adding / deleting.  Then, add the +Dependson statement in shapesheet.  Keep breakpoints in code.  See if behavior is as desired.  Finally, remove breakpoints and let code fully run.

>  As resizing the height is the trigger, moving should not be an issue.  Also, duplicating should not be an issue if the code is properly checking row count and connection position. There should not be any retriggering, or if there is, it's of no consequence.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: MacGyver on April 23, 2024, 11:13:57 PM
Thanks guys!
@wrapperdude, I changed it up to CALLTHIS("ConnPtAdjust")+DEPENDSON("Height"), but code continues to get executed multiple times.
 
QuoteAlso, duplicating should not be an issue if the code is properly checking row count and connection position. There should not be any retriggering, or if there is, it's of no consequence.
I'm finding this not to be the case.  With additional debug messaging, I'm finding out what is happening is 1st execution of macro Adds a new point and before it is able to set its properties, a 2nd macro might add another point, while the 3rd might delete one of those points.  so then when 1/2 macro goes to set the value it is not setting the intended row. 

Think I'll be resorting to @Yaccine's solution of making use of the shape actions.  Thanks all for the assistance!
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 24, 2024, 02:02:17 AM
I ran the macro from the shape with the Dependson syntax...confirmed the multiple executions.  Then, using Size and Position Window, typed in a value for height.  Execution was as expected for both increased and decreased heights.  The problem is dragging the height causes multiple triggers.

To eliminate the multiple triggers, the obvious is to disallow resizing by mouse drag.  Another approach might be to required mouse button up as necessary event.  Other approaches????

For the record, although I dont' recomme nd it, your SETATRREF syntax also works using keyboard value entry.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Yacine on April 24, 2024, 05:52:28 AM
The code with the global variable works. Why not try it?
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 24, 2024, 03:37:18 PM
Quote from: Yacine on April 24, 2024, 05:52:28 AMThe code with the global variable works. Why not try it?
How did you do this?  I tried and it made no difference,
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Yacine on April 25, 2024, 04:38:23 AM
Did you add the two pieces of code marked red?
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 25, 2024, 06:02:38 AM
Oh.  I thought you were referencing the original code.  So, no, I did not add the red stuff.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 25, 2024, 06:45:29 PM
Alrighty.  Copied / pasted the red code.  Variable declaration as global, the little IF timer is 1st executable in the macro.  Still doesn't execute properly.  I did tbhis with original code, located in Module1.,,

However, I did put a code break to pause the code before IF statement executed, then let code run, and all is well.  So, the If statement is being recognized.  Perhaps the test value needs adjusting. 

Seems to me, catching moluse button up event ought to be, perhaps less PC dependent, more reliable/predictable.

Edit:  Also need to test for initial case when lastcall = 0.  This would pass the IF test, but give incorrect multi-looping.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 26, 2024, 02:39:58 AM
Well, the global delay thing doesn't work for me.  I did add a test for lastcall=0, which will occur 1st time code runs with new launch of Visio. The timing errors tend to be grouped together, but range all over the place.  Doesn't seem to be a pattern nor predictable.

Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Thomas Winkel on April 26, 2024, 04:21:45 AM
I store the status in a user field to prevent such feedback loops:
QuoteEventXFMod=IF(User.Processing,SETF(GetRef(User.Processing),FALSE),SETF(GetRef(User.Processing),TRUE)+CALLTHIS("DoSomething"))

And some demo VBA:
Sub DoSomething(shp As Visio.Shape)
    Debug.Print "Do something that triggers EventXFMod..."
    shp.Cells("Width").ResultIU = 2 * shp.Cells("Width").ResultIU
End Sub
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Yacine on April 26, 2024, 07:48:57 AM
Isn't your solution handling only the first event?
We need to handle the last one.

Regarding the solution I posted, Wayne is right. The function gets called several times.

I consulted both ChatGPT and Gemini for a solution involving a timer object, but they did not manage to find a workable code.
In my idea the very first call would start the timer object and set a flag. As long as this flag is not reset do nothing.

A handler that the timer object triggers when the time is elapsed would then call the actual routine, then reset the flag.

Lost patience and dropped the idea. I don't know if someone else wants to pick it up.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 26, 2024, 01:59:27 PM
[quoteLost patience and dropped the idea][/quote]
I actually did spend a bit of time on this.  The concept seemed sound.  But ultimately, I think what happens is that the last event gets filtered by the timer too. After all, the system ought to be consistent in that regard.  Consequently, either all events are allowed to go thru or no events.  Using the timer did not allow the code to uniquely identify the last event.

What is it that makes the last event unique?  It is the mouse release (mouse up event) that immediately stops the dragging.  But there are a lot of mouse up events too.  So, the starting process is mouse down & shape selection & height change (& not 1D shape).  Followed by termination of mouse up.  What we take for granted is not a simple process.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Visio Guy on April 26, 2024, 05:24:59 PM
Without reading the post carefully, there's a way to handle this: your function ConnPtAdjust does one little thing:

bStuffChanged = TRUE

You might also want to note the shape's id, so you can find it later...

collChangedIds.Add(id)

...'later' happens when Visio.Application.NoEventsPending or  Visio.Application.IsIdle fire off. I can never remember which is the best event. When one of these fires, you process your que of IDs if bStuffChanged is true, and update your shapes.

This allows Visio to "settle down" after a flurry of events. So it matters less that your event is firing many, many times.

You'll have to figure out how to pass the id to your procedure. CALLTHIS  (https://learn.microsoft.com/de-de/office/client-developer/visio/callthis-function)allows for some arguments.

Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Yacine on April 26, 2024, 05:49:21 PM
@Chris, I saw the IsIdle property too, but the help said it gets only fired if you are listening to other events. Didn't understand and dropped this path.

But, and that is funny, I saw your answer in a google forum twenty years back and this inspired me to the following solution.

We don't need to handle the last event, but ONE event. So let it be the first one and block for a certain period all the following events.
We use a flag "Busy" to destroy the unwanted events, go in a loop with a doevents to prevent blocking other stuff and that's it.

Dim bBusy As Boolean
Dim counter As Long
Dim rejected As Long

Sub ConnPtAdjust(shp As Visio.Shape)
  Dim start As Double
  If bBusy Then
'    Debug.Print "Reject event"
      rejected = rejected + 1
    Exit Sub
  Else
    rejected = 0
    bBusy = True
    start = Timer
    counter = counter + 1
    Debug.Print "Start time: ", start
    While Timer - start < 1
      DoEvents
    Wend
    Debug.Print "Executing now @", Timer, "repetition", counter, "Rejected events", rejected
    actualRoutine shp
    bBusy = False
  End If
End Sub

Sub actualRoutine(shp As Visio.Shape)
  ' do stuff
End sub

Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Thomas Winkel on April 26, 2024, 06:59:13 PM
I removed the feedback-loop (User.Processing) and fixed a bug in AddRow (rowNew +1).
See attached file.
Is the behavior now as desired?

Edit:
Basically this is the same approach as Yacines or as I described above.
But this involves ShapeSheet technique to prevent calling the macro.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 26, 2024, 07:41:39 PM
@Thomas W: 
QuoteIs the behavior now as desired?
Sorry.  Does not eliminate the multiple firings, nor the addition of extraneous row entries.

Above reply was edited to make more sense.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 27, 2024, 01:38:43 AM
@Yacine:  Sleep well.  Works great.  I copied the core of the OP's code to the "actualRoutine" placeholder, and conn Pts get added or removed as necessary.

Here's the complete solution...

Dim bBusy As Boolean
Dim counter As Long
Dim rejected As Long

Sub ConnPtAdjust(shp As Visio.Shape)
  Dim start As Double
  If bBusy Then
'    Debug.Print "Reject event"
    rejected = rejected + 1
    Exit Sub
  Else
    rejected = 0
    bBusy = True
    start = Timer
    counter = counter + 1
    Debug.Print "Start time: ", start
    While Timer - start < 1
      DoEvents
    Wend
    Debug.Print "Executing now @", Timer, "repetition", counter, "Rejected events", rejected
    actualRoutine shp
    bBusy = False
  End If
End Sub

Sub actualRoutine(shp As Visio.Shape)
    connPtRow = shp.RowCount(visSectionConnectionPts) - 1   ' rownum used in vba formula generation is 0 based
    lastCPYVal = shp.CellsSRC(visSectionConnectionPts, connPtRow, visCnnctY).Result(visInches)

    If lastCPYVal >= 0.875 Then
'        Debug.Print "Add rows"
        rowsToAdd = 1 + Int((lastCPYVal - 0.875) / 0.625)
        rowNew = connPtRow
        ' we add rowsToAdd*2 cuz we add two conn points (left/right side of shape) per elevation

        For i = 1 To rowsToAdd
'            Debug.Print "Adding " & shp.Name & " Point " & rowNew

            ' left side conn point
            rowNew = rowNew + 1
'            Debug.Print "setting data"
            shp.AddRow visSectionConnectionPts, rowNew, visCnnctX
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctX).FormulaForceU = "Connections.X3"
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctY).FormulaForceU = "Connections.Y" & rowNew & "-0.625"
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctDirX).FormulaU = "Connections.DirX[3]"
            ' right side conn point
            rowNew = rowNew + 1
            shp.AddRow visSectionConnectionPts, rowNew, visCnnctX
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctX).FormulaForceU = "Connections.X4"
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctY).FormulaForceU = "Connections.Y" & rowNew
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctDirX).FormulaU = "Connections.DirX[4]"
        Next

    ' need to remove connection points
    ElseIf lastCPYVal < 0.375 Then
        For i = connPtRow To 1 Step -1 ' start removing conn points from last row, decreasing by two (left/right side of shape)
            If shp.CellsSRC(visSectionConnectionPts, i, visCnnctY).Result(visInches) < 0.375 Then
'                Debug.Print "Removing"; shp.Name & " Point " & i & ", " & shp.CellsSRC(visSectionConnectionPts, i, visCnnctY).Result(visInches)
                shp.DeleteRow visSectionConnectionPts, i
            Else
                Exit For
            End If
        Next

    End If
End Sub



Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Yacine on April 27, 2024, 06:14:50 AM
Quote from: Thomas Winkel on April 26, 2024, 06:59:13 PMBasically this is the same approach as Yacines or as I described above.
But this involves ShapeSheet technique to prevent calling the macro.

I do also favor shapesheet solutions over macros. Didn't however get your solution to work.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Thomas Winkel on April 27, 2024, 09:08:51 AM
Agree that the (ShapeSheet only) solution in my first post only works stable if the called code does not trigger more than one event.
But see the demo I provided with PreventFeedbackLoops.vsdm (0 Downloads).
Then replace this cell:
EventXFMod=IF(User.Processing,SETF(GetRef(User.Processing),FALSE),SETF(GetRef(User.Processing),TRUE)+CALLTHIS("DoSomething"))
with:
EventXFMod=CALLTHIS("DoSomething")
And you will see that this results in an endless-loop until it crashes.

MacGyvers code does not crash (but results in unpredictable behavior) because it saturates.
(I.e. comes to a state where no further events are triggered by the code.)

Did you test "tester.vsdm" I attached above? I'm quite sure that this works.
It's the same as your solution.
Only I store bBusy in the shape and not in a public variable.
That allows me to access it in the ShapeSheet before I call the code:
=IF(User.bBusy,"",CALLTHIS("ConnPtAdjust"))

It's been a long time and I cannot remember the exact background.
But I think that the solution with a public variable did not work for me in some situations.
Imagine many shapes trigger the same event at a time (e.g. user copies many shapes at once).
Then each shape requires its own "bBusy" state.
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 27, 2024, 02:31:02 PM
@Thomas W.:  In my previous reply, that was in response to the latest file version you had provided.  This multiple triggering is not due to code instability.  I had no issues with the OP's code in that regards.  The code always came to a normal conclusion...provided that there was no shape corruption.  I'll explain below. 

The multiple triggerings that are experienced are a normal response to using a mouse to drag-resize the shape, whether it be to enlarge or reduce the size.  As the dragging to a new size progresses, Visio will send multiple event signals.  Each of these will re-trigger the code, potentially causing excessive growth.  Occassionally, this causes the row removal portion of the algorithm to fail.  It is an abnormal condition / response.  Generally, though, the code reacts OK.  Unfortunately, there is no shapesheet solution applicable to the goals of the desired task of adding / removing connection point rows in response to height changes, multiple triggers notwithstanding.

Enter Yacine latest code solution.  It allows and waits until the multiple triggers have completed before continuing with the actual row count modifications.  Thus, there is only a single edit sequence applied to the shape based upon the final (and stable) size due to dragging.

Additionally, the OP's code did execute without issue if, for example, a new height value is entered via Size N Position window.  Visio only issues a single event response.  The code executed just fine.

Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 27, 2024, 03:40:55 PM
Quote@VisioGuy: ...'later' happens when Visio.Application.NoEventsPending or  Visio.Application.IsIdle fire off.
Stumbled across your old post...preferred seems to be VisioIsIdle.


Quote@Yacine:  @Chris, I saw the IsIdle property too, but the help said it gets only fired if you are listening to other events. Didn't understand and dropped this path.

@VisioGuy, Yacine:  Despite my curiosity, I've only managed to kill a bunch of cats with no satisfaction of bringing them back.  Alas, I can't get no satisfaction!!! 

I'm trying to understand how the VisioIsIdle event is called and utilized in VBA application.  It would seem like an obvious, alternative solution for this repeated event triggering issue.  But, the mechanics of it's implementation escape me.  I'm getting increasingly dull in my advancing age progression.  As Yacine's solution works well, this is an intellectual conundrum.  Rescue me!  Won't someone please rescue me!?! 

Well, life goes on...
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Yacine on April 27, 2024, 04:46:53 PM
Quote from: wapperdude on April 27, 2024, 03:40:55 PMthis is an intellectual conundrum.  Rescue me!  Won't someone please rescue me!?!
Well, life goes on...

I don't want to rescue you, I'd rather jump in next to you. All this event handling in Visio is so cryptic, with Add and Addadvice, Sink so and so. I am somehow missing a good overview article.
The regular Microsoft help pages are quite poor in this regard.
Has someone seen a good article somewhere?
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 27, 2024, 06:11:09 PM
@Yacine:  For sure!!!  Everything you said is SOOOO true.  Nice to see I'm not alone concerning this. 

Perhaps...to paraphrase a S & G song...Where have you gone VisioGuy? The Forum turns its lonely eyes to you...". 😁😄😄. Potential, patented, major topic development discussing how & why, the ins / outs, and examples regarding this topic of handling repeated event firings.

@VisioGuy:  in your abundant spare time, of course!  😉😊
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Thomas Winkel on April 27, 2024, 09:39:08 PM
@wapperdude:
Ah, I see what you mean, I must be blind :-[
Now I've spend an hour investigating and only get bullshit results that makes no sense.
Anyhow, I still think that all the events come either from the called VBA code and / or from the ShapeSheet formulas that calculate & set the height to fit a grid.
(The latter could be solved either by using the BOUND function, or by setting the new height in the same VBA function.)
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 28, 2024, 12:19:15 AM
Quote from: Thomas Winkel on April 27, 2024, 09:39:08 PMAh, I see what you mean, I must be blind :-[
Oh how I wish I could say I have perfect vision.

Quote from: Thomas Winkel on April 27, 2024, 09:39:08 PMAnyhow, I still think that all the events come either from the called VBA code and / or from the ShapeSheet formulas that calculate & set the height to fit a grid.
I'm quite sure it's not code, barring any unusual problems.  With Yacine's code, it's possible to debug.print each time the code is called, and that's before the OP's code (or any other "actualRoutine") is executed.  I suppose doing Event Monitor ought to verify the repeated calls from the mouse dragging.

I doubt that a bound fcn might eliminate this affect.  The OP already does the equivalent with a SETF formula.  Additionally, I deleted the SETF formula and grid snapping, and encountered increased multiple events.  Finally, placed a traditional, functionally equivalent SETEATREF formula in the height cell itself.  There may be a slight performance improvement, but still saw multiple events.  Seems to be the nature of resizing via mouse drag. The appropriate solution is for Visio to restrain sending any sizing event until after mouse release.  Well, that brings us back to Yacine's approach or possibly VisioIsIdle, which I don't understand, and may be more complicated anyways.

It's possible that the multiple events are related to screen redraw as the dragging takes place.  Just a thought.

Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 28, 2024, 06:29:35 AM
Found the issue.  It is linked to re-drawing...

Go to File>Options>Advanced.  Deselect Enable live dynamics.  That halts shape re-drawing, which halts events associated with dragging. 

Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Thomas Winkel on April 28, 2024, 08:35:28 AM
Quote from: wapperdude on April 28, 2024, 06:29:35 AMDeselect Enable live dynamics
Makes perfect sense because I had live dynamics disabled already.
So unexpected events only occurred sometimes (probably triggered by User.HeightCalc).
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Yacine on April 28, 2024, 10:08:52 AM
Quote from: wapperdude on April 28, 2024, 06:29:35 AMFound the issue.  It is linked to re-drawing...

Go to File>Options>Advanced.  Deselect Enable live dynamics.  That halts shape re-drawing, which halts events associated with dragging. 


Well, yes but no. I mean almost.
live dynamics is on by standard. For a standard solution it would be rather difficult to ask users to disable it.
Maybe the macro could / should disable the function by itself?
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 28, 2024, 03:05:37 PM
@Thomas W:  I've tried repeatedly, and not had failure.

@Yacine:  Yes, default is on, so would require User intervention.  It can be in a macro, entry would be, Application.LiveDynamics = False.  Obviously, need 2nd macro to set back to True.  I did this and created to Action rows with RunMacro.  Works fine.  As for User...well, I think the OP may be the only one doing this, so, minor inconvenience.

Note:  The dynamics must be disabled before the macro is called.  Doing so in the macro is after the fact and too late to do any good.  To facilitate, I call macros from the Actions section in shapesheet.  Thus, just a right click away.

Can you confirm that this solves problem?

The Action rows:
Action.Row_3.Menu -> "_SetLiveDynamics"
Action.Row_4.Action -> RUNMACRO("ThisDocument.DisAbleDyn")+SETF(GetRef(Actions.Row_4.Checked),1)+SETF(GetRef(Actions.Row_5.Checked),0)
Action.Row_4.Menu -> "Disable"

Action.Row_5.Action -> RUNMACRO("ThisDocument.EnAbleDyn")+SETF(GetRef(Actions.Row_4.Checked),0)+SETF(GetRef(Actions.Row_5.Checked),1)
Action.Row_5.Menu -> "Enable" 

Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 28, 2024, 03:19:18 PM
Interesting.  I went all the way back TO OP's original file and made the above changes.  Yes.  There does seem to be an issue with the code. 

@Thomas W:  My apologies.

Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 28, 2024, 04:28:13 PM
OK. Ok. Ok.

This would be a complete solution as I recommend.  It solves the initial problem.  It improves shapesheet syntax issues.  See the attached file...it contains everything.  Also, the code is listed below for quick reference.   It is Yacine's code, with option to bypass the delay if the LiveDynamics is disabled.  This results in faster execution time and doesn't require code editing if LiveDynamics are enabled or disabled.  The actualRoutine omits the Undo stuff, but otherwise does the add / remove connect point rows.

I placed the LiveDynamic code in the ThisDocument code section...because I could...and to easily distinguish it from working code.

The attached file has the both the original shape and edited shape (shapesheet).
  > Page-2 has the updated shape.  Page-1 has original shape.
  > The height and width resizing formulae have been moved from User section, to their respective cells.
  > The formulae use the full, SETATREF functions.
  > The width has added condition to set width to size of text entered.  Thus, long text will fit without wrapping.
  > Added Action entries to allow enable/disable of live dynamics.
 
Note:  if this approach is put to use, I would comment out the debug.print statements in the code.

Module1 code:
Dim bBusy As Boolean
Dim counter As Long
Dim rejected As Long
'
Sub ConnPtAdjust(shp As Visio.Shape)
  Dim start As Double
 

  If bBusy Then
    Debug.Print "Reject event"
    rejected = rejected + 1
    counter = counter + 1

    Exit Sub
  Else
    rejected = 0
    counter = 0
    bBusy = True
    start = Timer
'    counter = counter + 1
    Debug.Print "Start time: ", start
    If Application.LiveDynamics Then
        While Timer - start < 1
          DoEvents
        Wend
    End If
    Debug.Print "Executing now @" & Timer, "repetition", counter, "Rejected events", rejected
    actualRoutine shp
    bBusy = False
  End If
End Sub

Sub actualRoutine(shp As Visio.Shape)
    connPtRow = shp.RowCount(visSectionConnectionPts) - 1   ' rownum used in vba formula generation is 0 based
    lastCPYVal = shp.CellsSRC(visSectionConnectionPts, connPtRow, visCnnctY).Result(visInches)

    If lastCPYVal >= 0.875 Then
'        Debug.Print "Add rows"
        rowsToAdd = 1 + Int((lastCPYVal - 0.875) / 0.625)
        rowNew = connPtRow
        rowsToAdd = 1 + Int((lastCPYVal - 0.875) / 0.625)
        ' we add rowsToAdd*2 cuz we add two conn points (left/right side of shape) per elevation

        For i = 1 To rowsToAdd
'            Debug.Print "Adding " & shp.Name & " Point " & rowNew

            ' left side conn point
            rowNew = rowNew + 1
'            Debug.Print "setting data"
            shp.AddRow visSectionConnectionPts, rowNew, visCnnctX
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctX).FormulaForceU = "Connections.X3"
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctY).FormulaForceU = "Connections.Y" & rowNew & "-0.625"
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctDirX).FormulaU = "Connections.DirX[3]"
            ' right side conn point
            rowNew = rowNew + 1
            shp.AddRow visSectionConnectionPts, rowNew, visCnnctX
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctX).FormulaForceU = "Connections.X4"
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctY).FormulaForceU = "Connections.Y" & rowNew
            shp.CellsSRC(visSectionConnectionPts, rowNew, visCnnctDirX).FormulaU = "Connections.DirX[4]"
        Next

    ' need to remove connection points
    ElseIf lastCPYVal < 0.375 Then
        For i = connPtRow To 1 Step -1 ' start removing conn points from last row, decreasing by two (left/right side of shape)
            If shp.CellsSRC(visSectionConnectionPts, i, visCnnctY).Result(visInches) < 0.375 Then
'                Debug.Print "Removing"; shp.Name & " Point " & i & ", " & shp.CellsSRC(visSectionConnectionPts, i, visCnnctY).Result(visInches)
                shp.DeleteRow visSectionConnectionPts, i
            Else
                Exit For
            End If
        Next

    End If
End Sub

ThisDocument code:
Sub DisAbleDyn()
    Application.LiveDynamics = False
    Debug.Print "FALSE"
End Sub
Sub EnAbleDyn()
    Application.LiveDynamics = True
    Debug.Print "TRUE"
End Sub
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Yacine on April 28, 2024, 06:48:19 PM
if not bWapperdudeBusy then
  exploreVisioEvents
elif not bChildrenBusy
  BBQ
elif bWheatherFine
  go_hiking
else
  for i = 1 to todo_list.count
    if todo_list(i).bInTheMoodForTheTask then
      todo_list(i).finishTheFormidableJob
    endif
  next i
endif
 
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: wapperdude on April 28, 2024, 06:58:24 PM
😂😂😂. My side's hurt.   Off to do other things.... 8)
Title: Re: SETATREF(Height) / EventXFMod Behavior
Post by: Thomas Winkel on April 29, 2024, 06:03:45 PM
😂😂😂

Be careful of handling Wapperdude_FormidableJob_Finished() event.
Errors could lead to unpredictable behavior.

Today I tried again some approaches and always got inconsistent results...
Time to put Visio aside for a few days and then start again with a blank drawing ;D