• Offizieller Beitrag

    Ich habe mich mal ein wenig mit dem AutoItObject beschäftigt und damit eine objektbasierte CSV-UDF erstellt.
    Aus den Funktionsbeschreibungen und dem Bsp. sind alle Hinweise zur Anwendung ersichtlich.

    CSV_Object.au3
    [autoit]

    ;-- TIME_STAMP 2014-12-29 23:20:03 v 0.1

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

    ; Requires the AutoItObject-UDF: http://www.autoitscript.com/forum/topic/11…df/#entry775262

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

    ; #CURRENT# ========================================================================================
    ; FUNCTION REGISTERED METHODE SHORT DESCRIPTION
    ; _CSVObject Creates an object from an csv file.
    ; _CSVObject_FirstLine .First Points to the first data line.
    ; _CSVObject_NextLine .Next Points to the next data line.
    ; _CSVObject_PrevLine .Previous Points to the previous data line.
    ; _CSVObject_LastLine .Last Points to the last data line.
    ; _CSVObject_SetField .SetField Sets value of one field in current data line.
    ; _CSVObject_GetDS .GetDS Gets all values from the current data line.
    ; _CSVObject_SetDS .SetDS Sets all values in the current data line.
    ; _CSVObject_FieldList .FieldList Returns a list of all field names.
    ; _CSVObject_PropertySet .PropertySet Sets one field in current data line (to use in loops).
    ; _CSVObject_FieldNamesSet .FieldNamesSet Sets new field names.
    ; _CSVObject_WriteToFile .WriteToFile Writes from object back to csv-file.
    ; ==================================================================================================

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

    #include-once
    #include "AutoitObject.au3"
    #include <Array.au3>
    #include <File.au3>

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

    Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
    OnAutoItExitRegister ("_OnExit")

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

    _AutoItObject_StartUp()

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

    ;===================================================================================================
    ; Function Name....: _CSVObject
    ; Description......: Creates an object of a specified csv file.
    ; Parameters ......: $sFile Path to the csv file.
    ; ......optional...: $sFieldLine A string with field names. Default '' = 1st line includes the field names.
    ; .................: With 'num' will enumerated the fields, starting by 1.
    ; ......optional...: $sSeparator The field separator. Default is ';'.
    ; Return Value(s)..: Success The csv file object
    ; .................: Failure @error = 1 $sFile not exists.
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject($sFile, $sFieldLine='', $sSeparator=';')
    If Not FileExists($sFile) Then Return SetError(1,0,0)
    Local $aLines
    _FileReadToArray($sFile, $aLines)
    If $sFieldLine <> '' Then
    _ArrayInsert($aLines, 1, $sFieldLine)
    $aLines[0] += 1
    EndIf
    Local $sSplit = ($sFieldLine = 'num' Or $sFieldLine = '') ? $aLines[1] : $sFieldLine
    Local $aFields = StringSplit($sSplit, $sSeparator)
    Local $aTmp[$aFields[0]+1] = [$aFields[0]] ; Array zum Speichern der Feldnamen
    Local $iMin = ($sFieldLine = 'num') ? 1 : 2

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

    Local $self = _AutoItObject_Create()
    _AutoItObject_AddMethod($self, "First", "_CSVObject_FirstLine") ; gehe zum: ersten DS
    _AutoItObject_AddMethod($self, "Next", "_CSVObject_NextLine") ; gehe zum: nächsten DS
    _AutoItObject_AddMethod($self, "Previous", "_CSVObject_PrevLine") ; gehe zum: vorigen DS
    _AutoItObject_AddMethod($self, "Last", "_CSVObject_LastLine") ; gehe zum: letzten DS
    _AutoItObject_AddMethod($self, "SetField", "_CSVObject_SetField") ; Ändert Wert eines Feldes im aktuellen DS
    _AutoItObject_AddMethod($self, "GetDS", "_CSVObject_GetDS") ; Gibt den aktuellen DS als 1D-WerteArray (Standard) od. 2D-Array ([Feldname,Wert]) zurück
    _AutoItObject_AddMethod($self, "SetDS", "_CSVObject_SetDS") ; setzt den gesamten DS neu, alle Werte werden in einem Separator-getrennten String übergeben
    _AutoItObject_AddMethod($self, "FieldList", "_CSVObject_FieldList") ; Gibt ein Array mit den Feldnamen zurück
    _AutoItObject_AddMethod($self, "PropertySet", "_CSVObject_PropertySet") ; zum dynamischen Neubefüllen der Properties
    _AutoItObject_AddMethod($self, "FieldNamesSet", "_CSVObject_FieldNamesSet") ; Feldnamen ändern oder erstmalig setzen
    _AutoItObject_AddMethod($self, "WriteToFile", "_CSVObject_WriteToFile") ; schreibt den Inhalt des Objektes in eine Datei
    _AutoItObject_AddMethod($self, "ShowDS", "__ShowDS") ; [intern] Aktualisiert Feldinhalte für den aktuellen DS im Objekt
    _AutoItObject_AddMethod($self, "Line2Array", "__LineToArray") ; [intern] Hilfsfunktion
    _AutoItObject_AddMethod($self, "Array2Line", "__ArrayToLine") ; [intern] Hilfsfunktion
    _AutoItObject_AddMethod($self, "FieldIndex", "__FieldIndex") ; [intern] Hilfsfunktion
    _AutoItObject_AddProperty($self, "FilePath", $ELSCOPE_PUBLIC, $sFile) ; Dateipfad von dem eingelesen wurde
    _AutoItObject_AddProperty($self, "ArrayLines", $ELSCOPE_PUBLIC, $aLines) ; Array mit allen Zeilen der Datei
    _AutoItObject_AddProperty($self, "Separator", $ELSCOPE_PUBLIC, $sSeparator) ; der verwendete Separator, Standard ist ';'
    _AutoItObject_AddProperty($self, "CurrentIndex", $ELSCOPE_PUBLIC, $iMin) ; Index des aktuellen DS (an Index '0' steht Anzahl)
    _AutoItObject_AddProperty($self, "MinIndex", $ELSCOPE_PRIVATE, $iMin) ; Index des ersten DS der Datei ('1' wenn kein Feldnamen-DS, sonst '2')
    _AutoItObject_AddProperty($self, "MaxIndex", $ELSCOPE_PRIVATE, $aLines[0]) ; Index des letzten DS der Datei
    _AutoItObject_AddProperty($self, "HasFieldNames", $ELSCOPE_PRIVATE, $iMin-1) ; '0' wenn keine Feldnamen vorhanden, sonst '1'
    ; Array der verwendeten Feldnamen als Property erstellen
    Local $aFirstDataLine = StringSplit($aLines[$iMin], $sSeparator)
    For $i = 1 To $aFields[0]
    If $sFieldLine = 'num' Then
    _AutoItObject_AddProperty($self, String($i), $ELSCOPE_PUBLIC, $aFirstDataLine[$i])
    $aTmp[$i] = String($i) ; Feldnummer als Feldname eintragen
    Else
    _AutoItObject_AddProperty($self, $aFields[$i], $ELSCOPE_PUBLIC, $aFirstDataLine[$i])
    $aTmp[$i] = $aFields[$i]
    EndIf
    Next
    _AutoItObject_AddProperty($self, "ArrayFields", $ELSCOPE_PRIVATE, $aTmp)

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

    Return $self
    EndFunc ;==>_CSVObject

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_FirstLine
    ; Description......: Sets pointer to first data line. Sets current values to all fields.
    ; Parameter(s).....: $self The csv object.
    ; Return Value(s)..: -1 If current line is already the first, otherwise the current index.
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_FirstLine($self)
    With $self
    Local $iCurrent = .CurrentIndex
    Local $iFirst = .MinIndex
    If $iFirst = $iCurrent Then Return -1
    .CurrentIndex = $iFirst
    EndWith
    $self.ShowDS($self.ArrayLines[$self.CurrentIndex])
    Return $self.CurrentIndex
    EndFunc ;==>_CSVObject_FirstLine

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_NextLine
    ; Description......: Sets pointer to next data line. Sets current values to all fields.
    ; Parameter(s).....: $self The csv object.
    ; Return Value(s)..: -1 If current line is already the last, otherwise the current index.
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_NextLine($self)
    With $self
    Local $iCurrent = .CurrentIndex
    Local $iLast = .MaxIndex
    If $iLast = $iCurrent Then Return -1
    .CurrentIndex = $iCurrent +1
    EndWith
    $self.ShowDS($self.ArrayLines[$self.CurrentIndex])
    Return $self.CurrentIndex
    EndFunc ;==>_CSVObject_NextLine

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_PrevLine
    ; Description......: Sets pointer to previous data line. Sets current values to all fields.
    ; Parameter(s).....: $self The csv object.
    ; Return Value(s)..: -1 If current line is already the first, otherwise the current index.
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_PrevLine($self)
    With $self
    Local $iCurrent = .CurrentIndex
    Local $iFirst = .MinIndex
    If $iFirst = $iCurrent Then Return -1
    .CurrentIndex = $iCurrent -1
    EndWith
    $self.ShowDS($self.ArrayLines[$self.CurrentIndex])
    Return $self.CurrentIndex
    EndFunc ;==>_CSVObject_PrevLine

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_LastLine
    ; Description......: Sets pointer to last data line. Sets current values to all fields.
    ; Parameter(s).....: $self The csv object.
    ; Return Value(s)..: -1 If current line is already the last, otherwise the current index.
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_LastLine($self)
    With $self
    Local $iCurrent = .CurrentIndex
    Local $iLast = .MaxIndex
    If $iLast = $iCurrent Then Return -1
    .CurrentIndex = $iLast
    EndWith
    $self.ShowDS($self.ArrayLines[$self.CurrentIndex])
    Return $self.CurrentIndex
    EndFunc ;==>_CSVObject_LastLine

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_SetField
    ; Description......: Sets the value of one field in the current data set.
    ; Parameter(s).....: $self The csv object.
    ; .................: $sField The field name.
    ; .................: $value The new value.
    ; Return Value(s)..: Success 1
    ; .................: Failure @error - $sField not exists
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_SetField($self, $sField, $value)
    Local $aLines = $self.ArrayLines
    Local $aLine = $self.Line2Array($aLines[$self.CurrentIndex])
    Local $index = $self.FieldIndex($sField)
    If @error Then Return SetError(@error,0,0)
    $aLine[$index] = $value
    $aLines[$self.CurrentIndex] = $self.Array2Line($aLine)
    $self.ArrayLines = $aLines
    Return 1
    EndFunc ;==>_CSVObject_SetField

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_GetDS
    ; Description......: Returns the current data set as 1D array of values or 2D array with [field name, value].
    ; Parameter(s).....: $self The csv object.
    ; .................: $ret2D Default '0' - Array of values, '1' - [field name, value]
    ; Return Value(s)..: Array with data
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_GetDS($self, $ret2D=0)
    Local $aLines = $self.ArrayLines
    Local $aLine = StringSplit($aLines[$self.CurrentIndex], $self.Separator)
    Local $aFields = $self.ArrayFields
    Local $aOut[$aFields[0]+1] = [$aFields[0]]
    If $ret2D = 1 Then
    ReDim $aOut[$aFields[0]+1][2]
    $aOut[0][0] = $aFields[0]
    EndIf
    For $i = 1 To $aFields[0]
    If $ret2D = 1 Then
    $aOut[$i][0] = $aFields[$i]
    $aOut[$i][1] = $aLine[$i]
    Else
    $aOut[$i] = $aLine[$i]
    EndIf
    Next
    Return $aOut
    EndFunc ;==>_CSVObject_GetDS

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_SetDS
    ; Description......: Sets new values to the current data set.
    ; Parameter(s).....: $self The csv object.
    ; .................: $valString Separator delimited string with one value for each field.
    ; Return Value(s)..: 1
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_SetDS($self, $valString)
    Local $aLines = $self.ArrayLines
    Local $aFields = $self.ArrayFields
    Local $aLine[$aFields[0]+1] = [$aFields[0]]
    Local $aSet = StringSplit($valString, $self.Separator)
    For $i = 1 To $aFields[0]
    $aLine[$i] = $aSet[$i]
    Next
    $aLines[$self.CurrentIndex] = $self.Array2Line($aLine)
    $self.ArrayLines = $aLines
    Return 1
    EndFunc ;==>_CSVObject_SetDS

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_FieldList
    ; Description......: Returns the current field list as array or string.
    ; Parameter(s).....: $self The csv object.
    ; .................: $retArr Default '1' - returns array with field names, '0' returns an separator delimited string.
    ; Return Value(s)..: The array or string with field names.
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_FieldList($self, $retArr=1)
    If $retArr = 1 Then Return $self.ArrayFields
    Local $sFields = ''
    For $i = 1 To $self.ArrayFields[0]
    $sFields &= $self.ArrayFields[$i] & $self.Separator
    Next
    Return StringTrimRight($sFields, 1)
    EndFunc ;==>_CSVObject_FieldList

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_PropertySet
    ; Description......: Sets a new value to a property. To use i.e. in loops.
    ; Parameter(s).....: $self The csv object.
    ; .................: $Property The property to set.
    ; .................: $newVal The new value.
    ; Return Value(s)..: 1
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_PropertySet($self, $Property, $newVal)
    _AutoItObject_RemoveMember($self, $Property)
    _AutoItObject_AddProperty($self, $Property, $ELSCOPE_PUBLIC, $newVal)
    Return 1
    EndFunc ;==>_CSVObject_PropertySet

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_FieldNamesSet
    ; Description......: Sets new field names.
    ; Parameter(s).....: $self The csv object.
    ; .................: $sFieldNames Separator delimited string with new field names.
    ; Return Value(s)..: 1
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_FieldNamesSet($self, $sFieldnames)
    Local $aTmpFields = StringSplit($sFieldnames, $self.Separator)
    Local $aCurrent = $self.GetDS(1)
    For $i = 1 To $aCurrent[0][0]
    _AutoItObject_AddProperty($self, $aTmpFields[$i], $ELSCOPE_PUBLIC, $aCurrent[$i][1])
    _AutoItObject_RemoveMember($self, $aCurrent[$i][0])
    Next
    Local $aLines = $self.ArrayLines
    If $self.HasFieldNames = 0 Then
    $aLines[0] += 1
    $self.HasFieldNames = 1
    $self.ArrayLines = $aLines
    $self.MinIndex = 2
    $self.MaxIndex += 1
    $self.CurrentIndex += 1
    _ArrayInsert($aLines, 1, $sFieldnames)
    Else
    $aLines[1] = $sFieldnames
    EndIf
    $self.ArrayLines = $aLines
    $self.ArrayFields = $aTmpFields
    Return 1
    EndFunc ;==>_CSVObject_FieldNamesSet

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

    ;===================================================================================================
    ; Function Name....: _CSVObject_WriteToFile
    ; Description......: Writes the csv object back to an file. If the file was without field names and
    ; .................: the field names was set by object - they will also written to file.
    ; .................: Exceptions are automatically generated field names in the 'num' mode.
    ; Parameter(s).....: $self The csv object.
    ; .................: $sFullPath Default '-1' - uses the path from reading, overwrites the old file.
    ; .................: $sLinebreak Default '@CRLF' - the line ending character.
    ; Return Value(s)..: 1
    ; Author...........: BugFix
    ;===================================================================================================
    Func _CSVObject_WriteToFile($self, $sFullPath=-1, $sLinebreak=@CRLF)
    If $sFullPath = -1 Or $sFullPath = Default Then $sFullPath = $self.FilePath
    If FileExists($sFullPath) Then FileDelete($sFullPath)
    Local $sWrite = ''
    For $i = $self.MinIndex-$self.HasFieldNames To $self.MaxIndex
    $sWrite &= $self.ArrayLines[$i] & $sLinebreak
    Next
    Return FileWrite($sFullPath, StringTrimRight($sWrite, StringLen($sLinebreak)))
    EndFunc ;==>_CSVObject_WriteToFile

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

    #region - internal use only

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

    Func __ShowDS($self, $sNewDataLine)
    Local $aLine = StringSplit($sNewDataLine, $self.Separator)
    For $i = 1 To $self.ArrayFields[0]
    $self.PropertySet($self.ArrayFields[$i], $aLine[$i])
    Next
    Return 1
    EndFunc ;==>__ShowDS

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

    Func __LineToArray($self, $Line)
    Return StringSplit($Line, $self.Separator)
    EndFunc ;==>__LineToArray

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

    Func __ArrayToLine($self, $Array)
    Local $line = ''
    For $i = 1 To UBound($Array) -1
    $line &= $Array[$i] & $self.Separator
    Next
    Return StringTrimRight($line, 1)
    EndFunc ;==>__ArrayToLine

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

    Func __FieldIndex($self, $Field)
    Local $index = -1
    For $i = 0 To $self.ArrayFields[0]
    If $self.ArrayFields[$i] = $Field Then
    $index = $i
    ExitLoop
    EndIf
    Next
    If $index < 0 Then Return SetError(1,0,0)
    Return $index
    EndFunc ;==>__FieldIndex

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

    Func _OnExit()
    _AutoItObject_Shutdown()
    EndFunc ;==>_OnExit

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

    Func _ErrFunc()
    ConsoleWrite("! COM Error ! Number: 0x" & Hex($oError.number, 8) & " ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
    Return
    EndFunc ;==>_ErrFunc

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

    #endregion

    [/autoit]
    Bsp.
    [autoit]

    ;-- TIME_STAMP 2014-12-30 00:05:57

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

    #include 'CSV_Object.au3'

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

    Global $file = "test.csv"
    Global $oCSV = _CSVObject($file)

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

    Global $aAll, $a1D, $a2D

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

    ; alle Daten anzeigen
    $aAll = $oCSV.ArrayLines
    _ArrayDisplay($aAll, 'Show All')

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

    ; Iteration
    Do
    $a2D = $oCSV.GetDS(1)
    _ArrayDisplay($a2D, 'Next - Index #' & $oCSV.CurrentIndex)
    Until $oCSV.Next = -1

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

    $oCSV.Previous
    $a1D = $oCSV.GetDS
    _ArrayDisplay($a1D, 'Previous - Index #' & $oCSV.CurrentIndex)

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

    $oCSV.First
    $a1D = $oCSV.GetDS
    _ArrayDisplay($a1D, 'First - Index #' & $oCSV.CurrentIndex)

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

    $oCSV.Last
    $a1D = $oCSV.GetDS
    _ArrayDisplay($a1D, 'Last - Index #' & $oCSV.CurrentIndex)

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

    ; Ausgabe Feldnamen
    ConsoleWrite($oCSV.FieldList(0) & @CRLF)

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

    ; Ändern eines Feldwertes NICHT über direkte Wertzuweisung an die Property, dann werden Daten im csv-Objekt nicht mit geändert!
    ; Ändern einzelner Wert im aktuellen DS (z.Zt. letzter)
    $oCSV.SetField('Charly', 'WERT_NEU')

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

    ; Ändern aller Werte im ersten DS
    $oCSV.First
    $oCSV.SetDS('A;B;C;D;E;F;G')

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

    ; Änderungen ansehen
    $aAll = $oCSV.ArrayLines
    _ArrayDisplay($aAll, 'Änderungen')

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

    ; Feldnamen ändern
    $oCSV.FieldNamesSet('Juliette;Kilo;Lima;Mike;November;Oscar;Papa')

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

    ; Änderungen ansehen
    $aAll = $oCSV.ArrayLines
    _ArrayDisplay($aAll, 'neue Feldnamen')

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

    ; geänderte Datei speichern
    $oCSV.WriteToFile

    [/autoit]
  • Hi,
    sieht gut aus!
    Da ich selbst viel mit CSV arbeite (allerdings nur in VBA), bestünden ggf. weitere Anforderungen :D :
    - String in CSV finden und Zeile/Spalte ausgeben
    - Den n-ten Feldinhalt in einer Zeile zurückgeben
    - Anzahl Felder einer (der aktuellen) Zeile

    Allerdings muss ich zugeben, dass die vorliegende UDF außer als Programmierbeispiel für AutoItObjekt keinerlei Vorteile gegenüber eines simplen 2D-Arrays/Listen hat!
    Mir erscheint das Objektgedöns (in diesem Fall! ) eher kontraproduktiv.

    • Offizieller Beitrag

    Natürlich läßt sich das mit den rein Array bezogenen Varianten genauso bearbeiten.
    Da ich in letzter Zeit mehr mit objektorientierten Sprachen arbeite, war dies eigentlich nur eine Spielerei. Ich persönlich mag Objektorientiertheit.
    Das eigentliche Problem ist, dass AutoIt mal überhaupt nicht für Objekte vorbereitet ist. Wenn man innerhalb von AutoItObject dann zwangsweise doch mit nativem AutoIt arbeiten muss, bleibt von der OOP oft nur Syntaxveränderung übrig. :huh: