[Gelöst] Welche Unit/Komponente für CSV Dateien

Für Fragen von Einsteigern und Programmieranfängern...
BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

[Gelöst] Welche Unit/Komponente für CSV Dateien

Beitrag von BitRausch »

Hallo,

Ich bin neu hier :-)

Meine Object Pascal Programmiererfahrung liegt sehr sehr weit zurück. Die letzte Version mit der ich gearbeitet habe war Delphi 4.
Danach hat es mich beruflich in eine andere Richtung verschlagen und ich bin aus der Programmiererecke komplett raus gekommen...
Vor kurzem habe ich ein kleine Aufgabe übernommen und ich dachte mir ich könnte wieder etwas machen was mir immer Spaß gemacht hat: coden :-)

Also sitze ich wieder hier gehe (wieder) durch eine steile Lernkurve...und es macht echt Spaß :-)

Aber jetzt zu meiner Frage:
Die Aufgabe beinhaltet das einlesen von CSV Dateien (ca 5000-7000 Datensätze, einfache Summenbildung/Validierung über bestimmte Felder und das erstellen von CSV Dateien mit bestimmten Feldformaten.

Bei der Suche nach Lösungen/Beispielen und Doku's bin ich über CSVDocument und csvreadwrite gestolpert.
Leider habe ich jetzt noch nicht verstanden wie diese Komponenten einzuordnen sind und welche für mein Vorhaben am besten/einfachsten einzusetzen sind...
(Mein Plan ist es die Datensätze in ein Stringliste einzulesen (im Speicher halten) und zwecks Verarbeitung auf eine Record Struktur aufzubrechen, zu verarbeiten und anschließend die Sätze wieder in eine Stringliste zu schreiben und von da in eine CSV Datei zu streamen...)

Oder wäre es besser hier ein TStringGrid zu verwenden... (Eine Bearbeitung der Felder per GUI findet nicht statt und ich sehe das Thema Performance auch nicht sehr kritisch)

Sorry wenn die Frage sehr allgemein ist - ich stehe (wieder mal) am Anfang :-)

Über Hinweise auf Doku's/Tipps/Beispiele würde ich mich sehr freuen

Gruß
Zuletzt geändert von BitRausch am Mi 9. Aug 2017, 13:16, insgesamt 1-mal geändert.

wp_xyz
Beiträge: 4885
Registriert: Fr 8. Apr 2011, 09:01

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von wp_xyz »

Wie man mit dem CSV-Parser aus dem CSVdocument umgeht, findest du auf http://wiki.lazarus.freepascal.org/CsvD ... StringGrid (bin nicht 100% sicher, ob der Text aktuell ist, denn CSVdocument wurde vor einiger Zeit in fpc aufgenommen, und die Unit csvreadwrite wurde abgespalten, daher meine ich , dass du jetzt statt csvdocument die Unit csvreadwrite in "uses" aufführen musst).

Wenn dich primär interessiert, die Daten in einem StringGrid anzuzeigen, kannst auch dessen Methode LoadFromCSVFile (oder LoadFromCSVStream) verwenden.

Oder falls du die Zeilen selber zerlegen willst, kannst du alles in eine StringList (L) einlesen, diese String für String durchlaufen, und jeden String L[i] mit L[i].Split(<spaltentrenner>) in ein StringArray zerlegen (wobei der StringHelper .Split erst ab fpc 3.0 verfügbar ist - voher musst du selbst das Spaltentrennzeichen suchen und den String hier aufbrechen).

Und schließlich kannst du auch die Datenbank-Maschinerie anwerfen und die Datei in ein SdfDataset einlesen.

Viele Wege führen zum Ergebnis. Es kommt darauf an, was du genau machen willst.

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von BitRausch »

Vielen Dank für die sehr schnelle Antwort wp_xyz!!

Ich bin bei meiner Suche auch auf Deinen Beitrag vom letztem Jahr gestoßen ( viewtopic.php?f=55&t=10016&mobile=on) und da habe ich auch zum ersten mal gelesen das es überhaupt ein csvreadwrite gibt...Auslöser für diesen Thread ;-)

