0

I got the following macro that does calculation of percentage of rows filled per column and loops through a directory, and doesnt save the results in the files. Now how can I take these results with a file name and column name and paste it into a master worksheet within my active blank workbook?

Sub Calculation()

'PURPOSE: To loop through all Excel files in a user specified folder and perform a set task on them

Dim wb As Workbook, fileNames As Object, errCheck As Boolean 'part of loop


'Optimize Macro Speed
  Application.ScreenUpdating = False
  Application.EnableEvents = False
  Application.Calculation = xlCalculationManual




 'get user input for files to search
Set fileNames = CreateObject("Scripting.Dictionary")
errCheck = UserInput.FileDialogDictionary(fileNames)
If errCheck Then
   Exit Sub
End If
'''
For Each Key In fileNames 'loop through the dictionary I added the below Sept 9, 2015
    Set wb = Workbooks.Open(fileNames(Key)) 'I added the below Sept 9, 2015
    wb.Application.Visible = False 'make it not visible I added the below Sept 9, 2015




    Dim xrng As Range, lrw As Long, lrng As Range, i As Long
    Dim LstCo As Long, ws As Worksheet


    With Application
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
    End With

    For Each ws In ActiveWorkbook.Worksheets
        With ws

            If Not Application.WorksheetFunction.CountA(.Cells) = 0 Then

                LstCo = .Cells.Find("*", , xlValues, xlWhole, xlByColumns, xlPrevious, False).Column
                For i = 1 To LstCo
                    With .Columns(i)
                        .TextToColumns Destination:=.Cells(1, 1), DataType:=xlDelimited, TrailingMinusNumbers:=True
                    End With
                Next

                lrw = .Columns("A:Y").Find("*", , xlValues, , xlRows, xlPrevious).Row
                If lrw = 1 Then lrw = 2
                Set lrng = .Range("A" & lrw + 2)

                With .Range("A2:A" & lrw)
                    lrng.Formula = "=COUNTA(" & .Address(0, 0) & ")/ROWS(" & .Address(0, 0) & ")"
                End With


                Set xrng = .Range(lrng, .Cells(lrng.Row, LstCo))


                lrng.AutoFill xrng, Type:=xlFillDefault
                xrng.Style = "Percent"
            End If
        End With
    Next













 wb.Application.Visible = True '' I added this Sept 9, 2015
 wb.Close savechanges:=False 'close the workbook do not save
Set wb = Nothing 'release the object

Next 'End of the fileNames loop
Set fileNames = Nothing





'Message Box when tasks are completed
  MsgBox "Task Complete!"

ResetSettings:
  'Reset Macro Optimization Settings
    Application.EnableEvents = True
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True

End Sub

EDIT

Hi, thank you so much for the reply. I have altered my code slightly(not reflecting your changes). Can you alter this code to take the results of each worksheet and workbook and put into master worksheet? I've had troubles with your code probably because mine altered from the original question.

Sub Calculation2()


Dim wb As Workbook, fileNames As Object, errCheck As Boolean
    Dim ws As Worksheet, wks As Worksheet, wksSummary As Worksheet
    Dim boolWritten As Boolean
    Dim xrng As Range, lrw As Long, lrng As Range, i As Long
    Dim LstCo As Long

   'Skipped worksheet for file names
   Dim wksSkipped As Worksheet
   Set wksSkipped = ThisWorkbook.Worksheets("Skipped")


     ' Turn off screen updating and automatic calculation
    With Application
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
    End With





'get user input for files to search
Set fileNames = CreateObject("Scripting.Dictionary")
errCheck = UserInput.FileDialogDictionary(fileNames)
If errCheck Then
   Exit Sub
End If
'''
For Each Key In fileNames 'loop through the dictionary




On Error Resume Next
Set wb = Workbooks.Open(fileNames(Key))
If Err.Number <> 0 Then
    Set wb = Nothing    ' or set a boolean error flag
End If
On Error GoTo 0    ' or your custom error handler

'putting skipped files into skipped sheet
If wb Is Nothing Then
wksSkipped.Cells(wksSkipped.Cells(wksSkipped.Rows.Count, "A").End(xlUp).Row + 1, 1) = fileNames(Key)

Else
    Debug.Print "Successfully loaded " & fileNames(Key)
    wb.Application.Visible = False 'make it not visible
    ' more working with wb




 ' Check each sheet in turn
    For Each ws In ActiveWorkbook.Worksheets
        With ws



           'adding calculation code





    With Application
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
    End With



            If Not Application.WorksheetFunction.CountA(.Cells) = 0 Then

                LstCo = .Cells.Find("*", , xlValues, xlWhole, xlByColumns, xlPrevious, False).Column
                For i = 1 To LstCo
                    With .Columns(i)
                        .TextToColumns Destination:=.Cells(1, 1), DataType:=xlDelimited, TrailingMinusNumbers:=True
                    End With
                Next

                lrw = .Columns("A:Y").Find("*", , xlValues, , xlRows, xlPrevious).Row
                If lrw = 1 Then lrw = 2
                Set lrng = .Range("A" & lrw + 2)

                With .Range("A2:A" & lrw)
                    lrng.Formula = "=COUNTA(" & .Address(0, 0) & ")/ROWS(" & .Address(0, 0) & ")"
                End With


                Set xrng = .Range(lrng, .Cells(lrng.Row, LstCo))


                lrng.AutoFill xrng, Type:=xlFillDefault
                xrng.Style = "Percent"
            End If















    With Application
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
        Application.CalculateFull
    End With








        End With
    Next ws
wb.Close savechanges:=True 'close the workbook do not save
Set wb = Nothing 'release the object
End If

Next 'End of the fileNames loop
Set fileNames = Nothing


