Excel is versatile by itself and VBA makes it even better by allowing us to do our own thing. Most of us use VBA to automate tasks of varying complexity – some macros are executed in a flash, but others take hours to run. While there are users who are happy with just a Msgbox “This thing is DONE!”, there are others who’d like to let the user know more about what is happening.
If you are thinking, “Hey I can see exactly what is going on, why would I need to display messages?”, you may have to consider digging into optimizing your code a little. I admit that allowing Excel to update the screen each time your macro makes a change, helps during development, but it slows down the code a lot. It is best to set the ScreenUpdating and EnableEvents properties of the Application object to False at the outset. I intend to write about the best practices in the coming weeks, but let us get back to the issue at hand. The quickest way to display messages while the code is running is to use the Statusbar property of the Application object. Users can display custom messages on Excel’s status bar when needed, and allow excel to take over after their macro finishes executing. Here is a short example:
'======================================================================== 'A Macro to Illustrate the use of Application.Statusbad property '======================================================================== Sub StatusBarExample() 'Disable Screen Updating and Events Application.EnableEvents = False Application.ScreenUpdating = False 'Declaring Sub Level Variables Dim lngCounter As Long Dim lngNumberOfTasks As Long 'Initilaizing Variables lngNumberOfTasks = 10000 For lngCounter = 1 To lngNumberOfTasks 'Altering the Statusbar Property Application.StatusBar = "Executing " & lngCounter & _ " of " & lngNumberOfTasks & " | " & _ "Custom Message " & lngCounter Next lngCounter 'Letting Excel Take over the status bar Application.StatusBar = False 'Enable ScreenUpdating and Events Application.ScreenUpdating = True Application.EnableEvents = True End Sub
Another popular method is to deploy a UserForm and have a label control that displays a message. We may also choose to use the width property of a control and resize it as the code progresses, to display a progress bar of sorts. A fellow struggler, a good friend of mine, used to create dedicated forms for each of his macros, just to display a progress bar. That got me thinking, what if I could give my readers a generic form that they could use in all their spreadsheet applications? And I created this Form-Module combo.
So here is what you need to do, to use this in your code. Download Progress Bar V1.01.xlsm from DropBox, import the userform, ‘ufProgress‘; and the module, ‘modProgress‘, into your VBA project. You may just drag the objects and drop them into your project, in the Project Explorer window of the Visual Basics Editor. And Call the ‘modProgress.ShowProgress‘ with a few arguments. Listed below are the arguments, and their purpose:
- ActionNumber – This argument denotes the number of actions that have already been performed. You may probably use a For-Loop counter here, or explicitly change it as the code progresses.
- TotalActions – This denotes the total number of actions you need to perform.
- StatusMessage – The form has a little status bar at the bottom and you can display custom messages there. ideally, a short description of the action.
- CloseWhenDone – Set this argument to True, to close the form automatically when ActionNumber reaches TotalActions. Hence, remember to call ShowProgress with the last ActionNumber only when that action is complete.
- Title – You may choose to set a custom title for the form here.
Here is an example of how to use the ShowProgress sub:
Option Explicit '======================================================================== 'Cover Macro to Test the Progress Bar '======================================================================== Sub TestTheBar() 'Disable Screen Updating and Events Application.EnableEvents = False Application.ScreenUpdating = False 'Declaring Sub Level Variables Dim lngCounter As Long Dim lngNumberOfTasks As Long 'Initilaizing Variables lngNumberOfTasks = 10000 'Calling the ShowProgress sub with ActionNumber = 0, to let the 'user know we are going to work on the 1st task. Also, set a 'title for the form Call modProgress.ShowProgress(0, lngNumberOfTasks, _ "Excel is working on Task Number 1", False, _ "Progress Bar Test") For lngCounter = 1 To lngNumberOfTasks 'The code for each task goes here ' 'Call the ShowProgress sub each time a task is finished to 'the user know that X out of Y tasks are over, and that 'the X+1'th task is in progress. Call modProgress.ShowProgress(lngCounter, lngNumberOfTasks, _ "Excel is working on Task Number " & lngCounter + 1, False) Next lngCounter 'Enable ScreenUpdating and Events Application.ScreenUpdating = True Application.EnableEvents = True End Sub
Note that you can press the Abort button anytime to stop the execution. And this workbook also has a simple user defined function that you can use to check if a form has been already opened. I urge you to use them in your projects and let me know if you like it.
I have created a new class based progress bar. The new version does not need the Standard Code Module to animate the bar. Also, you can create multiple instances of the Progress Bar simultaneously. I recommend using that version in your code. Check it out and let me know what you think.