VBA Slowdown after using Shape.Nodes.SetPosition repeatedly on the nodes of msoFreeform

zyxel

New Member
Joined
Dec 15, 2020
Messages
7
Office Version
  1. 2007
Platform
  1. Windows
MS-Excel v11.8169.8172 SP3 progressively slows down VBA Slowdown after using Shape.Nodes.SetPosition repeatedly on the nodes of msoFreeform shape objects. Why and what can I do about it ?

The code responsible for invoking Shape.Nodes.SetPosition repeatedly is listed below. Note that this code does NOT create any new shape objects (that is done in another function but only once).

VBA Code:
Private Sub Animate(shp As Shape, ByVal steps As Integer, ByRef GapNodesArray() As GAPNODES)
    Dim r As Double
    Dim tt As Double
    Dim xx As Double
    Dim x, y, d, xd, yd, t As Double
    Dim rx, ry, rd, rxd, ryd, rt As Double
    Dim xL, xR As Double
    Dim yc As Double
    Dim ymin, ymax As Single
    Dim i As Integer
        
    r = shp.Nodes(4).Points(1, 2) - shp.Nodes(1).Points(1, 2)
    
    tt = r / 1.8
    t = tt
    
    yc = shp.Nodes(1).Points(1, 2)
    

    For xx = 0.0001 * r To 0.9999 Step (0.9999 / steps)
        x = r * (xx ^ 4) 'the exponent affect the animation speed variation profile
        rx = r - x
        
        y = Sqr(r ^ 2 - rx ^ 2)
        d = (rx / r) / (Sqr(1 - (rx / r) ^ 2))
        xd = Sqr(t ^ 2 / (1 + d ^ 2))
        yd = Sqr(t ^ 2 / (1 + (1 / (d ^ 2))))
        
        ry = Sqr(r ^ 2 - x ^ 2)
        rd = (x / r) / (Sqr(1 - (x / r) ^ 2))
        rxd = Sqr(rt ^ 2 / (1 + rd ^ 2))
        ryd = Sqr(rt ^ 2 / (1 + (1 / (rd ^ 2))))
        
        Application.ScreenUpdating = False

        For i = LBound(GapNodesArray) To UBound(GapNodesArray)
        
            xL = GapNodesArray(i).xL
            xR = GapNodesArray(i).xR
            
            If GapNodesArray(i).Dir Then
                shp.Nodes.SetPosition GapNodesArray(i).BL, xL, yc + y  '7
                shp.Nodes.SetPosition GapNodesArray(i).BR, xR, yc + y  '10
                shp.Nodes.SetPosition GapNodesArray(i).TL, xL, yc - y   '61
                shp.Nodes.SetPosition GapNodesArray(i).TR, xR, yc - y   '58
                
                shp.Nodes.SetPosition GapNodesArray(i).BL - 1, xL - xd, yc + y + yd
                shp.Nodes.SetPosition GapNodesArray(i).BR + 1, xR + xd, yc + y + yd
                shp.Nodes.SetPosition GapNodesArray(i).TL + 1, xL - xd, yc - y - yd
                shp.Nodes.SetPosition GapNodesArray(i).TR - 1, xR + xd, yc - y - yd
                
                If yd > y Then yd = y
                shp.Nodes.SetPosition GapNodesArray(i).BL + 1, xL + xd, yc + y - yd
                shp.Nodes.SetPosition GapNodesArray(i).BR - 1, xR - xd, yc + y - yd
                shp.Nodes.SetPosition GapNodesArray(i).TL - 1, xL + xd, yc - y + yd
                shp.Nodes.SetPosition GapNodesArray(i).TR + 1, xR - xd, yc - y + yd
            Else
                shp.Nodes.SetPosition GapNodesArray(i).BL, xL, yc + ry
                shp.Nodes.SetPosition GapNodesArray(i).BR, xR, yc + ry
                shp.Nodes.SetPosition GapNodesArray(i).TL, xL, yc - ry
                shp.Nodes.SetPosition GapNodesArray(i).TR, xR, yc - ry
                
                shp.Nodes.SetPosition GapNodesArray(i).BL - 1, xL - rxd, yc + ry + ryd
                shp.Nodes.SetPosition GapNodesArray(i).BR + 1, xR + rxd, yc + ry + ryd
                shp.Nodes.SetPosition GapNodesArray(i).TL + 1, xL - rxd, yc - ry - ryd
                shp.Nodes.SetPosition GapNodesArray(i).TR - 1, xR + rxd, yc - ry - ryd
                
                If ryd > ry Then ryd = ry
                shp.Nodes.SetPosition GapNodesArray(i).BL + 1, xL + rxd, yc + ry - ryd
                shp.Nodes.SetPosition GapNodesArray(i).BR - 1, xR - rxd, yc + ry - ryd
                shp.Nodes.SetPosition GapNodesArray(i).TL - 1, xL + rxd, yc - ry + ryd
                shp.Nodes.SetPosition GapNodesArray(i).TR + 1, xR - rxd, yc - ry + ryd
            End If
        Next i
        
        Application.ScreenUpdating = True
        
        t = tt * (rx / r)
        rt = tt * (x / r)
    Next xx
    
    ymin = shp.Nodes(shp.Nodes.Count - 2).Points(1, 2)
    ymax = shp.Nodes(4).Points(1, 2)
    
    Application.ScreenUpdating = False
        
    For i = LBound(GapNodesArray) To UBound(GapNodesArray)  'Do the last iteration to avoid divisions by zero and firmly set the vertical coordinate to ymin, yc, ymax
         xL = GapNodesArray(i).xL
         xR = GapNodesArray(i).xR

        If GapNodesArray(i).Dir Then
            shp.Nodes.SetPosition GapNodesArray(i).BL, xL, ymax
            shp.Nodes.SetPosition GapNodesArray(i).BR, xR, ymax
            shp.Nodes.SetPosition GapNodesArray(i).TL, xL, ymin
            shp.Nodes.SetPosition GapNodesArray(i).TR, xR, ymin
            
            shp.Nodes.SetPosition GapNodesArray(i).BL - 1, xL, ymax
            shp.Nodes.SetPosition GapNodesArray(i).BR + 1, xR, ymax
            shp.Nodes.SetPosition GapNodesArray(i).TL + 1, xL, ymin
            shp.Nodes.SetPosition GapNodesArray(i).TR - 1, xR, ymin
            
            shp.Nodes.SetPosition GapNodesArray(i).BL + 1, xL, ymax
            shp.Nodes.SetPosition GapNodesArray(i).BR - 1, xR, ymax
            shp.Nodes.SetPosition GapNodesArray(i).TL - 1, xL, ymin
            shp.Nodes.SetPosition GapNodesArray(i).TR + 1, xR, ymin
        Else
            shp.Nodes.SetPosition GapNodesArray(i).BL, xL, yc
            shp.Nodes.SetPosition GapNodesArray(i).BR, xR, yc
            shp.Nodes.SetPosition GapNodesArray(i).TL, xL, yc
            shp.Nodes.SetPosition GapNodesArray(i).TR, xR, yc
            
            shp.Nodes.SetPosition GapNodesArray(i).BL - 1, xL, yc + tt
            shp.Nodes.SetPosition GapNodesArray(i).BR + 1, xR, yc + tt
            shp.Nodes.SetPosition GapNodesArray(i).TL + 1, xL, yc - tt
            shp.Nodes.SetPosition GapNodesArray(i).TR - 1, xR, yc - tt
            
            shp.Nodes.SetPosition GapNodesArray(i).BL + 1, xL, yc
            shp.Nodes.SetPosition GapNodesArray(i).BR - 1, xR, yc
            shp.Nodes.SetPosition GapNodesArray(i).TL - 1, xL, yc
            shp.Nodes.SetPosition GapNodesArray(i).TR + 1, xR, yc
        End If
    Next i
    
    Application.ScreenUpdating = True
    
End Sub

Here is a link to the entire MS-Excel workbook with the complete VBA code.
http://ploxis.com/Bubbles.xls

When you open it, change the number in the RED cell from 0 to 1 ...and observe as that VBA code creates 34 msoFreeform shape objects and manipulates their nodes.
Note, that each subsequent invocation of the Bubbles() UDF runs slower and slower.

After it finishes updating the 34 msoFreeform shape objects, change the RED cell back to 0 and observe the update again (note that NO NEW shape objects are created the second time).
Note, that it is slower and slower...
 

Excel Facts

Add Bullets to Range
Select range. Press Ctrl+1. On Number tab, choose Custom. Type Alt+7 then space then @ sign (using 7 on numeric keypad)
If you enter 1 and 0 into the RED cell several times, then the slowdown will become more pronounced ...as if it accumulates.

P.S.
Could anyone with the editing privileges delete the two words "VBA Slowdown" from the first sentence of my Original Post. I made a mistake when pasting and now I cannot correct it... arrrghhh
 
Upvote 0

Forum statistics

Threads
1,215,563
Messages
6,125,568
Members
449,237
Latest member
Chase S

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top