csv Datei Import ClassHelper für TClientDataSet
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
oft kommt es vor, das man eine csv Datei ("comma seperated value" - Datei) laden möchte um die Daten zu verarbeiten. Eine Beispiel csv Datei könnte so aussehen:
Code:
Das würde folgenden Feldern entsprechen:
Test;"Test Test";"Test "" Test";"Test ; Test";"Test "";"" Test"
Code:
Im Netz habe ich nur relativ komplizierte "Lösungen" gefunden, die das mit den Delimiter und QuoteChar richtig machen.
Spalte 1: Test
Spalte 2: Test Test Spalte 3: Test " Test Spalte 4: Test ; Test Spalte 5: Test ";" Test Aus diesem Grund habe ich mir einen kleinen ClassHelper für das TClientDataSet geschrieben. In meiner "einfachen" Lösung mache ich mir den Umstand zunutze, das die csv Implementierung eigentlich schon im TStrings Objekt vorhanden ist. Deshalb muss ich nicht mir Pos(';', ... arbeiten. Ich habe das TClientDataSet verwendet, da es ein vollwertiges TDataSet ist und so alle Möglichkeiten der Bearbeitung und Anzeige zu Verfügung stehen. Folgendes kleines Beispiel soll die Benutzung demonstrieren:
Diese Lösung ist so felxibel, dass auch andere Delimiter und QuoteChar verwendet werden können. Eine evtl vorhandene Titelzeile mit Feldnamen kann auch berücksichtigt werden. Es gibt natürlich noch viel Raum für Verbesserungen. Aber es soll ja nur ein kleines Beispiel sein.
Ich hoffe das es einige nützlich finden Euer MaBuSE Das ist der komplette Quelltext:
Delphi-Quellcode:
////////////////////////////////////////////////////////////////////////////////
// ClientDatasetCsvClassHelper // // 2 einfache Methoden um csv Dateien (comma seperated value Dateien) in ein // TClientDataSet zu laden bzw. zu speichern. // // Der ClassHelper wurde Quick and Dirty geschrieben, und ist nicht als // Lehrbuchbeispiel der Programmierung geeignet. Trotzdem hoffe ich, das es // für den ein oder anderen lehrreich ist. // // Benutzung: // // - diese Unit in der uses Anweisung aufnehmen // - ClientDataSet hat nun die 2 Methoden zur Verfügung // // unit TestIt; // interface // uses // ... // Dialogs, StdCtrls, Grids, DBGrids, DB, DBClient, ComCtrls, // ClientDatasetCsvClassHelper; // type // TForm1 = class(TForm) // Button1: TButton; // DataSource1: TDataSource; // DBGrid1: TDBGrid; // ClientDataSet1: TClientDataSet; // procedure Button1Click(Sender: TObject); // end; // ... // implementation // ... // procedure TForm1.Button1Click(Sender: TObject); // ClientDataSet1.LoadFromFile('C:\temp\Test.txt', 15); // end; // ... // // Download des neusten Quelltextes auf www.delphipraxis.net // URL: http://www.delphipraxis.net/1132710-post1.html (url bitte anpassen) // // verwendete 3rd party Komponenten: // - keine // // sonstige verwendete Dateien, die nicht Bestandteil von Delphi sind: // - keine // //////////////////////////////////////////////////////////////////////////////// // Der Classhelper ist Freeware und darf beliebig benutzt und erweitert werden. // Es wäre nett, wenn dann auch der geänderte Quelltext in obiges URL-Adresse // gesendet wird. Dann haben alle was davon. // Es wäre auch nett wenn mein (unser) Name in den Dateien enthalten bleibt. // Der ClassHelper wird von Ihnen auf eigenes Risiko eingesetzt. Ich übernehme // keine Haftung für Schäden die durch den Classhelper oder die Benutzung des // Classhelper entstanden sind bzw. entstehen. //////////////////////////////////////////////////////////////////////////////// // (C) 2011, MaBuSE, member of DelphiPraxis.net //////////////////////////////////////////////////////////////////////////////// // ReleaseNotes: // v1.0 - 26.10.2011 - MaBuSE: Erste Version mit Kommentaren versehen //////////////////////////////////////////////////////////////////////////////// unit ClientDatasetCsvClassHelper; interface uses SysUtils, Classes, DB, DBClient; type TClientDataSetCsvClassHelper = class helper for TClientDataSet procedure LoadFromFile(Filename: string; const StringLength: Integer = 100; const FirstLineTitle: Boolean = False; const Delimiter: Char = ';'; const QuoteChar: Char = '"'); procedure SaveToFile(Filename: string; const FirstLineTitle: Boolean = False; const Delimiter: Char = ';'; const QuoteChar: Char = '"'); end; implementation { TClientDataSetCsvClassHelper } // LoadFromFile importiert eine csv Datei in ein TClientDataSet. // Dabei wird die Tabellenstruktur entsprechend der csv Datei neu erzeugt // // Parameter: // Filename: string Dateiname der csv Datei // const StringLength: Integer = 100 Länge der Felder (alle Felder sind gleich lang) // const FirstLineTitle: Boolean = False In 1. Zeile stehen Spaltennamen // const Delimiter: Char = ';' Delimiter trennt die einzelnen Felder // const QuoteChar: Char = '"' QuoteChar schließt Strings ein // procedure TClientDataSetCsvClassHelper.LoadFromFile; var slFile: TStringList; slRow: TStringList; i: Integer; j: Integer; begin slFile := TStringList.Create; slRow := TStringList.Create; try slRow.Delimiter := Delimiter; slRow.QuoteChar := QuoteChar; slRow.StrictDelimiter := True; slFile.LoadFromFile(Filename); // ClientDataset Initialisieren if slFile.Count > 0 then begin Active := False; slRow.DelimitedText := slFile[0]; FieldDefs.Clear; for i := 0 to slRow.Count - 1 do begin if FirstLineTitle then begin FieldDefs.Add(slRow[i], ftString, StringLength); end else begin FieldDefs.Add(Format('Field%d',[i]), ftString, StringLength); end; end; CreateDataSet; Active := True; end; // TClientDataset füllen DisableControls; for i := 0 to slFile.Count - 1 do begin slRow.DelimitedText := slFile[i]; Append; for j := 0 to slRow.Count - 1 do begin Fields[j].AsString := slRow[j]; end; Post; end; EnableControls; finally slFile.Free; slRow.Free; end; end; // SaveToFile exportiert ein TClientDataSet in eine csv Datei. // // Parameter: // Filename: string Dateiname der csv Datei // const FirstLineTitle: Boolean = False In 1. Zeile stehen Spaltennamen // const Delimiter: Char = ';' Delimiter trennt die einzelnen Felder // const QuoteChar: Char = '"' QuoteChar schließt Strings ein // procedure TClientDataSetCsvClassHelper.SaveToFile(Filename: string; const FirstLineTitle: Boolean; const Delimiter, QuoteChar: Char); var slFile: TStringList; slRow: TStringList; i: Integer; c: Integer; begin slFile := TStringList.Create; slRow := TStringList.Create; try slRow.Delimiter := Delimiter; slRow.QuoteChar := QuoteChar; slRow.StrictDelimiter := True; DisableControls; c := FieldDefs.Count; if FirstLineTitle then begin for i := 0 to c - 1 do begin slRow.Add(FieldDefs[i].Name); end; slFile.Add(slRow.DelimitedText); end; First; while not Eof do begin slRow.Clear; for i := 0 to c - 1 do begin slRow.Add(Fields[i].AsString); end; slFile.Add(slRow.DelimitedText); Next; end; slFile.SaveToFile(Filename); EnableControls; finally slFile.Free; slRow.Free; end; end; end. |
AW: csv Datei Import ClassHelper für TClientDataSet
Geht das auch mit einer CSV-Datei der Form
Code:
Daraus muss ein Record mit drei Feldern werden.
Test;"Zeile 1 von Test
Zeile 2 von Test";Test |
AW: csv Datei Import ClassHelper für TClientDataSet
Zitat:
Aber was heißt schon korrekt. Ein verbindliches Format für CSV gibt es nicht (nur RFC 4180) und ich habe selbst schon mehrfach eigene Implementierungen schreiben müssen, weil die Kollegen, die die erzeugenden Programme geschrieben haben, einfach ihre Hausaufgaben nicht gemacht hatten. |
AW: csv Datei Import ClassHelper für TClientDataSet
Zitat:
In csv Dateien bedeutet das Zeilenende in der Regel dass ein neuer Datensatz beginnt. Sprich: Es sind keine Zeilenunbrüche in Feldern erlaubt. In meiner Implementierung kopiere ich jede einzelne Zeile in ein TStrings und hole dann die einzelnen Felder aus diesem heraus. Mit meiner Methode geht das also auf keinen Fall. Ich habe mir das ursprünglich geschrieben um bestimmte Log-Dateien auszuwerten. Für die CodeLib habe ich dann noch SaveToFile ergänzt. Meine Intention, das in die CodeLib zu stellen, war zu zeigen, dass es einen relativ einfachen Weg gibt csv Dateien zu importieren. Letztendlich reicht schon folgender Quellcode aus um eine csv-Datei zu lesen und auf alle einzelnen Felder zuzugreifen:
Delphi-Quellcode:
Das ist ein gutes Beispiel für KISS (keep it stupid simple).
procedure TForm1.Button1Click(Sender: TObject);
var slFile, slRow: TStringList; i, j: Integer; begin slFile := TStringList.Create; slRow := TStringList.Create; slRow.Delimiter := ';'; slRow.QuoteChar := '"'; try slFile.LoadFromFile('dateiname.csv'); for i := 0 to slFile.Count - 1 do begin slRow.DelimitedText := slFile[i]; // wandelt eine csv-Zeile um -> jedes Feld bekommt eine eigene Zeile in slRow for j := 0 to slRow.Count - 1 do begin Memo1.Lines.Add(Format('Row:%3d Col:%2d: Value:%s', [i, j, slRow[j]])); end; end; finally slFile.Free; slRow.Free; end; end; Ich hoffe diese Info hilft Dir. |
AW: csv Datei Import ClassHelper für TClientDataSet
Auf der Basis des Beispiels in dem vorherigen Beitrag habe ich noch einen Class Helper geschrieben.
Damit kann man ein TStringGrid mit einer csv Datei befüllen. Beispiel:
Delphi-Quellcode:
Das ist ein einfaches Beispiel für Class Helper und csv Import.
...
uses StringGridCsvClassHelper; ... procedure TForm1.Button1Click(Sender: TObject); begin StringGrid1.LoadFromFile('Dateiname.csv'); end; ... Vieleicht hilft's wem. mfg MaBuSE ps: Hier ist die Unit des ClassHelpers:
Delphi-Quellcode:
unit StringGridCsvClassHelper;
// use at your own risk interface uses SysUtils, Classes, Grids; type TStringGridCsvClassHelper = class helper for TStringGrid procedure LoadFromFile(Filename: string; const Delimiter: Char = ';'; const QuoteChar: Char = '"'); end; implementation { TStringGridCsvClassHelper } procedure TStringGridCsvClassHelper.LoadFromFile(Filename: string; const Delimiter: Char = ';'; const QuoteChar: Char = '"'); var slFile: TStringList; slRow: TStringList; i: Integer; j: Integer; begin slFile := TStringList.Create; slRow := TStringList.Create; slRow.Delimiter := Delimiter; slRow.QuoteChar := QuoteChar; try slFile.LoadFromFile(Filename); // StringGrid Init if slFile.Count > 0 then begin slRow.DelimitedText := slFile[0]; FixedCols := 0; FixedRows := 0; ColCount := slRow.Count; RowCount := slFile.Count; end; // Fill StringGrid for i := 0 to slFile.Count - 1 do begin slRow.DelimitedText := slFile[i]; for j := 0 to slRow.Count - 1 do begin Cells[j,i] := slRow[j]; end; end; finally slFile.Free; slRow.Free; end; end; end. |
AW: csv Datei Import ClassHelper für TClientDataSet
Moin,
sorry wenn ich hier so was altes raussuche aber das hilft mir gerade sehr weiter. Allerdings ... 1) ich müsste den Trenner von Semikolon auf TAB ändern .. das wäre dann imho hier die "#9" statt "';'"
Delphi-Quellcode:
2) Was mache ich wenn ich nicht auf QuoteChars reagieren möchte ? Die Datei die ich habe hat keinen Texttrenner, dafür aber mitten im Text Anführungsstriche.
type
TClientDataSetCsvClassHelper = class helper for TClientDataSet procedure LoadFromFile(Filename: string; const StringLength: Integer = 100; const FirstLineTitle: Boolean = False; const Delimiter: Char = #9; const QuoteChar: Char = '"'); procedure SaveToFile(Filename: string; const FirstLineTitle: Boolean = False; const Delimiter: Char = #9; const QuoteChar: Char = '"'); end; Hans |
AW: csv Datei Import ClassHelper für TClientDataSet
Statt dem " ein Zeichen nehmen, das nicht vorkommt?
z. B. #7 |
AW: csv Datei Import ClassHelper für TClientDataSet
Oder alles mit QuoteChar zu tun hat aus dem Classhelper entfernen?
Probele können aber glaub ich auftreten, wenn du Leerzeichen in deinen Daten hast. |
AW: csv Datei Import ClassHelper für TClientDataSet
Den QuoteChar kannst Du ja selbst definieren, meist schließen sich ja ' und " gegenseitig aus.
Bei den SteuerZeichen STX,ETX,EOT...(x00..x1F) hab ich mich schon des Öfteren verhaspelt. U.U wäre xFF eine gute Wahl. Gruß K-H P.S. Zitat:
|
AW: csv Datei Import ClassHelper für TClientDataSet
Nicht ganz sauber - aber ich ersetzte jetzt das " durch ein ' :-)
Hans |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:28 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz