Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Problem mit dem Import aus einer csv-Datei in eine StringList (https://www.delphipraxis.net/204196-problem-mit-dem-import-aus-einer-csv-datei-eine-stringlist.html)

Luca Haas 5. Mai 2020 14:02

Problem mit dem Import aus einer csv-Datei in eine StringList
 
Hallo zusammen,

ich sitze nun seit letzter Woche daran eine CSV-Datei einzulesen und diese in eine StringList zu schreiben.
Das Ganze benötige ich, um 6 Daten der Liste in einenen DataRecord zu schreiben, hier mein fehlerhafter Code:
Delphi-Quellcode:
var
  tfDatei: TextFile;
  sZInhalt: string;
  liste: TStringList;
  i: Integer;
  tempRecord: dataRecord;
begin
  if ((OpenDialog1.Execute()) and (OpenDialog1.Filename <> '')) then
  begin
    GanttChart1.BeginUpdate(); // Änderungen an der Oberfläche werden gemacht
    try
      liste := TStringList.Create();
      try
        AssignFile(tfDatei, OpenDialog1.Filename);
        Reset(tfDatei);
        i := 0;
        while not Eof(tfDatei) do
        begin
          liste := TStringList.Create;
          ReadLn(tfDatei, sZInhalt);
          liste.Delimiter := ';';
          liste.StrictDelimiter := True;
          liste.DelimitedText := sZInhalt;

          Inc(i); // Kopfzeile

          if i > 1 then // Datenzeilen
          begin //Hier teste ich mit Beispieldaten was auch funktioniert
            tempRecord.StartDate := StrToDateTime('01.01.2020');
            tempRecord.EndDate := StrToDateTime('03.01.2020');
            tempRecord.Duration := 120;
            tempRecord.Bez := 'Test';
            tempRecord.AuftragNr := 123312;
            tempRecord.AuftragPosNr := 1;
            tempRecord.ArbeitsplanPosNr := 1;

            (* // Sobald ich mit liste.Strings[] echte Daten nutzen möchte sütrzt das Programm ab
              tempRecord.StartDate := StrToDateTime(liste.Strings[14]);
              tempRecord.EndDate := StrToDateTime(liste.Strings[15]);
              tempRecord.Duration := StrToInt(liste.Strings[19]);
              tempRecord.Bez := liste.Strings[7];
              tempRecord.AuftragNr := StrToInt(liste.Strings[9]);
              tempRecord.AuftragPosNr := StrToInt(liste.Strings[10]);
              tempRecord.ArbeitsplanPosNr := StrToInt(liste.Strings[2]);
            *)

            csvRecords.Add(tempRecord); // csvRecords ist eine TList<dataRecord> und wurde bereits deklariert
          end;
        end;
      except
        MessageDlg('Est ist ein Fehler aufgetreten, der Prozess wird beendet.', mtError, [mbOK], 0);
      end;
    finally
      FreeAndNil(liste);
      CloseFile(tfDatei);
      GanttChart1.EndUpdate(); // Repaint
    end;
  end;
end;
Ich habe mich schon durch diverse Foren gelesen, allerdings habe ich es selbst damit nicht geschafft das Ganze zu lösen, also wäre es super wenn ich über diesen Weg nötige Hilfe finden könnte.

DeddyH 5. Mai 2020 14:05

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Du hast Dir aber ein schönes Speicherleck gebaut. Bist Du sicher, dass Du die Liste einmal vor und dann noch einmal innerhalb der Schleife erzeugen willst?

Luca Haas 5. Mai 2020 14:09

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Ohje. :oops:
Nein ist natürlich Schwachsinn, aber behebt das Problem leider nicht.

Hobbycoder 5. Mai 2020 14:14

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
die Frage ist ja, was passiert denn? Gibt es Fehlermeldungen? Werden denn die Records mit Daten gefüllt? Läufst du in deinen Except-Block?
Hast du das ganz mal im Debugger schrittweise laufen lassen?

ich würde statt
Delphi-Quellcode:
StrToDateTime(liste.Strings[14]);
mal das
Delphi-Quellcode:
StrToDateTime(liste[14]);
probieren. Ist ja schon eine StringList. Aber das wird nicht das Problem sein.

Aber Vorsicht, immer prüfen, ob dein liste überhaupt 15 items hat.

DeddyH 5. Mai 2020 14:14

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Wie viele Einträge enthält die Liste denn nach der Zuweisung von DelimitedText?

Luca Haas 5. Mai 2020 14:21

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
@Hobbycoder, ja ich habe das Ganze schon des öfteren debuggt, sobald ich einen Eintrag der Liste ansprechen möchte springe ich in den Except Block der mir meine Fehlermeldung ausgibt.
Edit: Wenn ich die erste Position der Liste anzeige bekomme ich, mir unbekannte, Schriftzeichen, bei allen anderen Positionen der Liste komme ich dann n den Except Block.

@DeddyH, wenn ich mir die Länge der Liste nach dem DelimitedText anzeige variiert diese zwischen 0 und 3 für alle Einträge (knapp 30 Stück)

Hobbycoder 5. Mai 2020 14:23

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Dann zeig doch mal, was zu dem Zeitpunkt in szInhalt steht.

Luca Haas 5. Mai 2020 14:28

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Liste der Anhänge anzeigen (Anzahl: 1)
In sZInhalt werden mir nach dem DelimitedText nur "zufällige" Zeichen angezeigt, wobei sich diese auch in jedem Durchlauf ändern-

stifflersmom 5. Mai 2020 14:33

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Zitat:

Zitat von Luca Haas (Beitrag 1463725)
@DeddyH, wenn ich mir die Länge der Liste nach dem DelimitedText anzeige variiert diese zwischen 0 und 3 für alle Einträge (knapp 30 Stück)

Wenn die Länge der Liste variiert, dann hast Du Dein Problem doch schon gefunden, da Du ja feste Linienpositionen umwandeln willst.
Zeig doch mal ein paar dieser Textzeilen aus Deiner Importdatei.

Hobbycoder 5. Mai 2020 14:33

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
naja, findest du irgendwo in dem String ein Semikolon?
Ist die Datei wirklich eine Textdatei? Öffne sie mal mit Notepad.

Luca Haas 5. Mai 2020 14:38

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Also meine importierte Datei ist eine .csv-Datei und keine direkte Textdatei.
Wenn ich diese im Notepad öffne erhalte ich die Zeichen, welche ich mir eben ausgeben lassen habe.

Und nein ich finde hier im String kein Semikolon.

stifflersmom 5. Mai 2020 14:40

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Zitat:

Zitat von Luca Haas (Beitrag 1463733)
Also meine importierte Datei ist eine .csv-Datei und keine direkte Textdatei.
Wenn ich diese im Notepad öffne erhalte ich die Zeichen, welche ich mir eben ausgeben lassen habe.

Und nein ich finde hier im String kein Semikolon.

CSV ist eine Textdatei.
Und ohne Semikolon kann Deine Stringliste dann auch nicht "delimiten"...

Luca Haas 5. Mai 2020 14:42

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Also liegt das Problem nicht an meinem Code, sondern an der Datei, welche ich importieren möchte ?

stifflersmom 5. Mai 2020 14:42

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Sehr wahrscheinlich

Luca Haas 5. Mai 2020 14:45

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Okay, danke schonmal für die Info.

Allerdings weiß ich nicht wie ich die Datei dann entsprechend anpasse, dass ich Sie delimiten kann...

stifflersmom 5. Mai 2020 14:49

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Wie schon gesagt ist CSV eine Textdatei, die kannst Du selbst mit einem Texteditor Deiner Wahr erstellen.
Du kannst natürlich auch eine Exceldatei als CSV exportieren, das ist dann bequemer.

In der CSV-Date stehen dann Deine Werte, die Du einlesen möchtest mit einem Trennzeichen, in Deinem Fall das Semikolon, getrennt voneinander

Als Beispiel:
wert1;name1;geburt1;

Diese eine Zeile wird dann per Delimiter über DelimitedText in die Strings Deiner Stringlist umgewandelt:
Liste[0] = wert1
liste[1] = name1
liste[2] = geburt1

Wie Du siehst ist das ganz simpel.

Luca Haas 5. Mai 2020 14:51

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Okay dann bedanke ich mich nochmal bei allen die mir hierbei weitergeholfen haben und dann versuche ich mal eine neue Datei zu erstellen, welche ich dann auch richtig einlesen kann.

DeddyH 5. Mai 2020 14:52

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Für viele Menschen gilt die Formel csv = Excel. Vielleicht hat jemand ein Worksheet (*.xls bzw. *.xlsx) einfach in *.csv umbenannt. Dann kann das auch nicht funktionieren.

Delphi.Narium 5. Mai 2020 14:57

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Zitat:

Zitat von Luca Haas (Beitrag 1463725)
@Hobbycoder, ja ich habe das Ganze schon des öfteren debuggt, sobald ich einen Eintrag der Liste ansprechen möchte springe ich in den Except Block der mir meine Fehlermeldung ausgibt.
Edit: Wenn ich die erste Position der Liste anzeige bekomme ich, mir unbekannte, Schriftzeichen, bei allen anderen Positionen der Liste komme ich dann n den Except Block.

@DeddyH, wenn ich mir die Länge der Liste nach dem DelimitedText anzeige variiert diese zwischen 0 und 3 für alle Einträge (knapp 30 Stück)

Das klingt jetzt erstmal so, als ob ReadLn die Datei garnicht so zeilenweise lesen kann, wie es erwartet wird. Unbekannte Zeichen lassen auch darauf schließen.

Die erste Frage, die zu beantworten wäre ist: Um was für eine Datei handelt es sich?
Zweite Frage: Was für einen Zeichensatz enthält sie.
Dritte Frage: Enthält sie den windowstypischen Zeilenumbruch von #13#10?

Achso: csv heißt Comma-separated values
Ein Semikolon ist kein Komma.

Also zuerst mal prüfen, welches Zeichen denn zur Trennung der einzelnen Werte genutzt wird und dieses Zeichen dann als Delimiter nutzen.

Probier' es mal nicht mit AssignFile ... sondern mit zwei Stringlisten:
Delphi-Quellcode:
var
  sZInhalt: string;
  Datei: TStringList;
  liste: TStringList;
  i: Integer;
  tempRecord: dataRecord;
begin
  if ((OpenDialog1.Execute()) and (OpenDialog1.Filename <> '')) then
  begin
    GanttChart1.BeginUpdate(); // Änderungen an der Oberfläche werden gemacht
    try
      Datei := TStringList.Create();
      liste := TStringList.Create();
      try
        Datei.LoadFromFile(OpenDialog1.Filename);
        // 0. Zeile ist die Kopfzeile, die wir nicht benötigen.
        for i := 1 to Datei.Count - 1 do begin
          // Hier den tatsächlich genutzten Delimiter einfügen.
          // CSV ist nicht gleichbedeutend mit Delimiter := ';'
          liste.Delimiter := ';';
          liste.StrictDelimiter := True;
          liste.DelimitedText := Datei[i];
          if Liste.Count > 19 then // Diese Zeilen ggfls. anpassen an die tatsächlichen Gegebenheiten.
          begin //Hier teste ich mit Beispieldaten was auch funktioniert
            tempRecord.StartDate := StrToDateTime('01.01.2020');
            tempRecord.EndDate := StrToDateTime('03.01.2020');
            tempRecord.Duration := 120;
            tempRecord.Bez := 'Test';
            tempRecord.AuftragNr := 123312;
            tempRecord.AuftragPosNr := 1;
            tempRecord.ArbeitsplanPosNr := 1;

            (* // Sobald ich mit liste.Strings[] echte Daten nutzen möchte sütrzt das Programm ab
              tempRecord.StartDate := StrToDateTime(liste.Strings[14]);
              tempRecord.EndDate := StrToDateTime(liste.Strings[15]);
              tempRecord.Duration := StrToInt(liste.Strings[19]);
              tempRecord.Bez := liste.Strings[7];
              tempRecord.AuftragNr := StrToInt(liste.Strings[9]);
              tempRecord.AuftragPosNr := StrToInt(liste.Strings[10]);
              tempRecord.ArbeitsplanPosNr := StrToInt(liste.Strings[2]);
            *)

            csvRecords.Add(tempRecord); // csvRecords ist eine TList<dataRecord> und wurde bereits deklariert
          end else begin
            MessageDLG(Format('Es wurden nur %d Zeilen für Datensatz %d geliefert. Bitte Dateiformat prüfen.',[Liste.Count,i]),mtError,[mbOk],0);
            break;
          end;
        end;
      except
        // Except ist gut, die Fehlermeldung auch auszugeben deutlich besser.
        on e : Exception do begin
          MessageDlg(Format('Es ist ein Fehler aufgetreten: %s%s',[#13#13,e.Message], mtError, [mbOK], 0);
        end;
      end;
    finally
      FreeAndNil(liste);
      FreeAndNil(Datei);
      GanttChart1.EndUpdate(); // Repaint
    end;
  end;
end;
(Nur hingedaddelt und nicht getestet.)

Zitat:

Allerdings weiß ich nicht wie ich die Datei dann entsprechend anpasse, dass ich Sie delimiten kann...
Die Datei kommt doch irgendwo her, der Lieferant muss also anpassen oder Du musst Deinen Code an die Datei anpassen.

Wenn Du da Hilfe möchtest, häng' bitte mal eine entsprechende Datei hier an, dann können wir mit reinschauen und nach 'ner Lösung suchen. Ohne den konkreten Inhalt der Dateien zu kennen, ist eine wirklich zielführende Hilfe nicht möglich.

Achso: Weil ich wiedermal deutlich zu lang für meine Antwort benötigt habe, könnten sich Teile davon inzwischen erübrigt haben ;-)

Luca Haas 5. Mai 2020 14:57

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
@DeddyH Ja genau das scheint das Problem gewesen zu sein.

Luca Haas 5. Mai 2020 15:01

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Danke @Delphi.Narium für die überaus detaillierte Hilfe, allerdings habe ich nun die einzulesende Datei als den Fehler ausfindig machen können.
Mit einer von mir neu erstellten csv-Datei klappt das ganze, von daher denke ich, dass ich die zu importierende Datei alleine anpassen kann.

Alallart 5. Mai 2020 15:28

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
@Luca Haas

Ich habe deinen Code nur grob überflogen, und vielleicht wurde das bereits angesprochen (ich habe nicht alle Beiträge gelesen), oder du willst eine andere Lösung, aber warum der Aufwand? Eigentlich ist das Importieren eine CSV-Datei in der Regel Pillepalle. Die Technik beherrscht TStringList von Haus aus. Wobei ganz sauber wird der Import wenn die Felder in Anführungszeichen gesetzt sind.

Jetzt mal auf die Schnelle:

Delphi-Quellcode:
var
  slDatei,
  slDatensatz: TStringList;
  i, k: Integer;
begin
  slDatei := TStringList.Create;
  slDatensatz := TStringList.Create;
  try
    slDatei.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'Adressen.csv');
    slDatensatz.Delimiter := ';';
    for i := 0 to slDatei.Count - 1 do
    begin
      slDatensatz.DelimitedText := slDatei[i];

      for k := 0 to slDatensatz.Count - 1 do
        ShowMessage(slDatensatz[k]);
    end;
  finally
    slDatei.Free;
    slDatensatz.Free;
  end;
end;
Beispieldatei "Adressen.csv"

Code:
"Anrede";"Vorname";"Nachname";"Fima";"Adresse 1";"PLZ";"Ort"
"Frau";"Liselotte";"Müller";"Maier GmbH";"Schwetzingerstr. 7";"81234";"München"
"Herr";"Peter";"Becker ";"Hochbau AG";"Lustigstraße 2";"12345";"Berlin"

In der For-k Schleife muss man die Felder nur noch richtig zuordnen.

Moombas 6. Mai 2020 08:07

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
@Alallart: Leider ist nicht jede CSV mit "" ausgestattet. Wir haben hier im Unternehmen mehrere Bereiche wo mit csv gearbeitet wird und einige Hersteller/Firmen übergeben dies leider ohne die "". Also so:
Zitat:

abc;def;ghi;jkl
Aber ich gebe dir Recht, das wenn man Einfluss drauf hat, das mit den "" der wesentlich schönere Weg ist.

@Luca: Wenn das wirklich anfangs nur eine umbenannte Excel-Datei war, glaube ich kaum das beim öffnen im Texteditor da irgendetwas vernünftiges stand. Denn Excel-Dateien sind nun mal generell genommen "nur" Zip-Archive und die lassen sich nicht im Texteditor lesen (nur kryptische Zeichen).

Jumpy 6. Mai 2020 08:46

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Zitat:

Zitat von DeddyH (Beitrag 1463741)
Für viele Menschen gilt die Formel csv = Excel. Vielleicht hat jemand ein Worksheet (*.xls bzw. *.xlsx) einfach in *.csv umbenannt. Dann kann das auch nicht funktionieren.

[Offtopic]
Wir haben auch Kollegen, die bei .xlsx Dateien gerne mal das hintere x in der Dateiendung wegmachen, damit Kunden mit älteren Excel-Versionen das auch öffnen können. :thumb:
[/Offtopic]

p80286 6. Mai 2020 10:09

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Daß man einen Hex-Editor zur Anzege jeder Datei nutzen kann, hat sich wohl immer noch nicht herum gesprochen.
zb:https://mh-nexus.de/de/
oder was ich für den schnellen Blick bevorzuge:https://www.safer-networking.org/de/...ts/filealyzer/

Gruß
K-h

Delphi.Narium 6. Mai 2020 10:30

AW: Problem mit dem Import aus einer csv-Datei in eine StringList
 
Oder Norton Commander: Taste F3.

Diverse Clones/Nachbauten davon haben ebenfalls diese Möglichkeit und werden immernoch weiterentwickelt.

Die neueste, mir bekannte, Version eines dieser Clones ist vom 25.03.2020 und für 32 sowie 64 Bit verfügbar (Windows 95 bis Windows 10).


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:56 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