I created an Excel sheet with a VBA macro. The data written is read from a binary file. From this binary file, I consider every x byte represents a frame. A frame is written on a row, with a header.
First issue : As I write those data, there is a noticeable performance leak over time : the first 250 frames are done under a minute, then the next 150 take one minute. Overall, at the beginning of the process, ~10 frames are done in 1 second. After a few hundreds of frames, it takes more than a second to process 1 frame. Time is measured by hand, according to a progress bar.
Second issue :
I have a Worksheet_SelectionChange
event on the sheet that calls Cells(row, 1).EntireRow.Hidden
setting it to True
or False
depending on the situation. After some debugger inspection, I have realized those instructions take an increasing amount of time depending on the amount of data written during the session. Example, it takes a good 10 seconds with ~400 frames.
Now the part that makes me think there is room for improvement :
If I save the file, close it, reopen it, and change the selection, Cells(row, 1).EntireRow.Hidden
takes an insignificant amount of time. I'd even say, the expected amount of time.
If I only save the file and keep it open, there is no noticeable change.
What's I've tried : In order to improve performances, at the beginning of the main sub, I call :
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.AskToUpdateLinks = False
Application.DisplayAlerts = False
Application.Calculation = xlcalculationmanual
ThisWorkbook.Date1904 = False
ActiveWindow.View = xlNormalView
(and swap them back to their original values at the end)
I already avoid as much as possible the use of Select
and Activate
.
I also avoid arrays, using Collections instead, since I've read its faster.
I use the With
statement whenever necessary.
I make sure the Worksheet_SelectionChange
is disabled before writing into the file.
I believe both issues are related, but I do not understand what is the cause or how I can solve it. What am I doing wrong ?
EDIT:
Using Application.SaveWorkspace
every 100 frames does the job : it pauses the process (visibly thanks to the progress bar) for ~2 seconds but the amount of time saved to process the next 100 frames is entirely compensated.
I think that my problem is solved now, unless there is a cleaner way to do that. Thanks a lot to all of you in comments !
EDIT 2 :
Problem solved : I was adding comments to some cells, using selectedCell.Comment.Shape.TextFrame.AutoSize = True
every time like so :
With sheet.Cells(row, column)
.AddComment txt
.Comment.Shape.TextFrame.AutoSize = True
End With
The goal being to make them look pretty. For some reasons, this is what was slowing down the whole process each time it was called.
Instead, I now call the following snippet at the very end. For the information, 100 frames are now processed in under 10s, and the process time is constant. For ~400 frames, the following snippet took 16s (approx).
Dim comment As Comment
For Each comment In sheet.Comments
comment.Shape.TextFrame.AutoSize = True
Next comment