- 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
;-- 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.
; ==================================================================================================
#include-once
#include "AutoitObject.au3"
#include <Array.au3>
#include <File.au3>
Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
OnAutoItExitRegister ("_OnExit")
_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
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)
Return $self
EndFunc ;==>_CSVObject
;===================================================================================================
; 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
;===================================================================================================
; 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
;===================================================================================================
; 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
;===================================================================================================
; 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
;===================================================================================================
; 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
;===================================================================================================
; 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
;===================================================================================================
; 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
;===================================================================================================
; 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
;===================================================================================================
; 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
;===================================================================================================
; 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
;===================================================================================================
; 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
#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
Func __LineToArray($self, $Line)
Return StringSplit($Line, $self.Separator)
EndFunc ;==>__LineToArray
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
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
Func _OnExit()
_AutoItObject_Shutdown()
EndFunc ;==>_OnExit
Func _ErrFunc()
ConsoleWrite("! COM Error ! Number: 0x" & Hex($oError.number, & " ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
Return
EndFunc ;==>_ErrFunc
#endregion
[/autoit]Bsp.
;-- 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)
Global $aAll, $a1D, $a2D
[/autoit] [autoit][/autoit] [autoit]; alle Daten anzeigen
$aAll = $oCSV.ArrayLines
_ArrayDisplay($aAll, 'Show All')
; Iteration
Do
$a2D = $oCSV.GetDS(1)
_ArrayDisplay($a2D, 'Next - Index #' & $oCSV.CurrentIndex)
Until $oCSV.Next = -1
$oCSV.Previous
$a1D = $oCSV.GetDS
_ArrayDisplay($a1D, 'Previous - Index #' & $oCSV.CurrentIndex)
$oCSV.First
$a1D = $oCSV.GetDS
_ArrayDisplay($a1D, 'First - Index #' & $oCSV.CurrentIndex)
$oCSV.Last
$a1D = $oCSV.GetDS
_ArrayDisplay($a1D, 'Last - Index #' & $oCSV.CurrentIndex)
; Ausgabe Feldnamen
ConsoleWrite($oCSV.FieldList(0) & @CRLF)
; Ä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')
; Ändern aller Werte im ersten DS
$oCSV.First
$oCSV.SetDS('A;B;C;D;E;F;G')
; Änderungen ansehen
$aAll = $oCSV.ArrayLines
_ArrayDisplay($aAll, 'Änderungen')
; Feldnamen ändern
$oCSV.FieldNamesSet('Juliette;Kilo;Lima;Mike;November;Oscar;Papa')
; Änderungen ansehen
$aAll = $oCSV.ArrayLines
_ArrayDisplay($aAll, 'neue Feldnamen')
; geänderte Datei speichern
$oCSV.WriteToFile