
Cómo dividir un CSV grande en varios CSV más pequeños
Hace poco me encontré con una pregunta en un foro en la que el usuario necesitaba una forma de dividir un archivo CSV enorme en varios archivos más pequeños y conservar la fila de encabezado en cada uno de los archivos más pequeños. En este caso, la pregunta giraba en torno a JavaScript, pero me hizo pensar en cómo se podría abordar en VB/VBA/VBScript.
Bien, a continuación se presenta un primer intento por abordar una posible solución a esta cuestión.
Función VBA para dividir un archivo CSV
Function CSV_Split(ByVal sSrcCSVFile As String, _
ByVal sOutputFolder As String, _
ByVal lSplitCSVMaxRowCount As Long, _
Optional ByVal sOpenDestFolder As Boolean = True) As Boolean
Dim iFileNumber As Integer
Dim sLine As String
Dim sHeader As String
Dim lLineCounter As Long
Dim iFileCounter As Integer
Dim sOutputFile As String
Dim iOutputFileNumber As Integer
If Right(sOutputFolder, 1) "\" Then sOutputFolder = sOutputFolder & "\" ' Ensure the proper formatting of the folder path
iFileCounter = 1 ' Initialize the split file counter
' Open the source CSV for reading its content
iFileNumber = FreeFile
Open sSrcCSVFile For Input As #iFileNumber
Line Input #iFileNumber, sHeader 'Grab the 1st line as the Header to be used in each file we create
' Loop through each line of the source CSV file
Do While Not EOF(iFileNumber)
' If line count is zero, create a new output file and write the sHeader line to it
If lLineCounter = 0 Then
sOutputFile = sOutputFolder & iFileCounter & ".csv"
iOutputFileNumber = FreeFile
Open sOutputFile For Output As #iOutputFileNumber
Print #iOutputFileNumber, sHeader
End If
Line Input #iFileNumber, sLine ' Read a single line from the source file
Print #iOutputFileNumber, sLine ' Write the current line to the output file
lLineCounter = lLineCounter + 1 ' Increment line counter
' If the current line count reaches the max allowable row count,
' close the current output file and reset the line count and index the file counter
If lLineCounter >= lSplitCSVMaxRowCount Then
Close #iOutputFileNumber
lLineCounter = 0
iFileCounter = iFileCounter + 1
End If
Loop
' Close any open files
If lLineCounter > 0 Then Close #iOutputFileNumber
Close #iFileNumber
CSV_Split = True 'If we made it here, everything worked and we should have the split files in the output folder
If sOpenDestFolder Then Application.FollowHyperlink sOutputFolder 'Open the destination folder if requested
End Function
Luego para utilizar la función simplemente haces:
'Take the C:\Temp\testing.csv and break it into files containing a maximum of 15000 rows and save the resulting split CSVs in the C:\Temp\SplitCSV\ folder and don't open the folder once the operation is complete. If CSV_Split("C:\Temp\testing.csv", "C:\Temp\SplitCSV\", 15000, False) Then 'We're here because everything worked End If
Como es habitual, no olvides añadir un manejo de errores adecuado en todo momento.
Algo para considerar
Un enfoque alternativo sería leer el archivo CSV en la memoria (en una variable VBA) de una sola vez en lugar de hacerlo línea por línea, dividir la variable en una matriz y procesar la matriz. Sospecho que esto sería un poco más rápido.