' Reset system settings
With Application
   .Calculation = xlCalculationAutomatic
   .ScreenUpdating = True
   .Visible = True
End With
End Sub
Jonathan
  • 313
  • 4
  • 16
  • You change cells in every file but you dont save those files. So I think you copied the code and do not really understand what it does? If you just want to have the metrics in a separat file you would not use excel-functions but just vba. What is your final goal? –  Oct 24 '15 at 23:45
  • @Johanness, thank you for your reply. I used to have ` wb.Close SaveChanges:=True ` in there at the bottom , Is this a must? I just think if Im going through many files this can be annoying if I want the original files back . Your right I am pretty new to vba. My final goal is to take the results (the % filled of each column), and put it into a master sheet with say file name in column A, sheet name in B, Column names in C, and % of how much are filled in D, have this loop through a directory – Jonathan Oct 24 '15 at 23:57

1 Answers1

0

If you do all the calculations in vba you dont have to write anything to the individual sheets:

Sub calculations()
Dim wb As Workbook, fileNames As Object, errCheck As Boolean 'part of loop


Dim ws As Worksheet
Dim resultSheet As Worksheet
Dim i As Long
Dim lco As Integer
Dim lrw As Integer
Dim resultRow As Integer
Dim measurement As Double

Set resultSheet = Application.ActiveSheet
resultRow = 1

'Optimize Macro Speed
  Application.ScreenUpdating = False
  Application.EnableEvents = False
  Application.Calculation = xlCalculationManual
'get user input for files to search
  Set fileNames = CreateObject("Scripting.Dictionary")
  errCheck = UserInput.FileDialogDictionary(fileNames)
  If errCheck Then Exit Sub


For Each Key In fileNames 'loop through the dictionary I added the below Sept 9, 2015
    Set wb = Workbooks.Open(fileNames(Key)) 'I added the below Sept 9, 2015
    wb.Application.Visible = False 'make it not visible I added the below Sept 9, 2015

    For Each ws In wb.Worksheets
        If Not Application.WorksheetFunction.CountA(ws.Cells) = 0 Then
            'define the range to measure
            lco = ws.Cells.Find("*", , xlValues, xlWhole, xlByColumns, xlPrevious, False).Column
            lrw = ws.Columns("A:Y").Find("*", , xlValues, , xlRows, xlPrevious).Row
            If lrw = 1 Then lrw = 2
            For i = 1 To lco
                measurement = Application.WorksheetFunction.CountA(ws.Range(ws.Cells(1, i), ws.Cells(lrw, i))) / lrw
                resultSheet.Cells(resultRow, 1).Value = wb.name
                resultSheet.Cells(resultRow, 2).Value = ws.Name
                resultSheet.Cells(resultRow, 3).Value = Col_Letter(i)
                resultSheet.Cells(resultRow, 4).Style = "Percent"
                resultSheet.Cells(resultRow, 5).Value = measurement
                resultRow = resultRow + 1
            Next
        End If
    Next
    wb.Application.Visible = True '' I added this Sept 9, 2015
    wb.Close savechanges:=False 'close the workbook do not save
    Set wb = Nothing 'release the object
Next 'End of the fileNames loop

Set fileNames = Nothing
'Message Box when tasks are completed
MsgBox "Task Complete!"

ResetSettings:
  'Reset Macro Optimization Settings
    Application.EnableEvents = True
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
End Sub

Function Col_Letter(lngCol As Long) As String
    Dim vArr
    vArr = Split(Cells(1, lngCol).Address(True, False), "$")
    Col_Letter = vArr(0)
End Function
  • Thanks so much, I get sub or function not defined, highlight the sub calculations witha clue highlet on Col_letter. I altered my code abit(See edit), it just includes. Any ideas? – Jonathan Oct 25 '15 at 16:19
  • I would like to have the results displayed in the main actiive workbook, click my button, does the loop and calculations and spits out results in another sheet. – Jonathan Oct 25 '15 at 16:20
  • Sorry. Added the function I copied from @brettdj here http://stackoverflow.com/questions/12796973/function-to-convert-column-number-to-letter –  Oct 25 '15 at 17:18
  • As you may be aware, this is not a free programming service - so I think this code should do the most part of what you need. Any search engine can get you where you need to go from here. –  Oct 25 '15 at 17:20
  • Thank you so much!! I get an error on this line though `measurement = Application.WorksheetFunction.CountA(ws.Range(Cells(1, i), Cells(lrw, i))) / lrw` , Application defined or object defined error – Jonathan Oct 25 '15 at 17:45
  • Was I supposed to add my original code to your post? Or did you completely take that out? – Jonathan Oct 25 '15 at 21:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/93316/discussion-between-johanness-and-jonathan). –  Oct 25 '15 at 23:09
  • would you know how to fix a problem where the first worksheet in a file has only a header, it seems to give me an error on these types, overflow error on this line `lrw = ws.Columns("A:Y").Find("*", , xlValues, , xlRows, xlPrevious).Row` – Jonathan Oct 26 '15 at 13:16
  • After furthur testing , it doesnt seem that it has anything to do with the first sheet not having any data, still testing – Jonathan Oct 26 '15 at 13:31
  • Was able to solve above, sorry for commenting, just to document. I changed lwr to long instead of integer. But now difficulty with getting the right calculations, not sure what is wrong, maybe the actual formula itself, seems to work for most files but some end up showing a percent when the column is blank. – Jonathan Oct 26 '15 at 16:09
  • I took this from your code when I didn't realize you had the ColumnNames in the first row. Just change this: countA(ws.Range(ws.Cells(2,i........ (I think it would be very valuable for you to look at the code yourself and try to figure out what it does... You might learn something) –  Oct 26 '15 at 20:13