Count the total lines in all files in all subfolders

nadavrock

New Member
Joined
May 15, 2019
Messages
24
i want to use vba to count all the lines in all the files in all the subfolder of a directory and display them in a cell. how do i do that?
i found a code working for counting the lines in a single file. but i dont know how to construct the loop to apply this to all the files in all the subfolder




<code style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; vertical-align: baseline; box-sizing: inherit; white-space: inherit;">Function countLF(fName As String) As Long
Dim st As String
Open fName
For Input As #1: st = Input(LOF(1), 1): Close

countLF
= Len(st) - Len(Replace(st, vbLf, "")) + 1
End Function

=countLF("c:\test.txt")</code>
 

Excel Facts

Format cells as date
Select range and press Ctrl+Shift+3 to format cells as date. (Shift 3 is the # sign which sort of looks like a small calendar).
Re: how to count the total llines in all files in all subfolders

Below is a code which will create a list of all files in a selected folder from the active cell down (start the macro called ScanFilesInSubfolders)
Then you can use the filenames to get the line count any way you like (I think your code will not always work)
Code:
Option Explicit
Option Compare Text
Option Base 1


Private cRng As Range 'current cell - increasing with every new record


Sub ScanFilesInSubfolders()
    On Error GoTo errHandler
    
'Select folder to be scanned
    Dim root As String: root = BrowseForFolder
    If UCase(root) = "FALSE" Then Exit Sub 'if no folder is selected
    If Left(root, 2) = "\\" Then MsgBox "Cannot scan network drives yet!", vbOKOnly: Exit Sub
    
    If Right(root, 1) <> "\" Then root = root & "\" 'make sure we have \ at the end
    Dim AbsLevel As Long: AbsLevel = UBound(Split(root, "\")) - 1 'directory depth of root in the drive
    Dim RL As Long: RL = 0 'relative directory level - root=0
    Dim drv As String: drv = Left(root, 1)
'    Dim ColHeaders As String: ColHeaders = "Object,Name,Extension,Type,Size,Full path,Parent folder,Relative level,Attributes,Date created,Date Modified,Date accessed"
    
    Dim i As Long, j As Long
'    Stop
    Dim wb As Workbook
    If Not ActiveWorkbook Is Nothing Then
        Set wb = ActiveWorkbook
        If MsgBox("All files will be listed down from the ActiveCell. Do you want to continue?", vbYesNo + vbQuestion) = vbNo Then Exit Sub
    Else
        Set wb = Workbooks.Add
    End If
    
    i = 0
    Set cRng = ActiveCell
    Application.Calculation = xlCalculationManual
    Application.ScreenUpdating = False
    
    Call checkSubfolders42(root, 0)
    
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    wb.Activate
    
    If wb.Path = "" Then Application.Dialogs(xlDialogSaveAs).Show Else wb.Save
    
exitPoint:
    On Error Resume Next
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    
    Set wb = Nothing
    Set cRng = Nothing
    Exit Sub
    
errHandler:
    MsgBox "An error occurred." & vbCrLf & _
            "Number: " & Err.Number & vbCrLf & _
            "Description: " & Err.Description & vbCrLf & _
            "Error line: " & Erl, vbOKOnly


End Sub


Private Sub checkSubfolders42(strDirectory As String, curLevel As Long, Optional SubDepthLimit As Integer = -1, Optional FolderSize As Boolean = False)
    If SubDepthLimit > 0 Then _
        If curLevel > SubDepthLimit Then Exit Sub
    On Error Resume Next
    Dim objFSO As Object
    Dim objFolder As Object
    Dim objSubFolder As Object
    Dim objFile As Object
    Dim i As Integer, str1  As String, j As Long
    
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFolder = objFSO.getfolder(strDirectory)
    If objFolder.SubFolders.Count > 0 Then
        For Each objSubFolder In objFolder.SubFolders
            'RECURSION: Routine calls itself to drill down and check the contents before moving to next one
            checkSubfolders42 objSubFolder.Path, (curLevel + 1)
        Next objSubFolder
    End If
    
    For Each objFile In objFolder.Files
        cRng.Value = objFile.Path
        Set cRng = cRng.Offset(1)
    Next objFile
exitPoint:
    Set objFSO = Nothing
    Set objFolder = Nothing
    Set objSubFolder = Nothing
    Set objFile = Nothing
End Sub


Private Function BrowseForFolder(Optional OpenAt As Variant = 17) As Variant
     'Function purpose:  To Browser for a user selected folder.
     'If the "OpenAt" path is provided, open the browser at that directory
     'NOTE:  If invalid, it will open at the Desktop level
    Dim ShellApp As Object


     'Create a file browser window at the default folder
    Set ShellApp = CreateObject("Shell.Application").BrowseForFolder(0, "Please choose a folder", &H1, OpenAt)


     'Set the folder to that selected.  (On error in case cancelled)
    On Error Resume Next
    BrowseForFolder = ShellApp.Self.Path
    On Error GoTo 0


     'Destroy the Shell Application
    Set ShellApp = Nothing


     'Check for invalid or non-entries and send to the Invalid error handler if found
     'Valid selections can begin L: (where L is a letter) or \\ (as in \\servername\sharename.  All others are invalid
    Select Case Mid(BrowseForFolder, 2, 1)
    Case Is = ":"
        If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
    Case Is = "\"
        If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
    Case Else
        GoTo Invalid
    End Select


    Exit Function


Invalid:
     'If it was determined that the selection was invalid, set to False
    BrowseForFolder = False
End Function
 
Upvote 0
Re: how to count the total llines in all files in all subfolders

hi bobsan. thank you for the elaborate reply. how do i specify in your code which folder to look into?
 
Upvote 0
Re: how to count the total llines in all files in all subfolders

When you run it you will get a dialog box to select the folder.
 
Upvote 0
Re: how to count the total llines in all files in all subfolders

how do i change it to work for a specific folder? i want to set it up to update automatically
 
Upvote 0
Re: how to count the total llines in all files in all subfolders

Code:
....
Sub ScanFilesInSubfolders()
    On Error GoTo errHandler
    
'Select folder to be scanned
    Dim root As String: root =[COLOR=#ff0000]"your folder path here"[/COLOR]
    If UCase(root) = "FALSE" Then Exit Sub 'if no folder is selected
    If Left(root, 2) = "\\" Then MsgBox "Cannot scan network drives yet!", vbOKOnly: Exit Sub
    
    If Right(root, 1) <> "\" Then root = root & "\" 'make sure we have \ at the end
...
 
Upvote 0
Re: how to count the total llines in all files in all subfolders

ok it writes the list of files to active cell. now how do i store these names into variables or an array and run an if statement with the code i posted at the top to count lines in file in case its txt? sorry for needing you to do everything for me. im not very experienced in vba
 
Upvote 0
Re: how to count the total llines in all files in all subfolders

Why would you bother with code?
Your post shows that you want to use it as formula.
So if the filenames list is in column A starting from A1, then simply put this formula in column B starting from B1:
Code:
=countLF(A1)
if your function works properly you will see the results in column B

If you still want to incorporate it in the code for any reason, try this:
Code:
Option Explicit
Option Compare Text
Option Base 1




Private cRng As Range 'current cell - increasing with every new record
[COLOR=#0000ff]Private ac As Range[/COLOR]


Sub ScanFilesInSubfolders()
    On Error GoTo errHandler
    
'Select folder to be scanned
    Dim root As String: root = [I][COLOR=#ff0000]"your folder path here" [/COLOR][/I]
    
    If Right(root, 1) <> "\" Then root = root & "\" 'make sure we have \ at the end
    Dim AbsLevel As Long: AbsLevel = UBound(Split(root, "\")) - 1 'directory depth of root in the drive
    Dim RL As Long: RL = 0 'relative directory level - root=0
    Dim drv As String: drv = Left(root, 1)
'    Dim ColHeaders As String: ColHeaders = "Object,Name,Extension,Type,Size,Full path,Parent folder,Relative level,Attributes,Date created,Date Modified,Date accessed"
    
    Dim i As Long, j As Long
'    Stop
    Dim wb As Workbook
    If Not ActiveWorkbook Is Nothing Then
        Set wb = ActiveWorkbook
        If MsgBox("All files will be listed down from the ActiveCell. Do you want to continue?", vbYesNo + vbQuestion) = vbNo Then Exit Sub
    Else
        Set wb = Workbooks.Add
    End If
    
    i = 0
    Set cRng = ActiveCell
    Set ac = cRng
    Application.Calculation = xlCalculationManual
    Application.ScreenUpdating = False
    
    Call checkSubfolders42(root, 0)
    
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    wb.Activate
    
    If wb.Path = "" Then Application.Dialogs(xlDialogSaveAs).Show Else wb.Save
[COLOR=#0000ff]    [/COLOR]
[COLOR=#0000ff]    Set cRng = ac.Parent.Range(ac.Address & ":" & cRng.Address)[/COLOR]
[COLOR=#0000ff]    On Error Resume Next[/COLOR]
[COLOR=#0000ff]    For Each ac In cRng[/COLOR]
[COLOR=#0000ff]        If Len(ac.Value) > 0 Then[/COLOR]
[COLOR=#0000ff]            ac.Offset(0, 1).Value = countLF(ac.Value)[/COLOR]
[COLOR=#0000ff]        End If[/COLOR]
[COLOR=#0000ff]    Next ac[/COLOR]
            
exitPoint:
    On Error Resume Next
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    
    Set wb = Nothing
    Set cRng = Nothing
    Set ac = Nothing
    Exit Sub
    
errHandler:
    MsgBox "An error occurred." & vbCrLf & _
            "Number: " & Err.Number & vbCrLf & _
            "Description: " & Err.Description & vbCrLf & _
            "Error line: " & Erl, vbOKOnly


End Sub




Private Sub checkSubfolders42(strDirectory As String, curLevel As Long, Optional SubDepthLimit As Integer = -1, Optional FolderSize As Boolean = False)
    If SubDepthLimit > 0 Then _
        If curLevel > SubDepthLimit Then Exit Sub
    On Error Resume Next
    Dim objFSO As Object
    Dim objFolder As Object
    Dim objSubFolder As Object
    Dim objFile As Object
    Dim i As Integer, str1  As String, j As Long
    
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFolder = objFSO.getfolder(strDirectory)
    If objFolder.SubFolders.Count > 0 Then
        For Each objSubFolder In objFolder.SubFolders
            'RECURSION: Routine calls itself to drill down and check the contents before moving to next one
            checkSubfolders42 objSubFolder.Path, (curLevel + 1)
        Next objSubFolder
    End If
    
    For Each objFile In objFolder.Files
        cRng.Value = objFile.Path
        Set cRng = cRng.Offset(1)
    Next objFile
exitPoint:
    Set objFSO = Nothing
    Set objFolder = Nothing
    Set objSubFolder = Nothing
    Set objFile = Nothing
End Sub
 
Upvote 0
Re: how to count the total llines in all files in all subfolders

Why would you bother with code?
Your post shows that you want to use it as formula.
So if the filenames list is in column A starting from A1, then simply put this formula in column B starting from B1:
Code:
=countLF(A1)
if your function works properly you will see the results in column B

If you still want to incorporate it in the code for any reason, try this:
Code:
Option Explicit
Option Compare Text
Option Base 1




Private cRng As Range 'current cell - increasing with every new record
[COLOR=#0000ff]Private ac As Range[/COLOR]


Sub ScanFilesInSubfolders()
    On Error GoTo errHandler
   
'Select folder to be scanned
    Dim root As String: root = [I][COLOR=#ff0000]"your folder path here" [/COLOR][/I]
   
    If Right(root, 1) <> "\" Then root = root & "\" 'make sure we have \ at the end
    Dim AbsLevel As Long: AbsLevel = UBound(Split(root, "\")) - 1 'directory depth of root in the drive
    Dim RL As Long: RL = 0 'relative directory level - root=0
    Dim drv As String: drv = Left(root, 1)
'    Dim ColHeaders As String: ColHeaders = "Object,Name,Extension,Type,Size,Full path,Parent folder,Relative level,Attributes,Date created,Date Modified,Date accessed"
   
    Dim i As Long, j As Long
'    Stop
    Dim wb As Workbook
    If Not ActiveWorkbook Is Nothing Then
        Set wb = ActiveWorkbook
        If MsgBox("All files will be listed down from the ActiveCell. Do you want to continue?", vbYesNo + vbQuestion) = vbNo Then Exit Sub
    Else
        Set wb = Workbooks.Add
    End If
   
    i = 0
    Set cRng = ActiveCell
    Set ac = cRng
    Application.Calculation = xlCalculationManual
    Application.ScreenUpdating = False
   
    Call checkSubfolders42(root, 0)
   
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    wb.Activate
   
    If wb.Path = "" Then Application.Dialogs(xlDialogSaveAs).Show Else wb.Save
[COLOR=#0000ff]    
    Set cRng = ac.Parent.Range(ac.Address & ":" & cRng.Address)
    On Error Resume Next
    For Each ac In cRng
        If Len(ac.Value) > 0 Then
            ac.Offset(0, 1).Value = countLF(ac.Value)
        End If
    Next ac[/COLOR]
           
exitPoint:
    On Error Resume Next
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
   
    Set wb = Nothing
    Set cRng = Nothing
    Set ac = Nothing
    Exit Sub
   
errHandler:
    MsgBox "An error occurred." & vbCrLf & _
            "Number: " & Err.Number & vbCrLf & _
            "Description: " & Err.Description & vbCrLf & _
            "Error line: " & Erl, vbOKOnly


End Sub




Private Sub checkSubfolders42(strDirectory As String, curLevel As Long, Optional SubDepthLimit As Integer = -1, Optional FolderSize As Boolean = False)
    If SubDepthLimit > 0 Then _
        If curLevel > SubDepthLimit Then Exit Sub
    On Error Resume Next
    Dim objFSO As Object
    Dim objFolder As Object
    Dim objSubFolder As Object
    Dim objFile As Object
    Dim i As Integer, str1  As String, j As Long
   
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFolder = objFSO.getfolder(strDirectory)
    If objFolder.SubFolders.Count > 0 Then
        For Each objSubFolder In objFolder.SubFolders
            'RECURSION: Routine calls itself to drill down and check the contents before moving to next one
            checkSubfolders42 objSubFolder.Path, (curLevel + 1)
        Next objSubFolder
    End If
   
    For Each objFile In objFolder.Files
        cRng.Value = objFile.Path
        Set cRng = cRng.Offset(1)
    Next objFile
exitPoint:
    Set objFSO = Nothing
    Set objFolder = Nothing
    Set objSubFolder = Nothing
    Set objFile = Nothing
End Sub
This is a perfect code!
May I ask, how to make it as a function to call in a cell and extract just the number of files up to the deepethed subfolder?

Thanks for your assistance.
 
Upvote 0

Forum statistics

Threads
1,214,806
Messages
6,121,672
Members
449,045
Latest member
Marcus05

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top