Keeping a running time can be accomplished by using the Form's Timer event. But since you don't want the Timer event to start until begin your process, I suggest that you disable the timer in the Form_Load event.
Code:
Private Sub Form_Load()
Me.TimerInterval = 0
End Sub
When you want the timer to begin, set the timer interval, which is the number of milliseconds between Timer Events. For a one second interval, you would set the timer interval to 1000. At the completion of the process, you need to disable the timer by setting the interval back to 0.
Code:
Private Sub cmdBeginProcess_Click()
txtElapTime.Tag = Time()
Me.TimerInterval = 1000
<Build your Reports>
Me.TimerInterval = 0
txtElapTime.Tag = vbNullString
End Sub
Then inside the timer event, you would have the following code
Code:
Private Sub Form_Timer()
txtElapTime = DateDiff("s", txtElapTime.Tag, Time())
DoEvents
End Sub
You may be wondering why the .Tag property is initialized to Time() at the start of the interval and why in the Timer Event the DateDiff function is being used, rather than initializing to zero and simply incrementing by one, since the interval is one second. The answer lies in how events are processed, and what exactly you wish to capture, and the fact that we don't work in an optimal world and Windows is not a real-time OS. Every second, a Timer event will be placed on the Windows message queue. However, there will a time delay before Windows actually processes that message, and delivers it to the Application message queue. Another time delay will occur before the application will handle the event. The result is that by the time the event is handled, more than one second will have passed. Depending on how processor intensive your code is, and other processes running concurrently with your application, it may be almost immediate that the event is handled, or it may actually be a second or two before the message is actually handled by your application. If you simply increment the txtElapTime value, you will be counting the number of times that you application handled a Timer event, and not the elapsed time. Consequently, you capture the actual time the processed started, and display the elapsed time between the start time and the time that the current Timer event is being handled. You can improve the granularity of the event by using DoEvents inside of your process at appropriate times, which provides your application opportunities to catch up on the pending messages, such as the pending Timer events. You can also reduce your own time interval between events. Unfortunately, there are a few other processes running that may not be able to control to insure that you will be able to process the Timer events in precisely one second intervals.
Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein