TurboCoder
TurboCoder

Reputation: 1011

VBA - Show Progress Bar While Macro Executes

I have a macro that opens xlsx files in a folder one at a time and copies their sheets into a specific file. Sometimes this macro takes rather long to run and I would like to add a progress bar to show the user how far along the macro is.

I found a few guides that show how to do this, and I tested them in sample workbooks. Now, I am trying to integrate the guides with my macro but I am not having any success.

Here is my code (to copy the sheets):

Sub ImportDataSheets()

    Dim X As Workbook
    Set X = Workbooks("3rd Party.xlsm")

    path = "X:\Test\3rd Party\\"
    Filename = Dir(path & "*.xlsx")

    Do While Filename <> ""
        Workbooks.Open Filename:=path & Filename, ReadOnly:=True

        For Each Sheet In ActiveWorkbook.Sheets

            Sheet.Copy After:=X.Sheets(1)

        Next Sheet

        Workbooks(Filename).Close
        Filename = Dir()

    Loop

End Sub

Here is the link to the guide for using a form as a progress bar:

http://spreadsheetpage.com/index.php/tip/displaying_a_progress_indicator/

Here is the basic breakdown of that guide:

1) Insert form and make it look like this:

enter image description here

Added a frame (renamed to FrameProgress) inside the form and a label (renamed to LabelProgress) inside the frame

2) Right click on the form and click on view code

3) Inside the window, add this code:

Private Sub UserForm_activate()
    Call Main
End Sub

4) Insert a module and add this code:

Sub Main()
'   Inserts random numbers on the active worksheet
    Dim Counter As Integer
    Dim RowMax As Integer, ColMax As Integer
    Dim r As Integer, c As Integer
    Dim PctDone As Single

    If TypeName(ActiveSheet) <> "Worksheet" Then Exit Sub
    Cells.Clear
    Application.ScreenUpdating = False
    Counter = 1
    RowMax = 100
    ColMax = 25
    For r = 1 To RowMax
        For c = 1 To ColMax
            Cells(r, c) = Int(Rnd * 1000)
            Counter = Counter + 1
        Next c
        PctDone = Counter / (RowMax * ColMax)
        With UserForm1
            .FrameProgress.Caption = Format(PctDone, "0%")
            .LabelProgress.Width = PctDone * (.FrameProgress.Width - 10)
        End With
'       The DoEvents statement is responsible for the form updating
        DoEvents
    Next r
    Unload UserForm1
End Sub

5) Insert a module and add this code:

Sub ShowDialog()
    UserForm1.LabelProgress.Width = 0
    UserForm1.Show
End Sub

6) Run the "ShowDialog" module and it will fill data from cell A1 - cell Y100 and display a progress bar while doing so - This works 100%

I noticed in the above code, there's a counter and that counter gets used to divide by the row and column count combined to get the percentage, so I got the below code to do a count of the files in the folder so that I would have a counter value - and after every file gets closed, the second count variable would increment by 1.

Here is where I got the code for the counter:

count files in specific folder and display the number into 1 cel

Code:

Sub sample()

    Dim FolderPath As String, path As String, count As Integer
    FolderPath = "X:\Test\3rd Party"

    path = FolderPath & "\*.xlsx"

    Filename = Dir(path)

    Do While Filename <> ""
       count = count + 1
        Filename = Dir()
    Loop

    Range("Q8").Value = count
    'MsgBox count & " : files found in folder"
End Sub

Now here is where and/how I have tried to "combine" my code with the guide:

1) This is what the code in my form looks like:

Sub UserForm_activate()
    Call testing
End Sub

2) This is what my sub looked like:

Sub testing()

    Dim FolderPath As String, path As String, count As Integer
    Dim PctDone As Single
    Dim Counter As Integer
    FolderPath = "X:\Test\3rd Party"

    path = FolderPath & "\*.xlsx"

    Dim X As Workbook
    Set X = Workbooks("3rd Party.xlsm")

    Counter = 1

    Filename = Dir(path)

    For r = 1 To count

        Do While Filename <> ""

            Workbooks.Open Filename:=path & Filename, ReadOnly:=True

            For Each Sheet In ActiveWorkbook.Sheets

                Sheet.Copy After:=X.Sheets(1)

                Workbooks(Filename).Close

                Filename = Dir()

            Next Sheet

            count = count + 1

        Loop

        PctDone = Counter / count

        With UserForm1

            .FrameProgress.Caption = Format(PctDone, "0%")
            .LabelProgress.Width = PctDone * (.FrameProgress.Width - 10)

        End With

        DoEvents

    Next r

    Unload UserForm1

End Sub

I have many macros, and it would be fantastic to use this with the ones that take long to execute, so I am hoping that if I get it to work with one, I can use it with them all.

Upvotes: 2

Views: 33007

Answers (2)

LatifaShi
LatifaShi

Reputation: 440

Hope it helps ..

Edit : I moved outside for each loop the lines :

   Workbooks(strFile).Activate
   ActiveWorkbook.Close SaveChanges:=False

The code :

 Sub testing()

    Application.ScreenUpdating = False
    Dim path As String, count As Integer
    Dim PctDone As Single
    Dim Counter As Integer
    count = 0

    Dim wkbk As Workbook
    Set wkbk = Workbooks("3rd Party.xlsm")

    'Change this to your folder path
    path = "X:\Test\3rd Party\"
    strFile = Dir(path & "*.xlsx")

    'This loop counts the number of files in my folder
    Do While Len(strFile) > 0
        count = count + 1
        strFile = Dir
    Loop

    strFile = Dir(path & "\*.xlsx")
    ' This loop will go through the folder and open each file and close it
    Do While Len(strFile) > 0

        Workbooks.Open Filename:=path & "\" & strFile, ReadOnly:=False
        Workbooks(strFile).Activate
        ''''' Do what you want Here '''''

        For Each Sheet In ActiveWorkbook.Sheets

            Sheet.Copy After:=wkbk.Sheets(1)

        Next Sheet

        Workbooks(strFile).Activate
        ActiveWorkbook.Close SaveChanges:=False

        'Every time it opens a file and close it, the counter will increment by one
        Counter = Counter + 1

        'The progress bar will be updated each time a new file is opened
        PctDone = Counter / count
        With UserForm1
            .FrameProgress.Caption = Format(PctDone, "0%")
            .LabelProgress.Width = PctDone * (.FrameProgress.Width - 10)
        End With

        DoEvents

        'Go to the next file in the folder
        strFile = Dir
    Loop
    Application.ScreenUpdating = True

    Unload UserForm1

End Sub

Upvotes: 1

Darren Bartrup-Cook
Darren Bartrup-Cook

Reputation: 19782

Using the example for a progress bar that I gave in this post.

Notice Option Explicit at the very top of the module.... I can't stress enough how important this is. It forces you to declare each variable before using it.

Option Explicit

Sub ImportDataSheets()

    Dim X As Workbook
    Dim Src_Book As Workbook
    Dim FileCount As Long

    Dim Path As String
    Dim FileName As String
    Dim Sheet As Worksheet

    Dim lCurrentCount As Long

    Set X = Workbooks("3rd Party.xlsm")

    Path = "X:\Test\3rd Party\\"
    FileName = Dir(Path & "*.xlsx")

    'This will count all files in the folder.
    FileCount = CreateObject("Scripting.FileSystemObject").GetFolder(Path).Files.Count

    Do While FileName <> ""
        Set Src_Book = Workbooks.Open(FileName:=Path & FileName, ReadOnly:=True)

        For Each Sheet In Src_Book.Sheets
            Sheet.Copy After:=X.Sheets(1)
        Next Sheet

        'This is where the progress bar gets updated.  
        'You'll need something to update the lCurrentCount for each book.
        UpdateProgressBar lCurrentCount, lFinalCount

        Src_Book.Close
        FileName = Dir()
    Loop

End Sub  

You could change UpdateProgressBar lCurrentCount, lFinalCount to UpdateProgressBar lCurrentCount, lFinalCount, Src_Book.Name so the progress bar displays the name of the book being opened as well.

Upvotes: 1

Related Questions