The Previous page showed the code for the UserForm.

The code for the main program is below.

The two private variables go at the very top of the code module.

Private NewfrmProgress As frmProgress
Private NewLabel1 As msforms.Label

Sub MainProgram()
   Dim i As Integer
   Dim intProcess1ReturnValue, _
   intProcess2ReturnValue As Integer

   Dim intMainProgramProcess1ArgValue, _
   intMainProgramProcess2ArgValue As Long

   Dim objStartTime, objEndTime As Variant

   'Create a new instance of frmProgress.
   Set NewfrmProgress = New frmProgress

   'Create a new instance of the Label Control.
   Set NewLabel1 = NewfrmProgress.frameProgress. _
   Controls.Add(bstrProgId:="forms.label.1", _
   Name:="NewLabel1", Visible:=True)

   'Set some properties of new label.
   NewLabel1.BackColor = &HFF&
   NewfrmProgress.frameProgress.NewLabel1.Width = 0
   NewfrmProgress.frameProgress.NewLabel1.Left = 0
   NewfrmProgress.frameProgress.NewLabel1.Height = 10
   NewfrmProgress.frameProgress.NewLabel1.Top = 4

   'Set some variables for testing purposes.
   intMainProgramProcess1ArgValue = 250000
   intMainProgramProcess2ArgValue = 500000

   'Get systen time at start of process1.
   objStartTime = Timer

   'Set caption of UserForm.
   NewfrmProgress.Caption = _
   "Progress Meter - Process 1"

   'Run Process1
   ProcessWithProgressMeter _
   "Process1", intMainProgramProcess1ArgValue

   'Get the return value of process 1from the UserForm.
   intProcess1ReturnValue = NewfrmProgress.intResults

   'Get system time at end of process1.
   objEndTime = Timer

   'Display the results of process 1 in a message box.
   MsgBox "Process 1 time: " & _
   Format((objEndTime - objStartTime), "###.#") & _
   " seconds" & vbCrLf & "Process 1 Return Value: " & _
   intProcess1ReturnValue

   'Get systen time at start of process2.
   objStartTime = Timer

   'Reset the caption for Process 2.
   NewfrmProgress.Caption = "Progress Meter - Process 2"

   'Run Process 2
   intAnything = ProcessWithProgressMeter("Process2", _
   intMainProgramProcess2ArgValue)

   'Get the return value of process 2 from the Userform.
   intProcess2ReturnValue = NewfrmProgress.intResults

   'Get systen time at start of process2.
   objEndTime = Timer

   'Display the results of process 2 in a message box.
   MsgBox "Process 2 time: " & _
   Format((objEndTime - objStartTime), "###.#") & _
   " seconds" & vbCrLf & "Process 2 Return Value: " & _
   intProcess2ReturnValue

End Sub		

Note that Process 1 is initiated with the command:
ProcessWithProgressMeter _
"Process1", intMainProgramProcess1ArgValue			

Process2 is initiated with the command:
intAnything = ProcessWithProgressMeter("Process2", _
intMainProgramProcess2ArgValue)				
Both processes call the same function, pass 2 arguments to the function and return a value from the function.  br />
The first one cannot have parentheses around the arguments.  

The second one must have parentheses around the arguments. 
Function ProcessWithProgressMeter(ByVal strProcName As _ 
String, yVal intReceivedValue1) As Long

   'Pass 2 parameters to the userform
   'by setting the userform properties.
   NewfrmProgress.ProcValue = intReceivedValue1
   NewfrmProgress.ProcName = strProcName

   'Show the userform
   NewfrmProgress.Show

   'Hide the userform.
   NewfrmProgress.Hide

   'Prepare the return value for the MainProgram.
   ProcessWithProgressMeter = _
   NewfrmProgress.intResults

EEnd Function		

The command line above with NewfrmProgress.Show will next lead to the following UserForm event.
Private Sub UserForm_Activate()
   Me.Width = 240
   Me.Height = 60
   Me.frameProgress.Height = 20
   Me.frameProgress.Width = 225
   Me.frameProgress.Top = 12
   Me.frameProgress.Left = 5

   Select Case UCase(strProcName)

      Case "PROCESS1"
         intResultsValue = Process1(intProcValue)
         Me.intResults = intResultsValue

      Case "PROCESS2"
         intResultsValue = Process2(intProcValue)
         Me.intResults = intResultsValue

   End Select

