Update VBA script to search subfolders excel - excel

I previously got help to write read through several textfiles in a folder and organize the data in a spreadsheet. I got this script from #trincot that worked well for my need. How to import specific text from files in to excel?
Sub ReadFilesIntoActiveSheet()
Dim fso As FileSystemObject
Dim folder As folder, file As file, FileText As TextStream
Dim TextLine As String
Dim cl As Range
Dim num As Long ' numerical part of key, as in "Ann:"
Dim col As Long ' target column in Excel sheet
Dim key As String ' Part before ":"
Dim value As String ' Part after ":"
' Get a FileSystem object
Set fso = New FileSystemObject
' Get the directory you want
Set folder = fso.GetFolder("D:\YourDirectory\")
' Set the starting point to write the data to
' Don't write in first row where titles are
Set cl = ActiveSheet.Cells(2, 1)
' Loop thru all files in the folder
For Each file In folder.Files
' Open the file
Set FileText = file.OpenAsTextStream(ForReading)
' Read the file one line at a time
Do While Not FileText.AtEndOfStream
TextLine = FileText.ReadLine 'read line
key = Split(TextLine & ":", ":")(0)
value = Trim(Mid(TextLine, Len(key)+2))
num = Val(Mid(key,2))
If num Then key = Replace(key, num, "") ' Remove number from key
col = 0
If key = "From" Then col = 1
If key = "Date" Then col = 2
If key = "A" Then col = 2 + num
If col Then
cl.Offset(, col-1).Value = value ' Fill cell
End If
Loop
' Clean up
FileText.Close
' Next row
Set cl = cl.Offset(1)
Next file
End Sub
The problem I figured out afterwards was that my textfiles will in time start to be stored in subfolders within a subfolder, and this script is not written to handle this.
I found this script by #Cor_Blimey here Loop Through All Subfolders Using VBA
Public Sub NonRecursiveMethod()
Dim fso, oFolder, oSubfolder, oFile, queue As Collection
Set fso = CreateObject("Scripting.FileSystemObject")
Set queue = New Collection
queue.Add fso.GetFolder("your folder path variable") 'obviously replace
Do While queue.Count > 0
Set oFolder = queue(1)
queue.Remove 1 'dequeue
'...insert any folder processing code here...
For Each oSubfolder In oFolder.SubFolders
queue.Add oSubfolder 'enqueue
Next oSubfolder
For Each oFile In oFolder.Files
'...insert any file processing code here...
Next oFile
Loop
End Sub
And the two answers here Loop through all subfolders and files under a folder and write the last modifed date information to an Excel spreadsheet by #L42 and #chris nielsen.
I also tried a bit with TraversFolder function, but I have not been able to incorporate any of these solutions into my existing script. Any help would be much appreciated!

Put your function in section marked "HERE COMES YOUR READING CODE
Function is one of mine I used in projects. I deleted the surplus code and it should do its task.
Sub index()
ThisWorkbook.Save
DoEvents
Dim intResult As Integer
Dim strPath As String
Dim objFSO As Object
Dim intCountRows As Integer
Application.FileDialog(msoFileDialogFolderPicker).Title = "Vyberte prosím složku"
Application.FileDialog(msoFileDialogFolderPicker).ButtonName = "Vybrat složku"
Application.FileDialog(msoFileDialogFolderPicker).AllowMultiSelect = True
intResult = Application.FileDialog(msoFileDialogFolderPicker).Show
If intResult = 0 Then
End
End If
For Each Item In Application.FileDialog(msoFileDialogFolderPicker).SelectedItems
strPath = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1) 'ulož cestu ke složce
Set objFSO = CreateObject("Scripting.FileSystemObject")
intCountRows = GetAllFiles(strPath, ROW_FIRST, objFSO)
Call GetAllFolders(strPath, objFSO, intCountRows)
Next Item
End Sub
Private Function GetAllFiles(ByVal strPath As String, ByVal intRow As Integer, ByRef objFSO As Object) As Integer
DoEvents
Dim objFolder As Object
Dim objFile As Object
Dim i As Integer
i = intRow + 1
Set objFolder = objFSO.GetFolder(strPath)
For Each objFile In objFolder.Files
If Right(objFile.Name, 3) = "txt" Then
'HERE COMES YOU READING CODE
i = i + 1
End If
Next objFile
GetAllFiles = i + ROW_FIRST - 1
End Function
Private Sub GetAllFolders(ByVal strFolder As String, ByRef objFSO As Object, ByRef intRow As Integer)
DoEvents
Dim objFolder As Object
Dim objSubFolder As Object
Set objFolder = objFSO.GetFolder(strFolder)
For Each objSubFolder In objFolder.subfolders
intRow = GetAllFiles(objSubFolder.Path, intRow, objFSO)
Call GetAllFolders(objSubFolder.Path, objFSO, intRow)
Next objSubFolder
End Sub