Dein Beispiel kommt meinem Vorhaben schon sehr nahe auch wenn es hier um die Ausgabe in eine CSV Datei geht...
Was ich nicht verstanden habe bzw. gefunden habe war
a) TCSVBuilder - wo finde ich Infos dazu
b) ob Dein Beispiel auch mit TStringlist geht statt mit TList

Im Bespiel auf der Wiki Seite wird mit TParser der String zerlegt...könnte ich diese Komponente auch nutzen?
Wo finde ich die Info dazu bzw. ist es in CSVDocument oder csvreadwrite?
(Vielleicht auch ein nützliche Info: Die Datensätze die eingelesen werden sollen haben eine Größe von 1200 Byte und bestehen aus 72 Feldern.)

Vielen Dank für Deine Unterstützung!
(Ich Versuche immer noch die vielen Info Schnipsel zusammen zu führen...)

wp_xyz
Beiträge: 4885
Registriert: Fr 8. Apr 2011, 09:01

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von wp_xyz »

BitRausch hat geschrieben:a) TCSVBuilder - wo finde ich Infos dazu

Tut mir leid, aber besser als damals könnte ich das heute auch nicht schreiben. Ansonsten schaue dir den Quellcode von csvreadwrite an - immer noch besser als jede (unvollständige, nicht aktuelle) Dokumentation

BitRausch hat geschrieben:b) ob Dein Beispiel auch mit TStringlist geht statt mit TList

Ich versteh' nicht. Wenn deine Daten schon zu einer StringList zusammengefügt sind, hast du doch schon die CSV-Datei, du musst die Stringlist nur in eine Datei speichern (StringList.SaveToFile). Falls das anders ist, musst du mehr schreiben, was du genau machen willst. Sonst wird das nur Gefasel meinerseits.

Generell: TList hat bis auf das "List" im Namen und einige gleichnamige Methoden nichts mit TStringList gemeinsam. TStringList speichert primär Strings, TList speichert Pointer auf irgendwas, üblicherweise Pointer auf Records oder Objekte.

BitRausch hat geschrieben:Im Bespiel auf der Wiki Seite wird mit TParser der String zerlegt...könnte ich diese Komponente auch nutzen?

TParser? Das ist etwas anderes... In dem Beispiel wird TCSVParser verwendet. Der ist für das Lesen einer CSV-Datei zuständig und zerlegt die Datei (bestehend aus komma- oder anders-separierten Strings) in die einzelnen Bestandteile. Jede Zeile ist ein Datensatz, jeder Datensatz besteht aus Feldern. Das Zeichen, das die Felder trennt, kannst du über CSVParser.Delimiter festlegen. Zum Schreiben, andererseits, verwendest du den TCSVBuilder, der die Datensätze aus den Feldern zusammensetzt. Aber ehrlich gesagt: Eigentlich sind das nichts als einfache String-Operationen...

BitRausch hat geschrieben:Die Datensätze die eingelesen werden sollen haben eine Größe von 1200 Byte und bestehen aus 72 Feldern.

Das ist fürs Prinzip egal. Vielleicht kannst du eine Datei hochladen (zur Not mit Dummy-Daten, falls du die echten Daten nicht zeigen willst/kannst). Die Datei bitte in ein zip packen, sonst wird sie von der Forumssoftware nicht akzeptiert.

Ich würde dir gerne ein konkretes Beispiel geben, aber ich weiß nicht, wie deine Daten im Programm/in der Datei vorliegen.

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von BitRausch »

Sorry - mein Fehler. Habe es etwas ungeschickt formuliert...

Meinte den TCSVParser wie im Beispiel auf der Wiki...
Zum besseren Verständnis.
- Es werden aus Excel CSV Dateien erzeugt.
- Diese will ich mit meinem Program einlesen.
- Es handelt sich um Text, Zahlen- und Datumsfelder mit Semikolon getrennt. Es sind keine Sonderzeichen in den Textfeldern, auch kein CR.
- nach entsprechender Verarbeitung wird eine neue CSV Datei erstellt wobei die Felder mit bestimmten Formaten abgelegt werden. Z.B Text-Felder linksbündig+nur Großbuchstaben. Zahlen-Felder rechtsbündig und mit '0' aufgefüllt. Keine Trennzeichen, d.h die Felder werden hintereinander weggeschrieben und nur CR/LF am Satzende.

