VBA program stops to refresh the worksheet - vba

I'm making my own Conway's Game of Life on VBA where the current state is displayed on a worksheet.
Because I'm not skilled, the implementation is probably not very efficient (I use 2 boolean matrices to model the current state and the next one).
To display the result at each step, I've sub display() that took the matrix_currentand color each cell in black or white. To make the whole process smoother, I've wrapped Application.ScreenUpdating = Falseand Application.ScreenUpdating = True . Short story long, it looks like that :
Private Sub display()
Application.ScreenUpdating = False
For i = 0 To sizeGrid
For j = 0 To sizeGrid
If matrix_curr(i, j) Then
Cells(i + xmin, j + ymin).Interior.ColorIndex = 1
Else
Cells(i + xmin, j + ymin).Interior.ColorIndex = 2
End If
Next
Next
Application.ScreenUpdating = True
End Sub
Before each Call display() I call the method Sleep() to let enought time to watch each step.
So, here is my issue:
The display on the worksheet often stops after a number of steps. However, the programm is still running and finally shows the last state. So basically, I can monitor the beginning, then nothing change until the last step that are displayed.
Everything happen as if the worksheet suddenly stop to be refreshed.
Do you have any idea to solve this issue.
I thank you in advance for your help (and hope that I make myself understood
despite my poor english)

My problem is that after a number of steps, nothing more happen on the screen (as if it was freeze).
That's because Excel is essentially running out of breath - it's basically not keeping up with all the ScreenUpdating toggles.
When you toggle Application.ScreenUpdating back on once, Excel happily responds by repainting itself.
When you're running a busy loop, it's prioritizing execution of the VBA code and the Excel UI goes:
(not responding)
This is normal: there's a lot of things to process, so it's processing them - updating the UI, raising worksheet events, responding to user actions, calculating cells, all these things "drop priority", until the VBA code completes.
Try adding a DoEvents instruction immediately after toggling Application.ScreenUpdating back on; this explicitly tells Excel "okay, go ahead, process whatever other stuff you've got, then come back here when you're ready". I'd warmly recommend leaving Application.EnableEvents off and Application.Calculation set to xlCalculationManual until the code completely executed.

Related

Excel VBA: Animating Visibility of a Range w/ RowHeight loop

