VBA project - import several CVS files into excel workbook

Status
Niet open voor verdere reacties.

oederdekoe

Gebruiker
Lid geworden
2 mei 2013
Berichten
17
Hoi

Ik had eerder al een topic gestart hier, maar aangezien dit een volledig andere vraag is, leek het me wel beter een nieuw topic te starten.

HET PLAN :
Begin situatie => Een bestaand workbook met de naam "BEV project", met 1 bestaande sheet "INFO" met daarop een knop.
Doel =>
1. Bij druk op de knop zouden er 7 verschillende CSV files in de workbook geïmporteerd moeten worden. (iedere CSV file heeft slechts 1 sheet)
2. Als naam voor de 7 nieuwe sheets, zou telkens de naam van het bronbestand overgenomen moeten worden. (of de naam van de bronsheet, want die is ook gelijk aan de bestandsnaam)

De 7 files zijn de volgende :
- Personen.csv
- EJ.csv
- EN.csv
- OJ.csv
- NIET.csv
- WEL tot nu.csv
- WEL totaal.csv
Deze bronbestanden staan allen op de desktop in de map "BEV brondata"

Ik heb online wel al iets van code gevonden (bron), maar zelfs met alle uitleg erbij begrijp ik er nougabollen van :
Code:
Macro to parse a csv or txt file

If for some reason you don't want to use Excel's built-in import functions, you can parse ("read") a csv or txt file using code.

There is no reason to reinvent the wheel, and the following code, which I found on the internet, works just fine. I don't know the author, but he deserves the credit.

You can copy the code and insert it into a VBA module. Just highlight it with the mouse, press CTRL+C and insert with CTRL+V. If you are viewing this page on a small screen, some of the code lines may appear "broken," but they will be okay when you paste into a VBA module.

Option Explicit

Sub ImportFile()
Dim sPath As String
'Below we assume that the file, csvtest.csv,
'is in the same folder as the workbook. If
'you want something more flexible, you can
'use Application.GetOpenFilename to get a
'file open dialogue that returns the name
'of the selected file.
'On the page Fast text file import
'I show how to do that - just replace the 
'file pattern "txt" with "csv".
sPath = ThisWorkbook.Path & "\csvtest.csv"

'Procedure call. Semicolon is defined as separator,
'and data is to be inserted on "Sheet2".
'Of course you could also read the separator
'and sheet name from the worksheet or an input
'box. There are several options.
copyDataFromCsvFileToSheet sPath, ";", "Sheet2"

End Sub
'**************************************************************
Private Sub copyDataFromCsvFileToSheet(parFileName As String, _
parDelimiter As String, parSheetName As String)

Dim Data As Variant  'Array for the file values

'Function call - the file is read into the array
Data = getDataFromFile(parFileName, parDelimiter)

'If the array isn't empty it is inserted into
'the sheet in one swift operation.
If Not isArrayEmpty(Data) Then
  'If you want to operate directly on the array,
  'you can leave out the following lines.
  With Sheets(parSheetName)
    'Delete any old content
    .Cells.ClearContents
    'A range gets the same dimensions as the array
    'and the array values are inserted in one operation.
    .Cells(1, 1).Resize(UBound(Data, 1), UBound(Data, 2)) = Data
  End With
End If
'**************************************************************
Public Function isArrayEmpty(parArray As Variant) As Boolean
'Returns False if not an array or a dynamic array
'that hasn't been initialised (ReDim) or
'deleted (Erase).

If IsArray(parArray) = False Then isArrayEmpty = True
On Error Resume Next
If UBound(parArray) < LBound(parArray) Then
   isArrayEmpty = True
   Exit Function
Else
   isArrayEmpty = False
End If

End Function
'**************************************************************
Private Function getDataFromFile(parFileName As String, _
parDelimiter As String, _
Optional parExcludeCharacter As String = "") As Variant
'parFileName is the delimited file (csv, txt ...)
'parDelimiter is the separator, e.g. semicolon.
'The function returns an empty array, if the file
'is empty or cannot be opened.
'Number of columns is based on the line with most
'columns and not the first line.
'parExcludeCharacter: Some csv files have strings in
'quotations marks ("ABC"), and if parExcludeCharacter = """"
'quotation marks are removed.

Dim locLinesList() As Variant 'Array
Dim locData As Variant        'Array
Dim i As Long                 'Counter
Dim j As Long                 'Counter
Dim locNumRows As Long        'Nb of rows
Dim locNumCols As Long        'Nb of columns
Dim fso As Variant            'File system object
Dim ts As Variant             'File variable
Const REDIM_STEP = 10000      'Constant

