_CSV2Array (CSV-Dateien in Array einlesen)

  • Eine Funktion die ich schon ewig herumliegen habe ... kann sicher mal jemand brauchen.

    - Liest CSV-Dateien ein und liefert diese in einem 2-dim Array zurück
    - Trennzeichen wird automatisch ermittelt bzw. kann angegeben werden
    - variables Handling bei verschiedenen Spaltenzahlen pro Zeile - $iColumnMode:
    0: Fehler bei unterschiedlicher Spaltenzahl und Abbruch. @error: 2, @extended: CSV-Zeile in der der Fehler auftrat
    1: Alle Spalten werden genommen
    2: Alle Spalten die über die der ersten Zeile hinausgehen werden abgeschnitten
    - String-Kennzeichnung kann gefiltert werden (Hochkommata und Anführungszeichnen)

    Beispiel und Funktion:

    Spoiler anzeigen
    [autoit]

    #include <array.au3>
    Main()

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

    Func Main()
    Local $sAdr = "C:\\test.csv"
    Local $h = FileOpen($sAdr, 0)

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

    Local $aRet = _CSV2Array($h, Default, True, 1)

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

    FileClose($h)
    _ArrayDisplay($aRet)

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

    EndFunc ;==>Main

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

    ; #FUNCTION# ===================================================================
    ; Name ..........: _CSV2Array
    ; Description ...:
    ; AutoIt Version : V3.3.0.0
    ; Syntax ........: _CSV2Array($hFile[, $cSeperator = "auto"[, $bFilterString = True[, $iColumnMode = 0]]])
    ; Parameter(s): .: $hFile - Handle for the CSV file to Read
    ; $cSeperator - Optional: (Default = "auto") : Tries to find the separator char ;) or , or TAB or | or space)
    ; | Data-seperator-char
    ; | Empty-string = Opt("GUIDataSeparatorChar")
    ; $bFilterString - Optional: (Default = True) : Removes leading and trailing " or '
    ; $iColumnMode - Optional: (Default = 0) :
    ; | 0: Sets error if lines have different columns and @extended to the csv-line number
    ; | 1: returns lines with different columns numbers comparing to the first line, too
    ; | 2: removing all columns > column numbers in the first line
    ; Return Value ..: Success - 2-dim Array
    ; Failure - 0
    ; @ERROR - 1: error file read
    ; @ERROR - 2: different number of columns / @EXTENDED = CSV-line
    ; - 3: parameter error
    ; Author(s) .....: Thorsten Willert
    ; Date ..........: Mon Dec 07 18:54:35 CET 2009
    ; ==============================================================================
    Func _CSV2Array($hFile, $cSeperator = "auto", $bFilterString = True, $iColumnMode = 0)
    Local $s = FileRead($hFile)
    If @error Then Return SetError(1)

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

    If $cSeperator = Default Then $cSeperator = "auto"
    If Not $cSeperator Then $cSeperator = Opt("GUIDataSeparatorChar")

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

    ; searching the line-seperator and splitting the lines into an array
    Local $aLines
    If StringInStr($s, @CRLF) Then
    $aLines = StringSplit($s, @CRLF, 1)
    ElseIf StringInStr($s, @CR) Then
    $aLines = StringSplit($s, @CR)
    Else
    $aLines = StringSplit($s, @LF)
    EndIf

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

    ; searching the delimiter in the first line
    Local $aTMP
    If $cSeperator = "auto" Then
    Local $iMax = 0
    Local $iC[5] = [0, 0, 0, 0, 0]
    Local $sC[5] = [";", ",", @TAB, "|", " "]

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

    $aTMP = StringRegExp($aLines[1], ";", 3)
    If Not @error Then $iC[0] = UBound($aTMP)
    $aTMP = StringRegExp($aLines[1], ",", 3)
    If Not @error Then $iC[1] = UBound($aTMP)
    $aTMP = StringRegExp($aLines[1], "\t", 3)
    If Not @error Then $iC[2] = UBound($aTMP)
    $aTMP = StringRegExp($aLines[1], "\|", 3)
    If Not @error Then $iC[3] = UBound($aTMP)
    $aTMP = StringRegExp($aLines[1], "[ ]", 3)
    If Not @error Then $iC[4] = UBound($aTMP)

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

    For $i = 0 To UBound($sC) - 1
    If $iC[$i] > $iMax Then
    $iMax = $iC[$i]
    $cSeperator = $sC[$i]
    EndIf
    Next
    EndIf

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

    ; creating 2-dim array based on the number of data in the first line
    $aTMP = StringSplit($aLines[1], $cSeperator)
    Local $iCol = $aTMP[0]
    Local $aRet[$aLines[0]][$iCol]

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

    ; splitting and filling the lines
    For $i = 1 To $aLines[0]
    $aTMP = StringSplit($aLines[$i], $cSeperator)
    If @error Then ContinueLoop
    If $aTMP[0] > $iCol Then
    Switch $iColumnMode
    Case 0
    Return SetError(2, $i)
    Case 1
    ReDim $aRet[$aLines[0] - 1][$aTMP[0]]
    Case 2
    $aTMP[0] = $iCol
    Case Else
    Return SetError(3)
    EndSwitch
    EndIf
    For $j = 1 To $aTMP[0]
    $aTMP[$j] = StringStripWS($aTMP[$j], 3)
    If $bFilterString Then ; removing leading and trailing " or '
    $aTMP[$j] = StringRegExpReplace($aTMP[$j], '^("|'')(.*?)\1$', '$2')
    EndIf
    $aRet[$i - 1][$j - 1] = $aTMP[$j]
    Next ; /cols
    Next ; /lines

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

    Return $aRet
    EndFunc ;==>_CSV2Array

    [/autoit]

    test.csv:

    Spoiler anzeigen
    Code
    1; test1.1; test1.2
    2;test2.1;"test2.2";test2.3;test2.4
    3;test3.1;	test3.2
    4;test4.1;		test4.2
  • Die Schleife läuft nur bis zur vorletzten Zeile. Das ist egal solange die letzte Zeile leer ist, aber wenn Daten drin stehen, fehlen diese.

    [autoit]

    For $i = 1 To $aLines[0] - 1
    ; =========================/\

    [/autoit]
  • Hallo Zusammen,

    ich wollte die Funktion "_CSV2Array" nutzen um eine CSV Datei einzulesen.
    Leider arbeitet die Funktion nicht wie gewünscht.

    ---------csv-Datei--------------
    FILE, "C:\PROJEKTE\Daten, 1\XXX2_WZ_2_80%.bin", Heinz


    FILE, "C:\PROJEKTE\Daten, 1\XXX2_WZ_2_60%.bin", Rolf
    -----------------------------------

    Leider trennt das Script bei jedem Komma (auch bei dem Komma in den Anführungsstrichen).
    Genau das wollte ich aber durch die Anführungszeichen vermeiden.
    Hat jemand eine Idee wie das Problem simpel gelöst werden kann?

    Hinweis: Ich kann an den Verzeichnisstrukturen leider nicht ändern.

  • Schreib dir einen eigenen Parser. Ist ja schnell gemacht oder nimm die UDF und änder sie um.

    Hatte noch Zeit und Laune. Direkt auf dein Vorhaben zugeschnitten.

    Spoiler anzeigen
    [autoit]

    Func _CSV2Array($hFile, $sSeperator)
    Local $s = FileRead($hFile)
    If @error Then Return SetError(1)

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

    ; searching the line-seperator and splitting the lines into an array
    Local $aLines
    If StringInStr($s, @CRLF) Then
    $aLines = StringSplit($s, @CRLF, 1)
    ElseIf StringInStr($s, @CR) Then
    $aLines = StringSplit($s, @CR)
    Else
    $aLines = StringSplit($s, @LF)
    EndIf

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

    Local $aTmp1[1]
    Local $iCount = 0
    For $i = 0 To UBound($aLines) - 1
    $aSB = _StringBetween($aLines[$i], '"', '"')
    For $k = 0 To UBound($aSB) - 1
    $iCount += 1
    $aTmp1[UBound($aTmp1) - 1] = $aSB[$k]
    $aLines[$i] = StringReplace($aLines[$i], $aSB[$k], "sdffbsdkjfbhsdkjbasb" & $iCount)
    ReDim $aTmp1[UBound($aTmp1) + 1]
    Next
    Next

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

    ; creating 2-dim array based on the number of data in the first line
    $aTMP = StringSplit($aLines[1], $sSeperator)
    Local $iCol = $aTMP[0]
    Local $aRet[$aLines[0]][$iCol]

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

    ; splitting and filling the lines
    For $i = 1 To $aLines[0]
    $aTMP = StringSplit($aLines[$i], $sSeperator)
    If @error Then ContinueLoop
    For $j = 1 To $aTMP[0]
    $aTMP[$j] = StringStripWS($aTMP[$j], 3)
    $aRet[$i - 1][$j - 1] = $aTMP[$j]
    Next ; /cols
    Next ; /lines
    $iCount = 0
    For $i = 0 To UBound($aRet) - 1
    For $k = 0 To UBound($aRet, 2) - 1
    If StringInStr($aRet[$i][$k], "sdffbsdkjfbhsdkjbasb") Then
    $iCount += 1
    $aRet[$i][$k] = StringReplace($aRet[$i][$k], "sdffbsdkjfbhsdkjbasb" & $iCount, $aTmp1[$iCount - 1])
    EndIf
    Next
    Next
    Return $aRet
    EndFunc ;==>_CSV2Array

    [/autoit]

    Einmal editiert, zuletzt von m-obi (21. Juni 2012 um 00:45)

  • Verzeihen Sie mir, wenn meine Grammatik schlecht ist. Ich bin mit Google Translate.

    Was wäre der Vorteil der Verwendung dieser gegenüber _ExcelReadSheetToArray (be)

  • Bei _ExcelReadSheetToArray geht es über ein Objekt. Bei _CSV2Array über den Dateinamen.
    Bei _CSV2Array kannst du den Seperator angeben.
    Bei _ExcelReadSheetToArray kannst du die Spalten und Zeilen angeben. Mit sowas hat _CSV2Array nix zutun.

    Also _ExcelReadSheetToArray ist was völlig anderes als _CSV2Array.