I am interested in showing/hiding several ranges on my workbook. Normally I would just test whether or not the range is already hidden and set the following to either true or false rng.EntireRow.Hidden.
I would like to make my project feel more like an app (yes I know excel probably isn't the best place to go with it, but attention to small details like this is my kind of thing). The following is an example of what I am trying to do. It works, especially on a clean worksheet/workbook. The problem is that on the workbook in which I am trying to use it, there is already a ton of data/formatting/shapes on the worksheet. This is causing "skips" in the smoothness of the loop. I have tried different step by's, but nothing really seems to solve it. The DoEvents was necessary in order to see any animation at all.
If anyone has an idea on how to make this work, or if it's at all possible, that would be great. Thanks!
Sub testView()
Dim rng As Range
Dim i As Integer
With ActiveSheet
Set rng = .Range(.Cells(1, 1), .Cells(20, 1))
If rng.EntireRow.Hidden = True Then
For i = 1 To 15 Step 1
rng.EntireRow.RowHeight = i
DoEvents
Next i
Else
For i = 14 To 0 Step -1
rng.EntireRow.RowHeight = i
DoEvents
Next i
End If
End With
End Sub
I do a lot of animations in Excel for pedagogical reasons (mostly animations of charts). I sometimes use variations of the following sub:
Sub Pause(delay As Double)
Dim start As Double
start = Timer
Do While Timer < start + delay
DoEvents
Loop
End Sub
Then in the main code, have something like Pause 0.10 after (or instead of) where you currently have DoEvents. Low tech, but it sometimes helps.

VBA stopping without code telling it to do so

Pretty much the title. The code goes forward until it hits a line, and then acts as though it ran into a Stop command, except there is no such line.
StartDate = DateAdd("d", -1 * NDays + 1, EndDate) 'the immediately preceding line
'NDays is an integer, EndDate is a date
With Excel.Application 'the line that it stops on
.ScreenUpdating = True
.DisplayAlerts = True
.Calculation = xlAutomatic
End With 'I put these here because the next lines save the workbook
'if I put them before the excel.application stuff it asks if I want to save when closing
Why is it stopping on that second line? Does anybody know?
Try it without the with block and see what happens. So something like:
Application.Screenupdating = True
Application.DisplayAlerts = False
Application.Calculation = xlCalculationAutomatic
I am at a loss for the why behind this (and if anyone knows, please do share), but I have encountered issues with instancing new Applications, and as a result the code exhibits the same behavior where it goes to use the new instance and simply shuts off.
If I had to hazard a guess, I would assume it has something to do with how Excel is managing the VBA processes. It is possible (though I could be entirely mistaken) that the new Application process assumes control, and that this causes the first application to (in layman's terms) assume it is finished, and simply quit. That, or it pauses its own process (like a DoEvents command) but can't resume. Again, these are guesses.
Also, why the 'Excel.Application'? Are you creating a new instance called Excel? If you intend to just use the application the code is running in just us 'Application'.

Excel running slowly when Excel the active window

I couldn't find the answer to this issue anywhere, so I do hope you guys can help me. My excel macro goes through a couple iterations of data. It autofilters a source file, takes out information, works with the data, and does so again for about 50 times - once per person. Here's some code of what I mean, all the individual submethods work just fine and are pretty damn fast:
For j = 1 To names.Count
'filter the source by name, generate sheet
FilterName names(j)
'prepare data with the necessary dates
FillMasterDates dates(), j
Dim i As Long
Dim ending As Long
ending = Sheets("Daten").Rows.End(xlDown).Row
Dim cellvalue As String
'check dates, etc
For i = 1 To ending
cellvalue = Sheets("Daten").Cells(i, 1)
If cellvalue = "" Then
Exit For
End If
ColorCell (i)
FilterDate CStr(dates(i)), names(j)
Next i
'user data has been successfully gathered, copy over to final sheet
FillColumns j
Next j
The whole code takes about 4~ seconds to run (given that I have about 2000 rows and I create a new sheet for 50~ people), which is fine. The baffling thing is that when Excel stays my active window despite using Application.ScreenUpdating = False (earlier in the macro, but still active at this point), the necessary time to run the macro goes up to a staggering 25~ seconds. Same input, same output. So to put it simply - run macro, tab out of excel - macro needs about 4-5 seconds to run. run macro but stay in excel and wait - 25 seconds.
I've tried Application.WindowState = Application.WindowState, ActiveWindow.SmallScroll, DoEvents, Application.CalculateFull(). I tried different calculation settings, but I do not really use any of the formula calculations innate to Excel - I have to use Excel as an interface because the source file is an *.xls file and the final output has to remain in this format.
If you need me to provide more code snippets to make sense of it, ask away. I've been stumped for a good two days now.
You could always try a couple more lines to disable the calculations and alerts etc.
Application.ScreenUpdating = false
Application.Calculations = xlManual
Application.DisplayAlerts = False
However if you really want to bypass all the background nonsense excel seems to go through dont access the sheet directly through a loop, this concept maybe tricky if your not used to it but its worth every bit, and will speed up your code so fast you will wonder why you never did it in the first place.
I dont have your code so ill just give an example of how it works
Dim RangeArray as Variant 'This will store your range as a values array
RangeArray = Sheet1.Range("A1:G100000").Value 'this will put the entire ranges values into the array
If Not IsArray(RangeArray) Then ExitSub 'If your range is only 1 cell it will not create an array so be careful, handle this as needed
'This Array always starts lowerbound 1, RangeArray(1,1) = First Cell
Now with this you can loop through your data and manipulate and modify the array just like you would with a cell or a range except there is no overhead, its just values and not objects .
Once you have done what you need all you need to do then is put the values back into the sheets range
Sheet1.Range("A1:G100000").value = RangeArray
And thats it, very simple and very effective, and this transfer from array to range is immediate no matter how big it is.
Just let me know if this helps
Thanks
Paul S
---------------NEW MESSAGE-------------------
You could try something which maybe a little excessive and risky, if your only getting this problem while the window is active and displayed how about making it invisible, the problem is if your code fails and you fail to trap an error it will remain invisible until you goto taskmanager and close it there.
Application.Visible = false
This should deactivate the window too (although i have never tested that)
this should simulate you hiding the window and just bring it back when your code has finished..
---------------NEW MESSAGE-------------------
Application.Windowstate = xlMinimized
This should do the trick :D, should have mentioned this first haha
I also just saw that you tried something similar, but the code is incorrect there, try this one

VBA: To calculate the worksheet in background, while message userform is active

I wrote a loop procedure in vba, which pastes a lot of data each time to the new worksheet. Actually it pastes the formulas that get calculated. It takes excel approximately 40 seconds to get all calculations done. Unfortunately the next loop does not wait 40 seconds and fills with the data the next sheet. It takes a lot of resources. To make a loop to wait a little bit, but still to perform calculations I used userform, which appears for 40 seconds, than it will be unloaded and is used in the next loop. The purpose of the userform is to allow the calculations to get done before the calculations in the next sheet begin. This strategy has a drawback, since when the useform is active, the calculations in the background freeze. One can change the options of the useform to showmodal false, but then I cannot upload and unload it each time as new loop begins. Besides I am not sure weather the formulas a still calculated in the inactive sheet. I have to mention that the formulas in the sheet each time activate an excel add-in and I cannot make an add in to wait with calculations, even if the option manual calculations is turned on.
If anybody knows how to postpone the loop but not to make complete excel application wait (Application.wait or ontime methods do not work) I will appreciate the help a lot. I tried also to active and deactivate events, switch to manual calculation and back. Also this does not help and all data a calculated at once.
The method described in the other post did not worked for me and all formulas are still calculated at the same time:
Application.Calculate
If Not Application.CalculationState = xlDone Then
DoEvents
End If
My original code that copies formulas to the new worksheet:
For raw_i = 1 To 3
Set o = GetObject("d:\formulas.xlsx")
Set Sheet_i = Worksheets.Add(after:=Worksheets(Worksheets.Count))
Sheet_i.Cells(1, 1).Formula = o.Worksheets("Sheet1").Cells(raw_i, 1).Formula
Set o = Nothing
LoadForm
next raw_i
VBA doesn't support multiple process threads - there is one execution route and if you pause it, then you pause the whole execution. It's all or nothing.
Best hope you've got is a While Loop:
While Application.CalculationState <> xlDone
DoEvents
Wend
Which will loop until calculations have finished.
In response to your most recent edit:
Try changing the main loop to:
For raw_i = 1 To 3
Set o = GetObject("d:\formulas.xlsx")
Set Sheet_i = Worksheets.Add(after:=Worksheets(Worksheets.Count))
Sheet_i.Cells(1, 1).Formula = o.Worksheets("Sheet1").Cells(raw_i, 1).Formula
Sheet_i.Calculate
DoEvents
Set o = Nothing
Next

VBA While Loop freezing data uplink, need to run Sub once a second

I'm needing to run a sub once a second while also receiving data from a feed. The function looks at the data in the cells, determines if conditions are right, and if so sends a command to the trade server (where my data feed is coming in). This issue is once I run the loop, the While Loop freezes my cells in excel, making the program execute without updating.
Dim timeremaining As Integer
timeremaining = Range("E7").Value
Application.Calculation = xlCalculationAutomatic
Do While timeremaining > 5
Endowment
Sleep 1000
Loop
I've tried the setting a timer (OnTime) approach, and creating a function to run it a set number of times, yet both functions freeze my data feed.
Thank you.
Try using the wait method in VBA
For example:
Application.Wait(Now + TimeValue("0:00:10"))