Question

everyone. I have a large VBA module in an Excel workbook that takes data from a bunch of other, remote workbooks and copies it into the current workbook. Then, it formats and analyzes the data. All of that is working fine, except it can take a while, since I'm dealing with over 30,000 lines of data in two worksheets (and growing every day).

So, I'm trying to get it to put the progress as a percent in a certain cell on the "Admin" worksheet. This also seems to work OK, but only sometimes. During execution, Excel—seemingly at random—skips the .Value lines of code that update the progress. Sometimes, it updates about three-quarters of the time, other times, it doesn't update at all until the end of execution. Does anyone know why? Below is a summary of the relevant code.

<some code that declares variables and whatnot>
ThisWorkbook.Worksheets("Admin").Range("H18").Value = "Waiting..."
For Each rw In rng.Rows
    <code that does the data-gathering and analysis>
    progress = <code that returns a Double value>
    ThisWorkbook.Worksheets("Admin").Range("H18").Value = progress & "% complete."
Next rw
ThisWorkbook.Worksheets("Admin").Range("H18").Value = "Done!"
<some cleanup code>

Sometimes, "Waiting..." is never displayed. Other times, it is. "Done!" is almost always displayed at the end of execution, but Admin!H18 is not updated for many, many of the loops, and it's never the same set of loops when it's skipped. The calculation is still being done for progress (I think), because when it does update, it's updating to the correct value. But it's not updating the cell during every loop, just some of them.

Was it helpful?

Solution

Adding DoEvents after updating the cell may fix this problem. However, your code may run much faster if you disable ScreenUpdating (which would prevent your status updates from updating on the sheet). Try updating the statusbar instead.

Also - splitting out your Status updates into a separate Sub will simplify your code and allow you to more easily change how you display the updates.

Sub DoStatus(m)
    ThisWorkbook.Worksheets("Admin").Range("H18").Value = m
    DoEvents
End Sub 

OTHER TIPS

I believe that if you examined ThisWorkbook.Worksheets("Admin").Range("H18").Value after the line setting its value, its value would be exactly as expected.

While VBA that runs with Application.ScreenUpdating=True generally shows on-screen whatever the code is doing, there is no requirement that Excel must update the screen.

Conversely, with Application.ScreenUpdating=False, there is a requirement that Excel must not update the screen.

If for whatever reason Excel cannot command the system resources necessary to update the screen and do the other tasks it must perform while Application.ScreenUpdating=True, screen updating will be temporarily turned off, leading to the issue you describe. DoEvents may well fix this, but can lead to reduced performance, and other problems if you have events elsewhere in the workbook that are being triggered - DoEvents is specifically saying "Handle pending events now".

You will get better performance if you use Application.ScreenUpdating=False while your code is running, and use Application.StatusBar to display status.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top