1Sub BatchImportTextFiles(sourceFolderPath As String, destinationSheetName As String, errorLogSheetName As String)
2' Imports data from multiple text files in a folder to a destination sheet.
3' Appends data and logs errors to a separate sheet.
4' Handles file access, format, and data type errors.
5
6Dim fso As Object ' FileSystemObject
7Dim folder As Object
8Dim file As Object
9Dim ts As Object ' TextStream
10Dim wsDest As Worksheet
11Dim wsErrorLog As Worksheet
12Dim lastDestRow As Long
13Dim lastErrorRow As Long
14Dim lineNum As Long
15Dim fileNum As Long
16Dim lineData() As String
17Dim importError As Boolean
18Dim errorDescription As String
19Dim headerRow As String
20Dim fileCounter As Integer
21
22' --- Initialization and Setup ---
23On Error GoTo ErrorHandler
24
25' Create FileSystemObject
26Set fso = CreateObject("Scripting.FileSystemObject")
27
28' Validate source folder
29If Not fso.FolderExists(sourceFolderPath) Then
30Err.Raise vbObjectError + 2001, "BatchImportTextFiles", "Source folder not found: " & sourceFolderPath
31End If
32Set folder = fso.GetFolder(sourceFolderPath)
33
34' Get destination worksheet, create if it doesn't exist
35On Error Resume Next
36Set wsDest = ThisWorkbook.Sheets(destinationSheetName)
37On Error GoTo ErrorHandler
38If wsDest Is Nothing Then
39Set wsDest = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
40wsDest.Name = destinationSheetName
41' Add header row if new sheet
42wsDest.Cells(1, 1).Value = "FileName"
43wsDest.Cells(1, 2).Value = "LineNumber"
44wsDest.Cells(1, 3).Value = "ErrorDescription"
45wsDest.Cells(1, 4).Value = "OriginalLine"
46lastDestRow = 1 ' Start appending from row 2
47Else
48lastDestRow = wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Row
49If lastDestRow = 1 And IsEmpty(wsDest.Cells(1, 1).Value) Then ' Handle case where sheet exists but is empty
50wsDest.Cells(1, 1).Value = "FileName"
51wsDest.Cells(1, 2).Value = "LineNumber"
52wsDest.Cells(1, 3).Value = "ErrorDescription"
53wsDest.Cells(1, 4).Value = "OriginalLine"
54lastDestRow = 1
55End If
56End If
57
58' Get error log worksheet, create if it doesn't exist
59On Error Resume Next
60Set wsErrorLog = ThisWorkbook.Sheets(errorLogSheetName)
61On Error GoTo ErrorHandler
62If wsErrorLog Is Nothing Then
63Set wsErrorLog = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
64wsErrorLog.Name = errorLogSheetName
65' Add header row for error log
66wsErrorLog.Cells(1, 1).Value = "FileName"
67wsErrorLog.Cells(1, 2).Value = "LineNumber"
68wsErrorLog.Cells(1, 3).Value = "ErrorDescription"
69wsErrorLog.Cells(1, 4).Value = "OriginalLine"
70lastErrorRow = 1
71Else
72lastErrorRow = wsErrorLog.Cells(wsErrorLog.Rows.Count, "A").End(xlUp).Row
73If lastErrorRow = 1 And IsEmpty(wsErrorLog.Cells(1, 1).Value) Then ' Handle case where sheet exists but is empty
74wsErrorLog.Cells(1, 1).Value = "FileName"
75wsErrorLog.Cells(1, 2).Value = "LineNumber"
76wsErrorLog.Cells(1, 3).Value = "ErrorDescription"
77wsErrorLog.Cells(1, 4).Value = "OriginalLine"
78lastErrorRow = 1
79End If
80End If
81
82' --- File Processing Loop ---
83Application.ScreenUpdating = False
84Application.EnableEvents = False ' Prevent worksheet events
85Application.Calculation = xlCalculationManual
86
87fileCounter = 0
88For Each file In folder.Files
89' Process only text files (e.g., .txt, .csv)
90If LCase(fso.GetExtensionName(file.Name)) = "txt" Or LCase(fso.GetExtensionName(file.Name)) = "csv" Then
91fileCounter = fileCounter + 1
92lineNum = 0
93importError = False
94errorDescription = ""
95
96' Get a free file number
97fileNum = FreeFile
98
99On Error Resume Next ' Handle file open/read errors
100Set ts = fso.OpenTextFile(file.Path, 1) ' 1 for reading
101If Err.Number <> 0 Then
102importError = True
103errorDescription = "Error opening file: " & Err.Description
104GoTo LogError
105End If
106On Error GoTo ErrorHandler ' Reset to main error handler
107
108' Read file line by line
109Do While Not ts.AtEndOfStream
110lineNum = lineNum + 1
111Dim originalLine As String
112originalLine = ts.ReadLine
113
114' Attempt to parse and import the line
115On Error Resume Next ' Handle parsing/data type errors
116lineData = Split(originalLine, ",") ' Assuming comma-separated values
117If Err.Number <> 0 Then
118importError = True
119errorDescription = "Error splitting line: " & Err.Description
120GoTo LogError
121End If
122
123' Basic check for expected number of columns (adjust delimiter if needed)
124' This is a simplified check; more robust validation might be needed
125If UBound(lineData) < 0 Then ' Empty line or parsing issue
126If Trim(originalLine) <> "" Then ' If not just an empty line
127importError = True
128errorDescription = "Line appears malformed or empty after split."
129GoTo LogError
130End If
131Else
132' Append data to destination sheet
133lastDestRow = wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Row + 1
134wsDest.Cells(lastDestRow, 1).Value = file.Name ' Store filename
135wsDest.Cells(lastDestRow, 2).Value = lineNum ' Store line number
136wsDest.Cells(lastDestRow, 3).Value = "Success"
137wsDest.Cells(lastDestRow, 4).Value = originalLine ' Store original line for reference
138
139' Populate actual data columns
140Dim colIndex As Integer
141For colIndex = 0 To UBound(lineData)
142' Ensure destination column exists, expand if necessary
143If wsDest.Cells(1, 5 + colIndex).Value = "" Then
144wsDest.Cells(1, 5 + colIndex).Value = "Col " & (colIndex + 1) ' Auto-generate header
145End If
146wsDest.Cells(lastDestRow, 5 + colIndex).Value = Trim(lineData(colIndex))
147Next colIndex
148End If
149On Error GoTo ErrorHandler ' Reset to main error handler
150
151Loop
152ts.Close
153End If
154Next file
155
156' --- Finalization ---
157Application.ScreenUpdating = True
158Application.EnableEvents = True
159Application.Calculation = xlCalculationAutomatic
160
161If fileCounter = 0 Then
162MsgBox "No text files (.txt or .csv) found in the specified folder.", vbExclamation
163ElseIf lastErrorRow > 1 Then ' Check if any errors were logged
164MsgBox "Batch import completed with errors. Please check the '" & errorLogSheetName & "' sheet.", vbExclamation
165Else
166MsgBox "Batch import completed successfully.", vbInformation
167End If
168
169Exit Sub
170
171LogError:
172' Log the error to the error log sheet
173lastErrorRow = wsErrorLog.Cells(wsErrorLog.Rows.Count, "A").End(xlUp).Row + 1
174wsErrorLog.Cells(lastErrorRow, 1).Value = file.Name
175wsErrorLog.Cells(lastErrorRow, 2).Value = lineNum
176wsErrorLog.Cells(lastErrorRow, 3).Value = errorDescription
177wsErrorLog.Cells(lastErrorRow, 4).Value = originalLine
178
179' If error occurred during file open, mark it
180If ts Is Nothing Then ' Error opening file
181' No 'originalLine' to log in this specific case, but we have file name and error desc
182Else
183ts.Close ' Ensure stream is closed if opened
184End If
185importError = True ' Flag that an error occurred for this file/line
186GoTo ContinueProcessing ' Continue to next file/line if possible
187
188ContinueProcessing:
189If Not ts Is Nothing Then
190If Not ts.AtEndOfStream Then ' If not end of stream, try to continue reading
191Resume Next ' Attempt to continue reading from the current file
192Else
193ts.Close
194End If
195End If
196GoTo SkipMainErrorHandler ' Prevent main handler from firing if we handled it
197
198ErrorHandler:
199Application.ScreenUpdating = True
200Application.EnableEvents = True
201Application.Calculation = xlCalculationAutomatic
202
203If Not ts Is Nothing Then ts.Close ' Ensure file is closed
204
205If Err.Number = vbObjectError + 2001 Then ' Specific folder not found error
206MsgBox Err.Description, vbCritical
207ElseIf importError Then ' Error logged in LogError section
208' Message already displayed or handled by LogError logic
209' If we reached here due to an unhandled error after LogError, show it
210If Err.Number <> 0 Then
211MsgBox "An unhandled error occurred during processing: " & Err.Description & " (Error " & Err.Number & ")", vbCritical
212End If
213Else ' General unexpected error
214MsgBox "An unexpected error occurred: " & Err.Description & " (Error " & Err.Number & ")", vbCritical
215End If
216On Error GoTo 0 ' Reset error handling
217
218SkipMainErrorHandler:
219
220End Sub