Die Verarbeitung besteht aus Validierung (z.B. Pflichtfelder gefüllt?, Abhängigkeiten erfüllt (z.B. Wenn Feld A gesetzt dann muss auch Feld B gesetzt sein)
und Summenbildung von bestimmten Spalten.

Über die GUI werden die Datensätze nicht angezeigt. Der User kann nur die Datei auswählen und den Prozess starten, da das Ausgabeformat sprich Satzaufbau und Feldformate vorgegeben sind.


Womit tue ich mich schwer?
Ich bin etwas verwirrt bei der Auswahl der richtigen Mittel:
- einfaches TStringList oder CSVDocument oder csvreadwrite beim einlesen?
- Ausgabe in Datei wie in Deinem Beispiel?
(Ich denke eine Datenbank-Komponente wäre hier nicht notwendig.)

Wenn ich Spaltensummen bilden möchte tendiere zu der CSVDocument Lösung ... aber hab hier einfach zu wenig Wissen...

Mir würde eine einfache KISS Lösung reichen.

Ich werde jetzt erstmal für alle 3 Ansätze einfache Testprogramme schreiben und schauen...
ich merke auch das es schon verdammt lang her ist mit dem coden...

Den Quellcode für csvreadwrite habe ich gefunden...

Vielen Dank für Deine Hilfe!! Das ist echt super.
Die Daten müsste ich erst anonymisieren...

knight
Beiträge: 802
Registriert: Mi 13. Sep 2006, 22:30

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von knight »

Wenn deine Daten ohnehin schon in Excel vorliegen, dann würde ich mal einen Blick auf FPSpreadsheet werfen: http://wiki.lazarus.freepascal.org/FPSpreadsheet Damit wäre der Umweg über CSV nicht mehr notwendig.

knight

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von BitRausch »

danke für den Tipp!! FPSpreadsheet kannte ich noch nicht. Ich bekomme nur die CSV Dateien. Das Spreadsheet liegt mir nicht vor.

wp_xyz
Beiträge: 4885
Registriert: Fr 8. Apr 2011, 09:01

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von wp_xyz »

BitRausch hat geschrieben:Womit tue ich mich schwer?
Ich bin etwas verwirrt bei der Auswahl der richtigen Mittel:
- einfaches TStringList oder CSVDocument oder csvreadwrite beim einlesen?
- Ausgabe in Datei wie in Deinem Beispiel?
(Ich denke eine Datenbank-Komponente wäre hier nicht notwendig.)

Wenn ich Spaltensummen bilden möchte tendiere zu der CSVDocument Lösung ... aber hab hier einfach zu wenig Wissen...

Datenbank-Maschinerie erscheint mir auch überzogen.

Leider weiß ich immer noch nicht, wie die Daten aussehen. Ich denke, ich müsste dir ein einfaches Beispiel schreiben, aber ohne konkrete Angaben ist das genauso abstrakt wie alles, was bisher gesagt wurde. Denn eigentlich sind alle Hinweise schon genannt.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6208
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von af0815 »

Leichtgewichtig, könnte man SDF nehmen. Damit ist ein SDFDataSet möglich und dann sind zumindest rudimentäre DB Operationen möglich. Es hängt auch davon ab, wie die Daten strukturiert sind. Excel als Vorprodukt kann da jede strukturierte (DB) Verarbeitung verhindern :-)

Sind die CSV-Daten strukturiert ?

Andreas
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von BitRausch »

@wp_xyz
wp_xyz hat geschrieben:
BitRausch hat geschrieben:Womit tue ich mich schwer?
Leider weiß ich immer noch nicht, wie die Daten aussehen. Ich denke, ich müsste dir ein einfaches Beispiel schreiben, aber ohne konkrete Angaben ist das genauso abstrakt wie alles, was bisher gesagt wurde. Denn eigentlich sind alle Hinweise schon genannt.