Related

VBA "object Variable or With block variable not set" with Shell application

I am trying to extract some data from a series of zip files and store them in the same sheet I'm working on. I have already extract name of each zip file and store them in one column of the sheet. I want to loop through them to extract data I need, however, I keep getting error of "run time error 91" when I access the oApp.Namespace(zipName).Items. Here is the VBA code I have, can anyone help me with that? Thanks!
Sub GetData()
Dim iRow As Integer 'row counter
Dim iCol As Integer 'column counter
Dim savePath As String 'place to save the extracted files
Dim fileContents As String 'contents of the file
Dim fso As FileSystemObject 'FileSystemObject to work with files
iRow = 1 'start at first row
iCol = 1 'start at frist column
'set the save path to the temp folder
savePath = Environ("TEMP")
'create the filesystem object
Set fso = New FileSystemObject
Do While ActiveSheet.Cells(iRow, iCol).Value <> ""
fileContents = fso.OpenTextFile(UnzipFile(savePath, ActiveSheet.Cells(iRow, iCol).Value, "Device-1_IR_VR_7-16-2019-2-32-55_PM.pda-iv.txt"), ForReading).ReadAll
ActiveSheet.Cells(iRow, iCol).Value = fileContents
iRow = iRow + 1
Loop
'free the memory
Set fso = Nothing
End Sub
Function UnzipFile(savePath As String, zipName As String, fileName As String) As String
Dim oApp As Shell
Dim strFile As String
'get a shell object
Set oApp = CreateObject("Shell.Application")
'check to see if the zip contains items
'Debug.Print oApp.Namespace(zipName).Items.Count
If Not IsNull(oApp.Namespace(zipName).Items) Then
If oApp.Namespace(zipName).Items.Count > 0 Then
Dim i As Integer
'loop through all the items in the zip file
For i = 0 To oApp.Namespace(zipName).Items.Count - 1
'check to see if it is the txt file
If UCase(oApp.Namespace(zipName).Items.Item(i)) = UCase(fileName) Then
'save the files to the new location
oApp.Namespace(savePath).CopyHere oApp.Namespace(zipName).Items.Item(i)
'set the location of the file
UnzipFile = savePath & "\" & fileName
'exit the function
Exit Function
End If
Next i
End If
End If
'free memory
Set oApp = Nothing
End Function
Swap your variables to Variant if they're going to be passed to Shell:
Sub GetData()
Dim iRow As Long 'row counter
Dim iCol As Long 'column counter
Dim savePath As Variant 'place to save the extracted files
Dim zipName As Variant
Dim txtPath As String
Dim fileContents As String 'contents of the file
Dim fso As FileSystemObject 'FileSystemObject to work with files
iRow = 1 'start at first row
iCol = 1 'start at first column
savePath = Environ("TEMP") 'set the save path to the temp folder
Set fso = New FileSystemObject 'create the filesystem object
Do While ActiveSheet.Cells(iRow, iCol).Value <> ""
zipName = ActiveSheet.Cells(iRow, iCol).Value
txtPath = UnzipFile(savePath, zipName, "Device-1_IR_VR_7-16-2019-2-32-55_PM.pda-iv.txt")
If Len(txtPath) > 0 Then 'if found the file...
fileContents = fso.OpenTextFile(txtPath, ForReading).ReadAll
ActiveSheet.Cells(iRow, iCol).Value = fileContents
End If
iRow = iRow + 1
Loop
End Sub
Function UnzipFile(savePath As Variant, zipName As Variant, fileName As String) As String
Dim oApp As Object, ns As Object, i As Long
Set oApp = CreateObject("Shell.Application") 'get a shell object
Set ns = oApp.Namespace(zipName) 'get the zip namespace
If ns.Items.Count > 0 Then
For i = 0 To ns.Items.Count - 1
'check to see if it is the txt file
If UCase(ns.Items.Item(i)) = UCase(fileName) Then
'save the files to the new location
oApp.Namespace(savePath).CopyHere ns.Items.Item(i)
UnzipFile = savePath & "\" & fileName 'return the location of the file
Exit Function
End If
Next i
End If
End Function

Import text files contents and name of text file and you separator into Excel with a macro