'If this fails you need to reference Microsoft Scripting Runtime.
'You select this in "Tools" (VBA editor menu).
Set fso = CreateObject("Scripting.FileSystemObject")

On Error GoTo error_open_file
'Sets ts = the file
Set ts = fso.OpenTextFile(parFileName)
On Error GoTo unhandled_error

'Initialise the array
ReDim locLinesList(1 To 1) As Variant
i = 0
'Loops through the file, counts the number of lines (rows)
'and finds the highest number of columns.
Do While Not ts.AtEndOfStream
  'If the row number Mod 10000 = 0
  'we redimension the array.
  If i Mod REDIM_STEP = 0 Then
    ReDim Preserve locLinesList _
    (1 To UBound(locLinesList, 1) + REDIM_STEP) As Variant
  End If
  locLinesList(i + 1) = Split(ts.ReadLine, parDelimiter)
  j = UBound(locLinesList(i + 1), 1) 'Nb of columns in present row
  'If the number of columns is then highest so far.
  'the new number is saved.
  If locNumCols < j Then locNumCols = j
  i = i + 1
Loop

ts.Close 'Close file

locNumRows = i

'If number of rows is zero
If locNumRows = 0 Then Exit Function

ReDim locData(1 To locNumRows, 1 To locNumCols + 1) As Variant

'Copies the file values into an array.
'If parExcludeCharacter has a value,
'the characters are removed.
If parExcludeCharacter <> "" Then
  For i = 1 To locNumRows
    For j = 0 To UBound(locLinesList(i), 1)
      If Left(locLinesList(i)(j), 1) = parExcludeCharacter Then
        If Right(locLinesList(i)(j), 1) = parExcludeCharacter Then
          locLinesList(i)(j) = _
          Mid(locLinesList(i)(j), 2, Len(locLinesList(i)(j)) - 2)
        Else
          locLinesList(i)(j) = _
          Right(locLinesList(i)(j), Len(locLinesList(i)(j)) - 1)
        End If
      ElseIf Right(locLinesList(i)(j), 1) = parExcludeCharacter Then
        locLinesList(i)(j) = _
        Left(locLinesList(i)(j), Len(locLinesList(i)(j)) - 1)
      End If
      locData(i, j + 1) = locLinesList(i)(j)
    Next j
  Next i
Else
  For i = 1 To locNumRows
    For j = 0 To UBound(locLinesList(i), 1)
      locData(i, j + 1) = locLinesList(i)(j)
    Next j
  Next i
End If

getDataFromFile = locData

Exit Function

error_open_file:  'Returns empty Variant
unhandled_error:  'Returns empty Variant

