2

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.

Eitel Dagnin
  • 959
  • 4
  • 24
  • 61

2 Answers2

1

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
LatifaShi
  • 440
  • 1
  • 3
  • 12
  • Thank you for your reply @Latifa, I copied your code as is and ran it. The UserForm shows up but it is blank and then the macro just stops there. Nothing else happens. – Eitel Dagnin Apr 12 '18 at 17:46
  • @EitelDagnin did you change the line path = "C:\Users\User1\Desktop\New Folder" to your own path ? .. – LatifaShi Apr 12 '18 at 17:46
  • Yes I did. I am also looking at your past post to see if I can come up with something. But if youre able to assist, I would really appreciate :) – Eitel Dagnin Apr 12 '18 at 17:51
  • I'll try my best .. :) .. The UserForm show up blank when your path doesn't exist or when your folder doesn't contain *.xlsx files .. and make sure you are executing the ShowDialog sub not something else .. check That .. – LatifaShi Apr 12 '18 at 17:58
  • Thank you again. I double checked now, the path is correct, there are xlsx files in that folder and I am executing the ShowDialog sub. – Eitel Dagnin Apr 12 '18 at 18:01
  • Look at my code there is a line strFile = Dir(path & "\*.RSU") change it to strFile = Dir(path & "\*.xlsx") .. I forgot to change it because i was working with RSU files .. give me feedback .. :p – LatifaShi Apr 12 '18 at 18:03
  • Lol! I looked at that RSU and did't recognize it as a file extension so I looked passed it. The progress bar is working now :) I am going to put my worksheet copying code in now and test again. Also, one thing I saw is that the UserForm didn't close after it got to 100% – Eitel Dagnin Apr 12 '18 at 18:09
  • To close it .. add : Unload UserForm1 before End Sub .. I'll edit my answer to add this line .. – LatifaShi Apr 12 '18 at 18:12
  • Thank you!! I added my code and ran it but got an error. Please look at the bottom of my post, I updated it with the details. it's too long to fit in here. – Eitel Dagnin Apr 12 '18 at 18:21
  • Change the line "X:\Test\3rd Party\\" with "X:\Test\3rd Party\" and the both lines strFile = Dir(path & "\*.xlsx") with strFile = Dir(path & "*.xlsx") .. and change the line : Workbooks.Open Filename:=path & "\" & strFile, ReadOnly:=True with Workbooks.Open Filename:=path & "\" & strFile – LatifaShi Apr 12 '18 at 18:33
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/168865/discussion-between-eitel-dagnin-and-latifashi). – Eitel Dagnin Apr 12 '18 at 18:52
  • @EitelDagnin .. The two lines : Workbooks(strFile).Activate ActiveWorkbook.Close SaveChanges:=False .. you should put them outside the For Each loop because putting them inside will just copy one sheet per workbook .. not the whole sheets .. I'll edit my answer again ..check it .. – LatifaShi Apr 12 '18 at 19:42
1

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.

Darren Bartrup-Cook
  • 18,362
  • 1
  • 23
  • 45
  • Thank you for the reply @Darren. I Copied your code into a workbook, I just wanted to know, is this code supposed to go inside of my "testing" sub? – Eitel Dagnin Apr 12 '18 at 17:40
  • You'd add the `UpdateProgressBar lCurrentCount, lFinalCount` after you've increased the count, replacing the variables used in the call with your own. The code in the link I gave would then go in a separate module. You've found an answer that works for you since I last looked though, so all good. :) – Darren Bartrup-Cook Apr 13 '18 at 07:55
  • Thank you very much for the reply again Darren, much appreciated. :) – Eitel Dagnin Apr 13 '18 at 08:17