I have a folder of SQL files which I need to loop through and:
- Determine if any of the files are over 20MB
- If so, split them into multiple files, max 20MB filesize
However, there's a complication in that the original large file will have a header and a footer which needs to be included (and slightly tweaked) in each one of the broken down files.
Here is a graphical representation, if it helps. It's based on one file in particular, which is 130MB, with around 1.8m rows
Of course I’m very happy to receive any and all feedback about my code. However, my main issue is that my current code takes around 20 minutes to break this main file into seven smaller counterparts. Therefore, any speed improvements would be fantastic!
Option Explicit
Private Type TFile
Path As String
Name As String
Extension As String
FullPath As String
Size As String
Data() As String
CurrentBodyPosition As Long
HeaderStart As Long
HeaderEnd As Long
FooterStart As Long
FooterEnd As Long
End Type
Private File As TFile
Public Sub SplitLargeFiles()
Dim newFile As String
Dim i As Long, j As Long, numberOfNewFiles As Long, rowsPerNewFile As Long
With File
.HeaderStart = 0 'header always in the same position
.HeaderEnd = 11
.CurrentBodyPosition = .HeaderEnd + 1
.Path = "\\...\"
.Extension = ".sql"
.Name = Replace(Dir(.Path & "*" & .Extension), .Extension, "") 'name only, no extension
End With
Do While Len(File.Name) > 0
File.FullPath = File.Path & File.Name & File.Extension
File.Size = FileLen(File.FullPath) / 1000000 'filesize in MB
Debug.Print File.Size
If File.Size >= 20 Then
With File
'open file, transfer data to an array and close it
Open .FullPath For Input As #1
.Data = Split(input(LOF(1), #1), vbNewLine)
.Data(0) = Replace(.Data(0), .Name, .Name & "_0") 'specific tweak to data
Close #1
'now assign footer positions
.FooterStart = UBound(.Data) - 5
.FooterEnd = UBound(.Data)
End With
'determine how many files to split the data across, and hence how many rows each new file needs
numberOfNewFiles = WorksheetFunction.RoundUp(File.Size / 22, 0) '22 gives a buffer over 20
rowsPerNewFile = (CLng(UBound(File.Data)) - CLng(18)) / numberOfNewFiles
For i = 1 To numberOfNewFiles
newFile = File.Path & File.Name & "_" & i & File.Extension
Open newFile For Output As #2
'make iterative tweak to first row of header data
File.Data(0) = Replace(File.Data(0), "_" & (i - 1), "_" & i)
'transfer header data
For j = File.HeaderStart To File.HeaderEnd
Print #2, File.Data(j)
Next j
'transfer body of data
For j = 1 To rowsPerNewFile
If File.CurrentBodyPosition < File.FooterStart Then
Print #2, File.Data(File.CurrentBodyPosition)
File.CurrentBodyPosition = File.CurrentBodyPosition + 1
Else
Exit For
End If
Next j
'transfer footer data
For j = File.FooterStart To File.FooterEnd
Print #2, File.Data(j)
Next j
Close #2
Next i
End If
File.Name = Replace(Dir(), File.Extension, "")
Loop
End Sub