This is a weird one.
I have a macro which is taking a surprisingly long time to accomplish fairly simple tasks. Furthermore, each time I run it, even though it is running on the same data, it takes longer.
The workbook has several sheets but the two relevant ones are "Kids Cascade" and "KCtext". On "Kids Cascade" there is a diagram consisting of text boxes linked by connectors.
The macro:
1 creates a list of which connectors lead into and out of each shape
2 finds the "top" shape - i.e. the one with no input connectors
3 tracks down through each shape's connectors to the next shape
recursively to create a complete list of each shape name in order
4 clears the existing data on KCtext sheet
5 copies the text from each box, in tree order onto the KC sheet, such that the column number into which the text is written is equal to the number of "branches" that shape is down from the top
6 creates a hyperlink from each cell thus written back to the topleft cell of the shape from which the cell text came
7 creates a hyperlink from each shape to the cell in KCtext which has that shape's text
8 uses the group and outline feature to recursively group the tree "branches" on KCtext.
Starting with a freshly loaded workbook, that process took 44s when there were 389 shapes on the Kids Cascade sheet. I then ran the macro again, and it took 55s. Subsequent run times, in seconds, were:
61
72
82
92
103
97 *1
127
130
141
151
161
172
158 *2
163
172
At this point I lost the will to live.
*1 between this run and the previous one I manually deleted all the cells on KCtext.
*2 between this run and the previous one I changed the code to clear KCtext from a version where I delete the UsedRange to one where I delete all the cells.
I put some timer code in there to see how long the various bits were taking. The two slow parts are:
a writing the text on KCtext sheet and creating the hyperlinks
b creating the group outline hierarchy.
These two parts take very nearly the same length of time and grow in time at the same rate.
The rest (creating the connector list etc) is practically instantaneous.
I've tried running it both with the code window open and closed. This seems to make little or no difference. I've also tried calling the macro in different ways:
from the workbook menu (tools, macros...)
from a button I put on the Kids Cascade sheet
using a keyboard shortcut assigned to the macro
pressing F5 from the code window
using the IDE menu (run...)
None of these methods make an appreciable difference to the running time.
Here is the code for the macro:
Here is the code for CreateGroupHierarchy
If anyone can suggest why:
it is taking so long in the first place
or
why it seems to be taking longer every time I run it
I will be very grateful This is driving me absolutely nuts.
Tony
I have a macro which is taking a surprisingly long time to accomplish fairly simple tasks. Furthermore, each time I run it, even though it is running on the same data, it takes longer.
The workbook has several sheets but the two relevant ones are "Kids Cascade" and "KCtext". On "Kids Cascade" there is a diagram consisting of text boxes linked by connectors.
The macro:
1 creates a list of which connectors lead into and out of each shape
2 finds the "top" shape - i.e. the one with no input connectors
3 tracks down through each shape's connectors to the next shape
recursively to create a complete list of each shape name in order
4 clears the existing data on KCtext sheet
5 copies the text from each box, in tree order onto the KC sheet, such that the column number into which the text is written is equal to the number of "branches" that shape is down from the top
6 creates a hyperlink from each cell thus written back to the topleft cell of the shape from which the cell text came
7 creates a hyperlink from each shape to the cell in KCtext which has that shape's text
8 uses the group and outline feature to recursively group the tree "branches" on KCtext.
Starting with a freshly loaded workbook, that process took 44s when there were 389 shapes on the Kids Cascade sheet. I then ran the macro again, and it took 55s. Subsequent run times, in seconds, were:
61
72
82
92
103
97 *1
127
130
141
151
161
172
158 *2
163
172
At this point I lost the will to live.
*1 between this run and the previous one I manually deleted all the cells on KCtext.
*2 between this run and the previous one I changed the code to clear KCtext from a version where I delete the UsedRange to one where I delete all the cells.
I put some timer code in there to see how long the various bits were taking. The two slow parts are:
a writing the text on KCtext sheet and creating the hyperlinks
b creating the group outline hierarchy.
These two parts take very nearly the same length of time and grow in time at the same rate.
The rest (creating the connector list etc) is practically instantaneous.
I've tried running it both with the code window open and closed. This seems to make little or no difference. I've also tried calling the macro in different ways:
from the workbook menu (tools, macros...)
from a button I put on the Kids Cascade sheet
using a keyboard shortcut assigned to the macro
pressing F5 from the code window
using the IDE menu (run...)
None of these methods make an appreciable difference to the running time.
Here is the code for the macro:
Code:
Sub Create_KC_text()
On Error Resume Next
Application.ScreenUpdating = False
Dim i As Long, shpcount As Long
Dim now As Single, start As Single
Dim report As String
now = Timer()
start = now
CreateConnectorList
report = "made connector list in " & Format(Timer() - now, "0.00") & "s"
now = Timer()
shpcount = shpconlist.Count
For i = 1 To shpcount
If shpconlist.Item(i).up.Count = 0 And shpconlist.Item(i).down.Count > 0 Then
Worksheets("Kids Cascade").Shapes(shpconlist.Item(i).name).Select
Exit For
End If
Next i
report = report & vbCrLf & "found top of tree in " & Format(Timer() - now, "0.00") & "s"
now = Timer()
Dim shp As Shape
Dim r As Long, c As Long, numshapes As Long
r = 1
c = 1
numshapes = ActiveSheet.Shapes.Count
ReDim namelist(1 To numshapes) As Variant
ReDim MyNames(1 To numshapes) As Variant
For Each shp In Selection.ShapeRange
Get_Leg shp, c
If Err.Number <> 0 Then Err.Clear
Next shp
ReDim Preserve MyNames(1 To namecount) As Variant
ReDim Preserve namelist(1 To namecount) As Variant
Dim maxcol As Long
report = report & vbCrLf & "created name lists in " & Format(Timer() - now, "0.00") & "s"
now = Timer()
Dim op_r As Long, txtlen As Long
Dim txt As String
Dim cascadesheet As Worksheet, textsheet As Worksheet
Set cascadesheet = Worksheets("Kids Cascade")
Set textsheet = Worksheets("KC_Text")
Dim colr As Long
cascadesheet.Hyperlinks.Delete
report = report & vbCrLf & "deleted cascade HLs in " & Format(Timer() - now, "0.00") & "s"
now = Timer()
With textsheet
.Cells.Delete Shift:=xlUp
report = report & vbCrLf & "deleted kctext cells in " & Format(Timer() - now, "0.00") & "s"
now = Timer()
.Hyperlinks.Delete
report = report & vbCrLf & "deleted kctext HLs in " & Format(Timer() - now, "0.00") & "s"
now = Timer()
For r = 1 To namecount
txt = ""
Set shp = cascadesheet.Shapes(namelist(r)(0))
With shp
If .connector = False Then
' If .AlternativeText = "" Then
' If Err.Number <> 0 Then Err.Clear
' Else
op_r = op_r + 1
txt = .AlternativeText
txt = Mid(txt, 10, Len(txt) - 9)
colr = shp.DrawingObject.Interior.Color
' End If
End If
End With
If txt <> "" Then
.Cells(op_r, namelist(r)(2)) = txt
.Cells(op_r, namelist(r)(2)).Interior.Color = colr
.Hyperlinks.Add _
Anchor:=.Cells(op_r, namelist(r)(2)), _
Address:="", _
SubAddress:="'Kids Cascade'!" & cascadesheet.Shapes(namelist(r)(0)).TopLeftCell.Address, _
TextToDisplay:=txt
cascadesheet.Hyperlinks.Add _
Anchor:=cascadesheet.Shapes(namelist(r)(0)), _
Address:="", _
SubAddress:="KC_Text!" & .Cells(op_r, namelist(r)(2)).Address
End If
Next r
report = report & vbCrLf & "wrote KC_text and created hyperlinks in " & Format(Timer() - now, "0.00") & "s"
now = Timer()
With .UsedRange
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
.ColumnWidth = 1.71
End With
AddIndexColumn
End With
CreateGroupHierarchy textsheet, 1, 1
report = report & vbCrLf & "created group hierarchy in " & Format(Timer() - now, "0.00") & "s"
now = Timer()
Err.Clear
Application.ScreenUpdating = True
'debug
report = report & vbCrLf & "total time taken " & Format(Timer() - start, "0.00") & "s"
report = report & vbCrLf & "Number of shapes = " & Format(numshapes, "###")
report = report & vbCrLf & "Name Count = " & Format(namecount, "###")
namecount = 0
Set shpconlist = Nothing
Set textsheet = Nothing
Set cascadesheet = Nothing
Set shp = Nothing
MsgBox report, vbOKOnly, "Timings"
End Sub
Here is the code for CreateGroupHierarchy
Code:
Public Sub CreateGroupHierarchy(wksht As Worksheet, _
indexcol As Long, _
startrow As Long)
'This sub uses the excel inbuilt group and outline process to display the data on the KC_text sheet
Dim maxrow As Long, lastrow As Long, startval As Long
Dim r As Long, i As Long, j As Long
Dim maxindex As Long
Dim ingroup As Boolean
With wksht
.Cells.ClearOutline
maxrow = .UsedRange.Rows.Count
startval = .Cells(startrow, indexcol)
For r = startrow To maxrow
If .Cells(r, indexcol) > maxindex Then
maxindex = .Cells(r, indexcol)
End If
Next r
For i = maxindex To startval + 1 Step -1
ingroup = False
For r = startrow To maxrow
If .Cells(r, indexcol) = i Then
If Not ingroup Then
ingroup = True
grouprowstart = r
End If
Else
If .Cells(r, indexcol) < i And ingroup Then
.Rows(Trim(Str(grouprowstart)) & ":" & Trim(Str(r - 1))).Group
ingroup = False
End If
End If
Next r
If ingroup Then
.Rows(Trim(Str(grouprowstart)) & ":" & Trim(Str(maxrow))).Group
End If
Next i
End With
End Sub
If anyone can suggest why:
it is taking so long in the first place
or
why it seems to be taking longer every time I run it
I will be very grateful This is driving me absolutely nuts.
Tony