I have this code thanks to Import text files contents and name of text file into Excel with a macro
Option Explicit
Sub Import_video_txt_files()
' ADD REFERENCE TO MICROSOFT FILE SYSTEM OBJECT
Dim objFSO As FileSystemObject
Dim objFolder As folder
Dim objFile As file
Dim objTextStream As TextStream
Dim strPath As String
Dim i As Long
' Specify the folder...
strPath = "C:\Users\User\Desktop\TEST\"
' Use Microsoft Scripting runtime.
Set objFSO = New FileSystemObject
Set objFolder = objFSO.GetFolder(strPath)
' Check extension of each file in folder.
For Each objFile In objFolder.Files
If objFSO.GetExtensionName(objFile.Name) = "txt" Then
Cells(i + 2, 1) = objFile.Name
Set objTextStream = objFile.OpenAsTextStream(ForReading)
Cells(i + 2, 2) = objTextStream.ReadAll
i = i + 1
End If
Next
End Sub
However now I need to expand the function.
The text file has all the information on one line.
For example: grey, red, blue|408.95|14165.849841859
I am using this separator |
I would like to be able to import all the information from the text file and separate them using | and put them in their appropriate cells as illustrated in the image below.
Try,
Sub Import_video_txt_files()
' ADD REFERENCE TO MICROSOFT FILE SYSTEM OBJECT
Dim objFSO As FileSystemObject
Dim objFolder As folder
Dim objFile As file
Dim objTextStream As TextStream
Dim strPath As String
Dim i As Long
Dim s As String, vSplit
' Specify the folder...
strPath = "C:\Users\User\Desktop\TEST\"
' Use Microsoft Scripting runtime.
Set objFSO = New FileSystemObject
Set objFolder = objFSO.GetFolder(strPath)
' Check extension of each file in folder.
For Each objFile In objFolder.Files
If objFSO.GetExtensionName(objFile.Name) = "txt" Then
Cells(i + 2, 1) = objFile.Name
Set objTextStream = objFile.OpenAsTextStream(ForReading)
'Cells(i + 2, 2) = objTextStream.ReadAll
s = objTextStream.ReadAll
vSplit = Split(s, "|")
Range("b" & i + 2).Resize(1, UBound(vSplit) + 1) = vSplit
i = i + 1
End If
Next
End Sub
After importing your pipe data, run this short macro:
Sub PipeKleaner()
Dim i As Long, N As Long, s As String, arr
Dim v As String
N = Cells(Rows.Count, "B").End(xlUp).Row
For i = 1 To N
v = Cells(i, "B").Value
arr = Split(v, "|")
Cells(i, "C").Resize(1, UBound(arr) + 1).Value = arr
Next i
End Sub
NOTE:
This code does the parsing into column C and beyond rather than over-writing column B. If you don't need the original data, just change the Resize() code-line.

Open most recent folder within sub folder and open workbook based on name

As the title suggests, my objective is to open the most recently modified folder. Within this folder, I wish to open each sub folder and open each file with "summary" in it, then close. This is what i have so far:
Option Explicit
Function GetLastFolder(Path As String)
Dim FSO, FS, F, DtLast As Date, Result As String
Set FSO = CreateObject("scripting.FileSystemObject")
Set FS = FSO.GetFolder(Path).SubFolders
For Each F In FS
If F.DateLastModified > DtLast Then
DtLast = F.DateLastModified
Result = F.Name
End If
Next
GetLastFolder = Result
End Function
Sub OpenFolder()
Dim wb As Workbook
Dim Folder As String
GetLastFolder ("H:\myFile\")
Dim numberOfFolders As Long
numberOfFolders = GetLastFolder.Files.Count
mylist = Array("File1", "File2", "File3")
For i = 0 To numberOfFolders
If Folder.Exists(mylist(i)) Then
End If
Next i
End Sub
My function locates the most recent folder and the sub procedure is supposed to do the rest. I'm hoping that my loop will enter each sub folder numberOfFolder amount of times which is called the name of the array before opening the file. My attempt is weak, especially when I arrive at the loop. I'm not sure how to reference folders and files which are not pre-defined.
Your GetLastFolder seems fine.
Try this OpenFolder to get you going:
Sub OpenFolder()
Dim wb As Workbook
Dim Folder As String, sPath As String
Dim numberOfFolders As Long
Dim oFolder As Object, oSubFolder As Object, oFSO As Object
sPath = "C:\Program Files\"
numberOfFolders = 0
Set oFSO = CreateObject("Scripting.FileSystemObject")
Folder = GetLastFolder("C:\Program Files\")
Set oFolder = oFSO.getfolder(sPath + Folder)
For Each oSubFolder In oFolder.subfolders
numberOfFolders = numberOfFolders + 1
Next
MsgBox numberOfFolders
End Sub

List file names with links in excel

Is there a way to list file names across different directories in an excel sheet, with links (so one can click on the link beside the file name and the file would open)?
I'm ready to write a script, but I don't know of any particular method or command.
I don't want to be typing the whole thing.
I don't care about directory/tree structure, but file link should be present.
There is one directory which contains lots of other folders which contain the files I need to list, mostly *.pdf's.
Any help appreciated. Thanks!
You can use below code to get File name and File path Set main folder to strFolderPath
'Global Declaration for Start Row
Public lngRow As Long
Sub pReadAllFilesInDirectory()
Dim strFolderPath As String
Dim BlnInclude_subfolder As Boolean
'Set Path here
strFolderPath = "C:\"
'set start row
lngRow = 1
'Set this true if you want list of sub-folders as well
BlnInclude_subfolder = True
'---------- Reading of files in folders and sub-folders------
Call ListMyFiles(strFolderPath, BlnInclude_subfolder)
'---------- Reading of files in folders and sub-folders------
End Sub
Sub ListMyFiles(mySourcePath As String, blnIncludeSubfolders As Boolean)
Dim MyObject As Object
Dim mySource As Object
Dim mySubFolder As Object
Dim myfile As Object
Dim iCol As Long
Set MyObject = CreateObject("Scripting.FileSystemObject")
Set mySource = MyObject.GetFolder(mySourcePath)
'Loop in each file in Folder
For Each myfile In mySource.Files
iCol = 1
Sheet1.Cells(lngRow, iCol).Value = myfile.Name 'File Name
iCol = iCol + 1
Sheet1.Cells(lngRow, iCol).Value = myfile.Path 'File Path/Location
lngRow = lngRow + 1
Next
If blnIncludeSubfolders Then
For Each mySubFolder In mySource.SubFolders
Call ListMyFiles(mySubFolder.Path, True)
Next
End If
End Sub
A quick seach yielded this answer I believe you are looking for.
Sub Example1()
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim i As Integer
'Create an instance of the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Get the folder object
Set objFolder = objFSO.GetFolder("D:\Stuff\Business\Temp")
i = 1
'loops through each file in the directory
For Each objFile In objFolder.Files
'select cell
Range(Cells(i + 1, 1), Cells(i + 1, 1)).Select
'create hyperlink in selected cell
ActiveSheet.Hyperlinks.Add Anchor:=Selection, Address:= _
objFile.Path, _
TextToDisplay:=objFile.Name
i = i + 1
Next objFile
End Sub

Loop code keeps copying from the same excel spreadsheet in a folder

So I was trying to create a list of excel files in a folder (file name and path) and then use a For loop to copy and paste a specified worksheet for all of the files listed into a specified worksheet in the excel workbook that contains the macro. So far everything works except for the fact that the same file keeps getting copied and pasted over instead of all the files. The macro loops for the correct number of times, but it's not using all the excel files.
Here's the code:
First part for listing the files in the folder
Private Sub btn_LeaveReport()
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim i As Integer
'Create an instance of the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Get the folder object
Set objFolder = objFSO.GetFolder("D:\Administration\Time Sheets")
i = 2
'loops through each file in the directory and prints their names and path
For Each objFile In objFolder.Files
'print file name
Cells(i + 1, 2) = objFile.Name
'print file path
Cells(i + 1, 3) = objFile.Path
i = i + 1
Next objFile
End Sub
and this is the part for the loop
Private Sub btn_PullData()
'Declared Variables
Dim wbk As Workbook
Dim i As Integer
Dim StartAt As Integer
Dim EndAt As Integer
Dim CopyPath As String
Dim CopyPathRow As Integer
Dim iRow As Integer
'Ranges
StartAt = 1
EndAt = Val(ThisWorkbook.Worksheets("LeaveReport").Range("A1"))
CopyPathRow = 3
CopyPath = ThisWorkbook.Worksheets("LeaveReport").Range("C" & CopyPathRow)
iRow = 3
'Loop de loop
For i = StartAt To EndAt
Application.ScreenUpdating = False
Set wbk = Workbooks.Open(CopyPath)
Sheets("TIMESHEET").Select
Range("C12:S34").Select
Selection.Copy
ThisWorkbook.Activate
Sheets("Pastebin").Select
Range("a" & iRow).PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
iRow = iRow + 39
CopyPathRow = CopyPathRow + 1
wbk.Close True
Next i
Sheets("Pastebin").Select
Range("A:A").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Application.ScreenUpdating = True
MsgBox "Timesheet Data Imported"
End Sub
Based on the source of the error, i.e. same file being used, I'm guessing the issue lies with the part that has this:
CopyPath = ThisWorkbook.Worksheets("LeaveReport").Range("C" & CopyPathRow)
and is "supposed" to update in the For loop via this:
CopyPathRow = CopyPathRow + 1
Move the line
CopyPath = ThisWorkbook.Worksheets("LeaveReport").Range("C" & CopyPathRow)
Inside the loop, that value of CopyPath is never being changed, but the value of CopyPathRow is.
Edit: I wouldn't call this recursion either.

Resources