Da gebe ich Dir recht. Schreibe gerade ein einfaches Prog mit Hilfe Deiner Tipps/Hinweise, um es mit ein paar einfachen Testdaten zu verdeutlichen. Vielleicht klappt es ja :wink:

@Andreas
Vielen Dank!
Was meinst Du mit strukturiert?
Die (CSV) Felder sind in einer bestimmten Reihenfolge.
SDFDataset schau ich mir gleich mal an...

Werde den Code mal posten dann hätten wir eine besser Gesprächsgrundlage...(hoffe ich schaffe es heute noch)
Ich wühle mich durch viele Informationen...

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von BitRausch »

habe jetzt mal ein kleines Prog geschrieben und TCSVDocument verwendet.
War schwieriger als ich dachte - liegt doch alles sehr weit zurück... :(
Das Prog ist sehr einfach gehalten aber ich hoffe es hilft beim Verständnis... :?:
eine kleine CSV Datei ist mit typischen Feldern, die verarbeitet werden müssen, dabei...
Im Memo wird der Satz so aufgebaut wie er später wieder in eine Datei geschrieben werden sollte... bin aber nicht soweit gekommen um eine entsprechende Routine einzubauen...
Auch die Routine für das bilden der Spaltensummen ist nicht enthalten ... werde mich morgen mal daran setzen...

Womit ich nicht zurechtgekommen bin war der try...final..end Part...und wie die Objekte wieder freigegeben werden ...

Ich bin mir nicht sicher ob TCSVDocument hier das richtige Mittel ist. Wenn ich die Menge der Datensätze denke und die Verarbeitung nach Spalten... :shock:

Wie auch immer ... ich würde mich sehr freuen wenn Ihr Euch das mal anschaut und mir euer Feedback geben könntet.
Spart bitte nicht an Kritik und Verbesserungsvorschläge. Ich lerne.

Echt Vielen Dank im Voraus!
Dateianhänge
CSVTest2.zip
Testprog für TCSVDocument
(128.11 KiB) 116-mal heruntergeladen

wp_xyz
Beiträge: 4885
Registriert: Fr 8. Apr 2011, 09:01

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von wp_xyz »

Ganz grob ist das schon in Ordnung. Nur würde ich beim Einlesen der Datei eher die Strategie verfolgen, die Strings so schnell wie möglich loszuwerden, denn mit Strings kannst du nicht rechnen. Daher würde ich den Record TDatensatz statt mit Strings gleich mit den richtigen Datentypen deklarieren:

Code: Alles auswählen

type
  TDatensatz = record
    IDNr: Integer;
    LfdNr: Integer;
    Zahl: Double;
    Datum: TDate;
    Text: String;
    Betrag: Double;
  end
 

Und dementsprechend würde ich die eingelesenen Daten nicht in einem CSVDocument speichern (denn da sind sie ja Strings), sondern z.B. in einem Array (oder einer Liste, TList, o.ä - aber das führt für den Wiedereinstieg wahrscheinlich zu weit). Für das Einlesen selbst reicht dann der CSVParser (oder man macht alles gleich "händisch" mit einer StringList, so schwer ist das nicht).

Arrays sind in FPC dynamisch, d.h. man kann mit SetLength() ihre Länge zur Laufzeit festlegen. Da die Anzahl der Zeilen nicht bekannt ist, reserviere ich immer in Blöcken von, z.B., 1000 Arrayelementen und lasse einen Zähler mitlaufen. Immer wenn der Zählerstand ohne Rest durch 1000 teilbar ist, ist der Block voll, und es wird die Arraylänge um weitere 1000 Elemente vergrößert. Am Ende des Einlesens wird dann das Array auf die nun bekannte Länge gtrimmt. (Man könnte das Array auch nach jeder Zeile um 1 Element verlängern, aber wenn die Datei groß ist, wird man das permanente umkopieren der Daten in der Geschwindigkeit merken).

Beim Umwandeln der Strings in Zahlen gibt es noch die Unschönheit, dass deine Werte einen Tausendertrenner enthalten, was keine der vorhanden Konvertierungsroutinen mag. Daher habe ich eine Routine ThSepStrToFloat geschrieben, die zuerst das Tausendertrennzeichen aus dem String entfernt und dann die Konvertierung durchführt.

Damit man etwas sieht habe ich zum Schluss das Daten-Array in einem Memo ausgegeben. Dabei kommt die Format()-Routine zum Einsatz, mit der man alle möglichen Datentypen zu einem String zusammen bauen kann. Ist am Anfang sicher umgewohnt, aber später unerlässlich, um ellenlange Stringverkettungsoperationen zu vermeiden. Schau dir die Dokumentation dazu an (https://www.freepascal.org/docs-html/rt ... ormat.html).

Deine eigenen Routinen zum Auffüllen eines Strings auf eine bestimmte Länge sind unnötig, sie gibt es schon in der Unit StrUtils (PadLeft und PadRight).

Das Memo musst du beim Programmende selbst nicht freigeben, das macht das Formular automatisch.

try-Böcke verwende ich in der Regel nur zusammen mit "finally". Da dabei der finally-teil immer durchlaufen wird, auch wenn im Block vorher ein Fehler aufgetreten ist, kann so sichergestellt werden, dass angeforderte Resourcen wieder freigegeben werden. In dem Beispiel kommt das mehrmals vor: Zum Beispiel wird der CSVParser erzeugt, und durch den finally-Abschnitt wird sichergestellt, dass der Parser wieder freigegeben wird. Also

Code: Alles auswählen

  csv := TCSVParser.Create;
  try
    // tue etwas mit dem Parser
  finally
    // Parser wird nicht mehr benötigt
    csv.free;
  end;


P.S.
Das beigefügte Demo-Programm funktioniert soweit. Allerdings habe ich nicht getestet, ob das Verlängern des Arrays richtig funktioniert, wenn der vorab reservierte Block voll ist. Normalerweise ist das kein Problem, aber da die Header-Zeile der Datei ja nicht ins Datenarray eingelesen wird, muss man das im Zähler korrigieren, und da rutscht ein -1 leicht an die falsche Stelle.
Dateianhänge
csv_test-wp.zip
(3.71 KiB) 143-mal heruntergeladen

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von BitRausch »

wow wp_xyz!!
Sehr geil! Vielen Dank!!

Ich muss mir das morgen genauer ansehen und verstehen ... ist jetzt zu spät...
Ich sehe jetzt schon vieles was ich checken kann/muss...Viel Input - sehr gut! :D

Das war/ist eine super Hilfe - vielen Dank für Deine Zeit wp_xyz!!
Hab mir den ganzen Tag dafür eingeplant...wer braucht schon Sonne :lol:

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von BitRausch »

@wp_xyz
Dein Beispiel sagt mehr als 1000 Worte! :wink:
Seit heute morgen sitze ich daran und folge Deinen Vorschlägen...

Bei der Umgestaltung des Records bin ich auf folgende Frage gestoßen:

- Ich habe numerische Felder mit 15 Vorkomma+2 Nachkomma = 17 Stellen - welchen Datentyp entspricht das - ist double hier richtig?
- dumme frage: Felder mit Prozentzahlen 3 Vorkomma+3 Nachkomma = 6 Stellen - entspricht das dem type single?

Bei Deinem Beispiel

Code: Alles auswählen

 
    memLog.Lines.Clear;
    s := PadLeft('ID', 3) + ' ' + PadLeft('LfdNr', 7) + ' ' +PadLeft('Zahl', 19)+ ' ' +
         PadLeft('Datum', 15) + '   ' + PadRight('Text', 10) + ' ' + PadLeft('Betrag', 19);
    memLog.Lines.Add(s);
    for i := 0 to High(Data) do begin
      with Data[i] do
        s := Format('%3d %7d %19.2f %10s   %-20s %19.2f', [
          IDNr, LfdNr, Zahl, DateToStr(Datum), Text, Betrag
        ]);
      memLog.Lines.Add(s);     
 
 


bekomme ich es nicht hin z.B Zahl mit führenden '0' aufzufüllen. Entweder finde ich das passende Formatzeichen nicht oder ich müsst jedes Feld einzeln formatieren
z.B.
s:= AddChar('0',PadLeft('Zahl', 19),19) )+' ' + ...

Oder übersehe ich da etwas?

wp_xyz
Beiträge: 4885
Registriert: Fr 8. Apr 2011, 09:01

Re: Welche Unit/Komponente für CSV Dateien

Beitrag von wp_xyz »

BitRausch hat geschrieben:- Ich habe numerische Felder mit 15 Vorkomma+2 Nachkomma = 17 Stellen - welchen Datentyp entspricht das - ist double hier richtig?
- dumme frage: Felder mit Prozentzahlen 3 Vorkomma+3 Nachkomma = 6 Stellen - entspricht das dem type single?

Immer wenn ein Dezimalpunkt drinnen ist, brauchst du Single, Double oder Extended, in dieser Reihenfolge mit wachsender Genauigkeitsanforderung (https://de.wikibooks.org/wiki/Programmi ... d_Extended); ich nehme routinemäßig meistens Double, als Kompromiss sozusagen. Mit max 3 Nachkommastellen ist Single völlig ausreichend, du wirst schon die Extremwerte von -E45 ... + E38 nicht überschreiten.

Bei diesen Gleitkommazahlen sind Rundungsfehler zu beachten, d.h. du darfst dich nicht darauf verlassen, dass 1.2 + 2.4 = 3.6 ist, denn die nächste binäre Zahl zu 1.2 könnte in Wirklichkeit 1.20000003 und zu 2.4 könnte es 3.3999999999 sein. Also bei Vergleichen immer die Funktion SameValue aus math verwenden, hier kann man einen Genauigkeitsparameter angeben, den ich üblicherweise eher großzügig ansetze (bei Single etwa 1E-6 - d.h. du vergleichst die ersten 6 Nachkommastellen).

Bei Geldbeträgen gibt es noch den Typ Currency, eigentlich ein Integer-Typ, der 4 Nachkommastellen darstellen kann. Hier gibt es keine Rundungsfehler.

Prozentzahlen gibt es in Pascal nicht. Du musst aus dem String das Prozentzeichen entfernen, den Rest in eine Gleitkommazahl umwandlen (Single reicht), und durch 100 dividieren.

BitRausch hat geschrieben:Bei Deinem Beispiel

Code: Alles auswählen

 
    memLog.Lines.Clear;
    s := PadLeft('ID', 3) + ' ' + PadLeft('LfdNr', 7) + ' ' +PadLeft('Zahl', 19)+ ' ' +
         PadLeft('Datum', 15) + '   ' + PadRight('Text', 10) + ' ' + PadLeft('Betrag', 19);
    memLog.Lines.Add(s);
    for i := 0 to High(Data) do begin
      with Data[i] do
        s := Format('%3d %7d %19.2f %10s   %-20s %19.2f', [
          IDNr, LfdNr, Zahl, DateToStr(Datum), Text, Betrag
        ]);
      memLog.Lines.Add(s);     
  

bekomme ich es nicht hin z.B Zahl mit führenden '0' aufzufüllen. Entweder finde ich das passende Formatzeichen nicht oder ich müsst jedes Feld einzeln formatieren
z.B.
s:= AddChar('0',PadLeft('Zahl', 19),19) )+' ' + ...

Oder übersehe ich da etwas?

Um eine Integer in der Format-Anweisung mit führenden Nullen darzustellen, musst du einen Punkten vor die Längenangabe setzen, also Format('%.3d', [IDNr]) statt Format('%3d', [IDNr]). Bei Gleitkommazahlen kenne ich das nicht, weil der Punkt da den Dezimalpunkt bezeichnet und die folgende Zahl als Zahl der Dezimalstellen genommen ist. Hier musst du führende Nullen manuall ergänzen:

Code: Alles auswählen

function PadZeroLeft(x: Double; Decimals, MaxLen: Integer): String;
begin
  Result := Format('%.*f', [Decimals, x])// Das Symbol '*' wird durch den Wert von Decimals ersetzt
  while Length(Result) < MaxLen do Result := '0' + Result;  // o.ä.   
end;

Antworten