End Sub		

One of the parameters received by the erForm is strProcName.

It is used by the UserForm in the Select Case statement to control which processed the UserForm will run.

The second parameter received by the UserForm is intProcValue.

It is the value that needs to be passed to the function being called next.

Those
 two functions shown below.  The functions do not do anything useful.  The first one will loop to 250,000 and the second one will loop to 500,000.  Your actual program functions would be placed in these functions.
Function Process1(ByVal intLastNumber As Long)

   'intLastNumber will be 250000 
   'from the MainProgram above.
   Dim pctdone As Single
   Dim i As Long
   Dim intProcess1ReturnValue As Long
   Dim ProgressCounter As Long


   ProgressCounterEnd = intLastNumber

   'Loop through all files.
   'Simple steps intended to take up
   'some processor time.
   For i = 1 To intLastNumber

      ProgressCounter = i

      'Only update the ProgressMeter
      'once every 10 times.
      If i Mod 10 = 0 Then
         pctdone = ProgressCounter / ProgressCounterEnd
         UpdateProgressBar pctdone
      End If

   Next i

   'Make up a return value.
   Process1 = 100

   NewfrmProgress.Hide

End Function			

Process2:
Function Process2(ByVal intLastNumber As Long)

   'intLastNumber will be 500000 
   'from the MainProgram above.
   Dim pctdone As Single
   Dim i As Long
   Dim Process2ReturnValue As Integer
   Dim ProgressCounter As Long

   ProgressCounterEnd = intLastNumber

   'Loop through all files.
   'Simple steps intended to take up
   'some processor time.
   For i = 1 To intLastNumber

      ProgressCounter = i


      'Only update the ProgressMeter
      'once every 10 times.
      If i Mod 10 = 0 Then
         pctdone = ProgressCounter / ProgressCounterEnd
         UpdateProgressBar pctdone
      End If

   Next i

   'Make up a return value.
   Process2 = 200

   NewfrmProgress.Hide

End Function			


The last function is shown below.  This is the one that will update the progress meter.
Sub UpdateProgressBar(pctdone As Single)

   With NewfrmProgress

      ' Update the Caption property of the
      'Frame control by showing new percentage number
      .frameProgress.Caption = Format(pctdone, "0 %")

      ' Widen the Label control.
      .frameProgress.NewLabel1.Width = pctdone * _
      (.frameProgress.Width)

   End With

   'The DoEvents causes the UserForm to update.
   DoEvents

End Sub				

After you start the inProgram at the top of this page, the ProgressMeter shown below will appear.

This progress meter is updated 25,000 times while the program runs.

This is one of the 25,000 updates captured after about 3 seconds.



ThThe code in Process1 and Process2 said.

If i Mod 10 = 0 Then
   pctdone = ProgressCounter / ProgressCounterEnd
   UpdateProgressBar pctdone
End If			

This caused it to update erytime that i was evenly divisibly by 10 while i went from 1 to 250,000 in process1.

After Process1 finished the MessageBox from MainProgram below was displayed. 




This means that the red label control width went from 0 to the full width of the frame in about 6.5 seconds.  It will look like a continuous movement.

The frame title showing 50% complete is also updated 25,000 times and it will change from 1% to 100% in about 6 seconds.

It will be almost impossible to read the Percentage Complete since it is moving so fast.  The ProgressMeter will also be a bit jerky.

In a real world application I would change if i mod 10 to if i mod 20.  This would cause the ProgressMeter to update whenever i is evenly divisible by 20.  In the example above it would update 12,500 times and appear less jerky and the Percentage Complete will be easier to read.

After you click on OK on the messagebox Process2 will start.

After about 3 seconds the ProgressMeter will look like the following:



After Process2 finished the MessageBox below will appear.



Process2 counted to 500,000.  It updated the ProgressMeter 50,000 times during the process.  The Percentage Complete was a bit easier to read since it went from 1% to 100% in about 12 seconds in Process2 compared to 6.5 seconds in Process1.

I would still update if i mod 10 to if i mod 20. so that t would only update 25,000 times.

From there I would experiment with different values of mod and check the appearance of the ProgressMeter each time until it looks least jerky.

Valid XHTML 1.0 Transitional        Valid CSS!