CSV-Dateien lesen und verarbeiten

  • Hallo zusammen...

    Als Neuling habe ich mich schwer getan, das lesen einer CSV-Datei zu realisieren, aber es hat am Ende doch geklappt.
    Vielleicht hätte man das anders oder besser lösen können, aber das ist es, wie ich es nun umgesetzt habe.

    Als "Aufgabe" hatte ich folgende Voraussetztung:


    • Eine CSV-Datei mit 5 Spalten und einer nicht angegebenen Zahl an Zeilen soll gelesen werden.
    • In jeder Zeile sollen die Werte der 5 Spalten in eine Variable verfügbar sein, um sie hinterher weiter zu verwenden.
    • Ist die Zeile abgearbeitet soll die nächste genommen werden (ist ja fast logisch, oder :) )

    Da ich denke, dass auch andere "Newbies" mit CSV-Dateien hantieren müssen/wollen, stelle ich hier mein Beispiel-Script zur Verfügung.
    Kommentare, Verbesserungvorschläge etc. ausdrücklich erwünscht ;)

    Gruß, Matthias

    Beispiel CSV-Datei:

    Code
    Zeile1Wert1;Zeile1Wert2;Zeile1Wert3;Zeile1Wert4;Zeile1Wert5 
    Zeile2Wert1;Zeile2Wert2;Zeile2Wert3;Zeile2Wert4;Zeile2Wert5 
    Zeile3Wert1;Zeile3Wert2;Zeile3Wert3;Zeile3Wert4;Zeile3Wert5

    AutoIt-Script:

    [autoit]


    ;Include die benötigte UDF's
    #include <File.au3>
    #include <Array.au3>

    [/autoit][autoit][/autoit][autoit]

    ;Öffnet einen "Datei öffnen Dialog" und lässt als Datei nur CSV-Dateien zu.
    $file = FileOpenDialog("Datei öffnen", @ScriptDir , "CSV Dateien (*.csv)", 1 )

    [/autoit][autoit][/autoit][autoit]

    ;Umwandeln der Datei in ein Array
    Dim $array
    _FileReadToArray($file, $array)

    [/autoit][autoit][/autoit][autoit]

    ;Abarbeiten des Arrays
    For $zeile = 1 To $array[0]

    [/autoit][autoit][/autoit][autoit]

    ;Splitten der Werte anhand des Semikolons (";")
    $wert = StringSplit($array[$zeile], ";")

    [/autoit][autoit][/autoit][autoit]

    ;Test-Ausgabe der einzelnen Werte
    MsgBox(0,"Hinweis", "Wir befinden uns in Zeile: " & $zeile & @CRLF & "Der Wert in Spalte 1 ist: " & $wert[1])
    MsgBox(0,"Hinweis", "Wir befinden uns in Zeile: " & $zeile & @CRLF & "Der Wert in Spalte 2 ist: " & $wert[2])
    MsgBox(0,"Hinweis", "Wir befinden uns in Zeile: " & $zeile & @CRLF & "Der Wert in Spalte 3 ist: " & $wert[3])
    MsgBox(0,"Hinweis", "Wir befinden uns in Zeile: " & $zeile & @CRLF & "Der Wert in Spalte 4 ist: " & $wert[4])
    MsgBox(0,"Hinweis", "Wir befinden uns in Zeile: " & $zeile & @CRLF & "Der Wert in Spalte 5 ist: " & $wert[5])
    Next

    [/autoit][autoit][/autoit][autoit]

    ;Ende des Scripts
    Exit

    [/autoit]

    Anbei noch die Datei zum autoit.de/wcf/attachment/13724/

  • Okey gefällt mir eigendlich muss man schon sagen :D.

    vlt was du noch machen kann mal so aus lernzwecken, wie wärs den das alles in ein 2D array zu packen was meinste?
    Also den inhalt der CSV.

    MFG Matthias

  • Ich hab auch einen CSV Splitter, der jedoch "automatisch" die richtige Spaltenanzahl (= vom ersten Element ausgehend)
    übernimmt.
    Leider gibt es einen Fehler den ich nicht ganz verstehe:

    Spoiler anzeigen
    [autoit]

    #include <array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Func ReadCSVtoArray($sFilePath, $cDelimiter=";")
    Local $maxColumns = 0
    $hFile = FileOpen($sFilePath,0)
    If @error Then Return SetError(1)
    $sContent = FileRead($hFile)
    FileClose($hFile)
    $aRows = StringSplit(StringStripCR($sContent), @LF)
    If IsArray($aRows) = False Then Return SetError(2)
    $aItem = StringSplit($aRows[1], $cDelimiter)
    If IsArray($aItem) = False Then Return SetError(3)
    $maxColumns = $aItem[0]
    Dim $aOut[$aRows[0]][$maxColumns]
    For $r = 1 To $aRows[0]
    $aItem = StringSplit($aRows[$r], $cDelimiter)
    If IsArray($aItem) = False Then Return SetError(3)
    If (Number($aItem[0]) > Number($maxColumns)) Then ; Zeile 18
    Return SetError(4)
    MsgBox(0,"Error?",$aItem[0] > $maxColumns) ; zeigt true an, sollte aber bei true nicht sichtbar sein!
    endif

    [/autoit] [autoit][/autoit] [autoit]

    For $c = 1 To $aItem[0]
    $aOut[$r - 1][$c - 1] = $aItem[$c]
    Next
    Next
    Return $aOut
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    $a = ReadCSVtoArray(@ScriptDir&"\content.txt") ;Inhalt ist der aus Post1, wobei in Zeile 4 ein weiteres Item hinzugefügt wurde
    $e = @error
    If $e Then
    MsgBox(0,"Error: ",$e)
    Else
    _ArrayDisplay($a)
    EndIf

    [/autoit]

    Zeile 19 wird mit True ausgegeben und danach sagt mir die Console:
    "Array variable has incorrect number of subscripts or subscript dimension range exceeded"
    aber genau das sollte ja durch Zeile 18 (wenns wahr wird) verhindert werden.
    Habe ich einen Denkfehler?
    Eigentlich sollte er via Seterror die Funktion direkt terminieren! :S

    EDIT: Ich hab das Return vor Seterror unterschlagen :pinch:

    Wer immer nur das tut, was er bereits kann - wird auch immer nur das bleiben, was er bereits ist!

    Einmal editiert, zuletzt von XovoxKingdom (12. Juli 2011 um 19:47)

  • Hallo!

    @Xovox:
    Ab Zeile 18 folgendes ändern:

    [autoit]


    If (Number($aItem[0]) > Number($maxColumns)) Then ; Zeile 18
    SetError(4)
    MsgBox(0,"Error?",$aItem[0] > $maxColumns) ; zeigt true an, sollte aber bei true nicht sichtbar sein!
    endif

    [/autoit]

    Sollte dann Funzen!
    Grüsse!

    2 Mal editiert, zuletzt von Techmix (12. Juli 2011 um 19:09)

  • Hallo Techmix,
    leider wird mit deiner leichten Variaten die Msgbox angezeigt (d.h. es existiert ein Fehler),
    aber SetError(4) wird nicht wie erwartet ausgeführt (-> Funktion wird nicht beendet).
    Abhilfe (mit der ich mich nicht zufrieden gebe) wäre statt Seterror ein Return, aber das kann
    ja nicht gewollt sein!

    PS: Hier nochmal der Inhalt der Testdatei:

    Code
    Zeile1Wert1;Zeile1Wert2;Zeile1Wert3;Zeile1Wert4;Zeile1Wert5 
    Zeile2Wert1;Zeile2Wert2;Zeile2Wert3;Zeile2Wert4;Zeile2Wert5 
    Zeile2Wert1;Zeile2Wert2;Zeile2Wert3;Zeile2Wert4;Zeile2Wert5
    Zeile3Wert1;Zeile3Wert2;Zeile3Wert3;Zeile3Wert4;Zeile3Wert5;Zeile3Wert6

    EDIT: Man muss Return SetError(..) schreiben :whistling:
    Geheiligt sei die magische Hilfedatei und die Fähigkeit in ihr zu Lesen!

    Wer immer nur das tut, was er bereits kann - wird auch immer nur das bleiben, was er bereits ist!