End Function
Geen flauw idee wat ik moet vervangen door wat, om dit aan mijn specifieke situatie aan te passen. Dit gaat echt m'n petje te boven :confused:
Zonder jullie hulp wordt het niks. :(

Alvast 1000 maal dank !
 
Laatst bewerkt:
Lees je vraag nog eens goed door. Ik ben niet bekend met cvs bestanden.
 
Om met VBA te werken moet je heel erg nauwkeurig zijn.
Ik vind jouw vraag geen vraag maar een opdracht. Dat past in mijn ogen niet in een forum.
 
Je hebt wellicht helemaal gelijk...
Ik ben dan ook maar heel naarstig aan de slag gegaan, en ik denk er min of meer uit te zijn.
Vermoedelijk ziet mijn code er dan ook veel omslachtiger uit dan dat jullie het zouden doen... but who cares, als het maar werkt he :cool:

Voorlopig nog even in aparte stappen, tot ik zeker ben dat alles werkt. Daarna voeg ik alles samen tot 1 geheel.

Stap 1: importeren van de cvs files
Code:
Option Explicit
Sub Stap1()
'
' Import csv file "Personen"
'
    ActiveWorkbook.Worksheets.Add(After:=Sheets(Sheets.Count)).Name = "Personen"
    With ActiveSheet.QueryTables.Add(Connection:= _
        "TEXT;\\SRV-NAS-01\CtxProfiles$\Redirections\VhorenbK.SECURIS\Desktop\BEV brondata\Personen.csv" _
        , Destination:=Range("$A$1"))
        .Name = "Personen"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 1252
        .TextFileStartRow = 1
        .TextFileParseType = xlDelimited
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = False
        .TextFileSemicolonDelimiter = True
        .TextFileCommaDelimiter = False
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = Array(1, 1, 1, 1)
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With
'
' Import csv file "EJ"
'
    ActiveWorkbook.Worksheets.Add(After:=Sheets(Sheets.Count)).Name = "EJ"
    With ActiveSheet.QueryTables.Add(Connection:= _
        "TEXT;\\SRV-NAS-01\CtxProfiles$\Redirections\VhorenbK.SECURIS\Desktop\BEV brondata\EJ.csv" _
        , Destination:=Range("$A$1"))
        .Name = "EJ"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 850
        .TextFileStartRow = 1
        .TextFileParseType = xlDelimited
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = False
        .TextFileSemicolonDelimiter = True
        .TextFileCommaDelimiter = False
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = Array(1, 1, 1, 1, 1)
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With
'
' Import csv file "EN"
'
    ActiveWorkbook.Worksheets.Add(After:=Sheets(Sheets.Count)).Name = "EN"
    With ActiveSheet.QueryTables.Add(Connection:= _
        "TEXT;\\SRV-NAS-01\CtxProfiles$\Redirections\VhorenbK.SECURIS\Desktop\BEV brondata\EN.csv" _
        , Destination:=Range("$A$1"))
        .Name = "EN"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 850
        .TextFileStartRow = 1
        .TextFileParseType = xlDelimited
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = False
        .TextFileSemicolonDelimiter = True
        .TextFileCommaDelimiter = False
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = Array(1, 1, 1, 1, 1)
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With
'
' Import csv file "OJ"
'
    ActiveWorkbook.Worksheets.Add(After:=Sheets(Sheets.Count)).Name = "OJ"
    With ActiveSheet.QueryTables.Add(Connection:= _
        "TEXT;\\SRV-NAS-01\CtxProfiles$\Redirections\VhorenbK.SECURIS\Desktop\BEV brondata\OJ.csv" _
        , Destination:=Range("$A$1"))
        .Name = "OJ"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 850
        .TextFileStartRow = 1
        .TextFileParseType = xlDelimited
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = False
        .TextFileSemicolonDelimiter = True
        .TextFileCommaDelimiter = False
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = Array(1, 1, 1, 1, 1)
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With
'
' Import csv file "WEL tot nu"
'
    ActiveWorkbook.Worksheets.Add(After:=Sheets(Sheets.Count)).Name = "WEL tot nu"
    With ActiveSheet.QueryTables.Add(Connection:= _
        "TEXT;\\SRV-NAS-01\CtxProfiles$\Redirections\VhorenbK.SECURIS\Desktop\BEV brondata\WEL tot nu.csv" _
        , Destination:=Range("$A$1"))
        .Name = "WEL tot nu"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 850
        .TextFileStartRow = 1
        .TextFileParseType = xlDelimited
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = False
        .TextFileSemicolonDelimiter = True
        .TextFileCommaDelimiter = False
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = Array(1, 1, 1, 1)
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With
'
' Import csv file "WEL totaal"
'
    ActiveWorkbook.Worksheets.Add(After:=Sheets(Sheets.Count)).Name = "WEL totaal"
    With ActiveSheet.QueryTables.Add(Connection:= _
        "TEXT;\\SRV-NAS-01\CtxProfiles$\Redirections\VhorenbK.SECURIS\Desktop\BEV brondata\WEL totaal.csv" _
        , Destination:=Range("$A$1"))
        .Name = "WEL totaal"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 850
        .TextFileStartRow = 1
        .TextFileParseType = xlDelimited
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = False
        .TextFileSemicolonDelimiter = True
        .TextFileCommaDelimiter = False
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = Array(1, 1, 1, 1)
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With
  
    Sheets("START").Select
    
End Sub

Stap 2: range converteren naar table
Code:
    Sub Stap2()
    '
    ' Delete Row 2 & Column D
    '
        Sheets(Array("Personen", "EJ", "EN", "OJ", "WEL tot nu", "WEL totaal")).Select
        Rows("2:2").Select
        Selection.Delete Shift:=xlUp
        Columns("D:D").Select
        Selection.Delete Shift:=xlToLeft
    '
    ' Convert Querytables to ListObjects
    ' + Sort Column "Persoon" AtoZ
    '
        Sheets("Personen").Select
        ActiveSheet.QueryTables("Personen").Delete
        ActiveSheet.ListObjects.Add(xlSrcRange, Range("A1").CurrentRegion, , xlYes).Name = "Personen"
        ActiveSheet.ListObjects(1).ListColumns("persoon").DataBodyRange.Sort "persoon", , , , , , , 0
        
        Sheets("EJ").Select
        ActiveSheet.QueryTables("EJ").Delete
        ActiveSheet.ListObjects.Add(xlSrcRange, Range("A1").CurrentRegion, , xlYes).Name = "EJ"
        ActiveSheet.ListObjects(1).ListColumns("persoon").DataBodyRange.Sort "persoon", , , , , , , 0
        ActiveSheet.ListObjects(1).ShowTotals = True
    
        Sheets("EN").Select
        ActiveSheet.QueryTables("EN").Delete
        ActiveSheet.ListObjects.Add(xlSrcRange, Range("A1").CurrentRegion, , xlYes).Name = "EN"
        ActiveSheet.ListObjects(1).ListColumns("persoon").DataBodyRange.Sort "persoon", , , , , , , 0
        ActiveSheet.ListObjects(1).ShowTotals = True
        
        Sheets("OJ").Select
        ActiveSheet.QueryTables("OJ").Delete
        ActiveSheet.ListObjects.Add(xlSrcRange, Range("A1").CurrentRegion, , xlYes).Name = "OJ"
        ActiveSheet.ListObjects(1).ListColumns("persoon").DataBodyRange.Sort "persoon", , , , , , , 0
        ActiveSheet.ListObjects(1).ShowTotals = True
        
        Sheets("WEL tot nu").Select
        ActiveSheet.QueryTables("WEL tot nu").Delete
        ActiveSheet.ListObjects.Add(xlSrcRange, Range("A1").CurrentRegion, , xlYes).Name = "WEL tot nu"
        ActiveSheet.ListObjects(1).ListColumns("persoon").DataBodyRange.Sort "persoon", , , , , , , 0
        ActiveSheet.ListObjects(1).ShowTotals = True
        
        Sheets("WEL totaal").Select
        ActiveSheet.QueryTables("WEL totaal").Delete
        ActiveSheet.ListObjects.Add(xlSrcRange, Range("A1").CurrentRegion, , xlYes).Name = "WEL totaal"
        ActiveSheet.ListObjects(1).ListColumns("persoon").DataBodyRange.Sort "persoon", , , , , , , 0
        ActiveSheet.ListObjects(1).ShowTotals = True
        
    End Sub

Het enige dat nog ontbreekt is een COUNT variant van ShowTotals, om het aantla werknemers te tellen op sheet "Personen"
Dat vind ik niet zo meteen zonder veel poespas aan code bij te halen.
Code:
ActiveSheet.ListObjects(1).ShowTotals = True

Hopelijk wordt dit niet als een opdracht gezien. :confused: Ditmaal heb ik echt m'n best gedaan om het zelf uit te pluizen. Met 98% resultaat :thumb:
 

Thanks hellboy01 !! :thumb::thumb:
Een bijzonder goed instructiefilmpje, dat ook voor een noob als ik duidelijk uitlegt wat elk stukje van de code doet.

Nu is mijn code wel "af", maar die loop lijkt me wel interessant om het een stuk in te korten.
En vooral ook interesssant voor als ik mijn werk ooit eens moet overdragen naar een collega, die zijn bestanden uiteraard op een andere locatie zal bewaren dan ik.
 
Als alle csv bestanden in dezelfde map staan, en er verder geen csv bestanden bijstaan die niet mogen worden geïmporteerd, kun je ze met een simpele lus inlezen.
Code:
Sub Stap1()
Dim newSheet As Worksheet
Dim sPad As String, sFile As String
    sPad = "\\SRV-NAS-01\CtxProfiles$\Redirections\VhorenbK.SECURIS\Desktop\BEV brondata\"
    sFile = Dir(sPad & "*.csv")
    Do While sFile <> ""
        Set newSheet = ActiveWorkbook.Worksheets.Add(After:=Sheets("Personen"))
        newSheet.Name = Left(sFile, InStr(1, sFile, "csv") - 2)
        With newSheet.QueryTables.Add(Connection:="TEXT;" & sPad & sFile, Destination:=Range("$A$1"))
            .Name = Left(sFile, InStr(1, sFile, "csv") - 2)
            .FieldNames = True
            .RowNumbers = False
            .FillAdjacentFormulas = False
            .PreserveFormatting = True
            .RefreshOnFileOpen = False
            .RefreshStyle = xlInsertDeleteCells
            .SavePassword = False
            .SaveData = True
            .AdjustColumnWidth = True
            .RefreshPeriod = 0
            .TextFilePromptOnRefresh = False
            .TextFilePlatform = 1252
            .TextFileStartRow = 1
            .TextFileParseType = xlDelimited
            .TextFileTextQualifier = xlTextQualifierDoubleQuote
            .TextFileConsecutiveDelimiter = False
            .TextFileTabDelimiter = False
            .TextFileSemicolonDelimiter = True
            .TextFileCommaDelimiter = False
            .TextFileSpaceDelimiter = False
            .TextFileColumnDataTypes = Array(1, 1, 1, 1)
            .TextFileTrailingMinusNumbers = True
            .Refresh BackgroundQuery:=False
        End With
    sFile = Dir
    Loop
End Sub
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan