CSV in ListView lesen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut

CSV in ListView lesen

Beitragvon Aphadias » 14. Aug 2018, 12:11 CSV in ListView lesen

Moin,

nach langer Zeit muss ich mich doch mal wieder melden :lol:

Ich möchte gerne eine CSV Datei in meine ListView lesen und danach in meiner vorhandenen Datenbank speichern. Ich habe 0 Plan wie ich das angehen soll. Es muss ja irgend wie eine for Schleife gebaut werden und sobald in der CSV ein ; kommt muss er i ein hoch rechnen oder?

bei PHP war es mit explode irgend wie leichter :lol:
Aphadias
 
Beiträge: 123
Registriert: 28. Okt 2015, 18:28

Beitragvon af0815 » 14. Aug 2018, 12:34 Re: CSV in ListView lesen

es gibt viel Möglichkeiten das zu machen. Hängt auch von der Qualität des csv ab :-)

CSV Kann man direkt als Datenbank lesen. http://wiki.freepascal.org/CSV

fpSpreadsheet kann es auch lesen http://wiki.freepascal.org/FPSpreadsheet

In ein StringList selbst einlesen und die richtigen Delimiter setzen http://forum.lazarus.freepascal.org/ind ... ic=17345.0
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
af0815
 
Beiträge: 3479
Registriert: 7. Jan 2007, 10:20
Wohnort: Niederösterreich
OS, Lazarus, FPC: FPC 3.2 Lazarus 2.0 per fpcupdeluxe | 
CPU-Target: 32Bit (64Bit)
Nach oben

Beitragvon Aphadias » 14. Aug 2018, 12:43 Re: CSV in ListView lesen

Danke für die schnelle Antwort ^^

Mit der Datenbank das habe ich schon mal gemacht. Aber dort habe ich ein DBGrid genommen weil ich damals schon dran gescheitert bin es in einer ListView zu schreiben. Nur dieses mal muss es in eine ListView ^^
Spreadsheet hatte ich mir auch schon angesehen... aber irgend wie zu kompliziert :roll:
Ich schaue mir es mal mit der StringList an. Mal schauen wie das wird
Aphadias
 
Beiträge: 123
Registriert: 28. Okt 2015, 18:28

Beitragvon Warf » 14. Aug 2018, 13:44 Re: CSV in ListView lesen

Die Subitems property eines ListItems ist ein TStrings, also müsste sowas gehen:
Code: Alles auswählen
with ListView1.Items.Add do
begin
  SubItems.Delimiter := ',';
  SubItems.StrictDelimiter := True;
  SubItems.DelimitedText := CSVLine;
  Caption := SubItems[0];
  SubItems.Delete(0);
end;


Die letzen zwei zeilen kannst du dir sogar sparen wenn du die erste spalte einfach unsichtbar machst und nur mit dem subitems arbeitest (mache ich gerne um dort zusätzliche Informationen wie Indexe oder so zu speichern).

Das einzige was du noch separat machen musst ist der Header (also die erste zeile)
Warf
 
Beiträge: 984
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon wp_xyz » 14. Aug 2018, 18:51 Re: CSV in ListView lesen

Im Anhang findest du ein Beispiel, wie eine CSV-Datei (geklaut von https://cerc.blackboard.com/Page/1189) in ein TListView eingelesen werden kann. Es gibt wahrscheinlich so viele Möglichkeiten wie Programmierer...

Da du offenbar neu in Pascal bist, habe ich die Datei zeilenweise mit Hilfe der klassichen Readln-Anweisungen eingelesen. Jede Zeile steht dann immer in einem String s, der mit dessen Helper-Methode .Split(',') an den Komma-Positionen zerhackt wird (das Gegenstück zum php-Explode); die Teile stehen dann in einem String-Array. Wenn man das mit der 1. Zeile macht, die die Überschriften enthält, hat man alle Informationen, um die Spalten der Listview zu erzeugen. Anschließend liest man den Rest der Datei und verteilt die zerhackten Strings vom Array in die Spalten der ListView, wobei zu beachten ist, dass in der 1.Spalte immer die Caption der ListItems steht, und die folgenden Strings in den SubItems.

P.S.
Die Warf-Methode ist gefällt mir besser als mein Beispiel. Aber ich wollte unbedingt das String.Split erwähnen, da im 1. Beitrag das Fehlen von php's explode bedauert wird.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
wp_xyz
 
Beiträge: 2642
Registriert: 8. Apr 2011, 08:01

Beitragvon Frank Ranis » 15. Aug 2018, 06:09 Re: CSV in ListView lesen

Hallo wp_xyz

ich muß dir mal ein dickes Lob aussprechen.

Deine Kern-Routine hast Du super dokumentiert , die kann man in 10,15,20 Jahren noch mal rauskramen und weis sofort was Sache ist.

Code: Alles auswählen
procedure TForm1.ReadCSVToListView(AFileName: String);
var
  F: TextFile;
  s: String;
  sa: TStringArray;
  listitem: TListItem;
  i: Integer;
begin
  // Neuzeichnen der ListView beim Hinzufügen von neuen Einträgen unterbinden.
  // Das würde alles sehr verlangsamen (natürlich nur bei großen Dateien).
  ListView1.Items.BeginUpdate;
 
  AssignFile(F, FILE_NAME);
  Reset(F);
 
  // TListView hat Spalten nur im Viewstyle vsReport
  ListView1.ViewStyle := vsReport;
 
  // Feldnamen einlesen - die stehen in der 1. Zeile
  // - Zeile einlesen
  ReadLn(F, s);
  // - In die einzelnen felder, die durch Komma getrennt sind, aufspalten
  sa := s.Split(',');
  // - Für jedes Feld eine Spalte erzeugen
  for i:=0 to High(sa) do
    with ListView1.Columns.Add do begin
      Caption := sa[i];
      Width := 150;
    end;
 
  // Nun den Rest der Datei einlesen
  while not EoF(F) do begin
    // - Aktuelle Zeile einlesen
    ReadLn(F, s);
    // - In die einzelnen Felder aufspalten
    sa := s.Split(',');
    // - ListItem für diesen Record erzeugen
    listitem := ListView1.Items.Add;
    // - Das 1.feld geht in die Caption des ListItem
    listitem.Caption := sa[0];
    // - Alle folgenden Felder gehen in die SubItems des ListItem
    // Achtung: Nummerierung beginnt hier bei 1, weil 0 ja schon verwendet wurde!
    for i := 1 to High(sa) do
      listitem.SubItems.Add(sa[i]);
  end;
 
  // Neuzeichnen der Listview wieder aktivieren und anstoßen.
  ListView1.Items.EndUpdate;
end;                     
 


Genau so wünscht man sich jeden Democode .

Gruß

Frank
www.flz-vortex.de
Frank Ranis
 
Beiträge: 111
Registriert: 24. Jan 2013, 21:22
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon Warf » 15. Aug 2018, 09:59 Re: CSV in ListView lesen

Noch ein kleiner tipp, Pack das Begin-End Update in ein Try-Finally:
Code: Alles auswählen
  ListView1.Items.BeginUpdate;
  try
    ...
  finally
    ListView1.Items.EndUpdate;
  end;


Sonst bekommst du eventuell in der Funktion einen Fehler (z.B. Datei lässt sich nicht öffnen) und durch die Exception wird EndUpdate nicht aufgerufen, was dazu führt das dein ListView sich nicht mehr aktualisieren kann. Macht also das gesammte Control nutzlos
Warf
 
Beiträge: 984
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Timm Thaler » 15. Aug 2018, 10:52 Re: CSV in ListView lesen

Code: Alles auswählen
    for i := 1 to High(sa) do
      listitem.SubItems.Add(sa[i]);
  end;


Was passiert, wenn in den Zeilen mehr Zellen vorhanden sind als im Header? Werden dann Zellinhalte in nicht vorhandene Subitems geschrieben?

Kann ja vorkommen, dass eine CSV fehlerhaft ist.
Timm Thaler
 
Beiträge: 707
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Warf » 15. Aug 2018, 10:55 Re: CSV in ListView lesen

Timm Thaler hat geschrieben:Was passiert, wenn in den Zeilen mehr Zellen vorhanden sind als im Header? Werden dann Zellinhalte in nicht vorhandene Subitems geschrieben?

Kann ja vorkommen, dass eine CSV fehlerhaft ist.


Gibt es weniger Subitems als Colums werden die restlichen Colums leer gefüllt, ich denke mal wenn es mehr gibt wird alles was übersteht einfach ignoriert/nicht gezeichnet (habs aber nicht getestet und hängt natürlich auch vom WS ab)
Warf
 
Beiträge: 984
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Aphadias » 16. Aug 2018, 17:14 Re: CSV in ListView lesen

Danke erst mal.

Leider funktioniert es bei mir noch nicht so wie es soll. Meine ListView soll im Caption bereich nicht beschrieben werden. Dazu soll es nur die erste Spalte beschrieben werden und als Split habe ich "

Problem macht mir eigentlich nur die erste Spalte. Eigentlich verstehe ich die For-Schleife so das er dafür sorgt ein nach unten zu gehen. Aber er geht wohl immer nach rechts.

Zur meiner Listview. Die hat ca 17 Spalten aber nur die erste soll beschrieben werden.

oder liegt es an der csv Datei? Die sieht ca. so aus

Text Art; Wort Wort, Schrift, Text"
Text Art; Wort Wort, Schrift, Text"
Text Art; Wort Wort, Schrift, Text"

und so soll es in einer Spalte auch untereinander stehen
Aphadias
 
Beiträge: 123
Registriert: 28. Okt 2015, 18:28

Beitragvon Warf » 16. Aug 2018, 18:34 Re: CSV in ListView lesen

Aphadias hat geschrieben:Danke erst mal.

Leider funktioniert es bei mir noch nicht so wie es soll. Meine ListView soll im Caption bereich nicht beschrieben werden. Dazu soll es nur die erste Spalte beschrieben werden und als Split habe ich "

Problem macht mir eigentlich nur die erste Spalte. Eigentlich verstehe ich die For-Schleife so das er dafür sorgt ein nach unten zu gehen. Aber er geht wohl immer nach rechts.

Zur meiner Listview. Die hat ca 17 Spalten aber nur die erste soll beschrieben werden.

oder liegt es an der csv Datei? Die sieht ca. so aus

Text Art; Wort Wort, Schrift, Text"
Text Art; Wort Wort, Schrift, Text"
Text Art; Wort Wort, Schrift, Text"

und so soll es in einer Spalte auch untereinander stehen


Dafür ist CSV nicht gedacht. Ist es immer einzeilig oder gibt es auch einträge die Mehrzeilig sein können.
Wenn es immer Einzeilig ist, vergiss die " und lies es einfach in eine TStringList ein und Iteriere dann über die Zeilen. Wenn es Mehrzeilig sein kann, kannst du entweder um es effizient zu gestalten einen Parser bauen oder einfach den ganzen Text spliten (und dann trim auf den einzelnen Elementen um die am anfang newlines wegzubekommen) und dann durchzuiterieren. Das braucht dann aber zwei Durchläufe (split muss einmal den gesamten Inhalt durchsuchen und du am ende musst jeden eintrag in den Listview einbauen).

Beispiel für das zweite:
Code: Alles auswählen
var sl: TStringList;
s: string;
begin
  sl:=TStringList.Create;
  try
    sl.LoadFromFile('csvFile');
    sl.Delimiter = '"';
    sl.StrictDelimiter := True;
    sl.DelimitedText := sl.Text;
    ListView1.BeginUpdate;
    try
      for s in sl do
        with ListView1.Items.Add do
           SubItems.Add(s.Trim);
    finally
      ListView1.EndUpdate;
    end;
  finally
    sl.Free;
  end;
end;
Warf
 
Beiträge: 984
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon wp_xyz » 16. Aug 2018, 18:53 Re: CSV in ListView lesen

Aphadias hat geschrieben:Zur meiner Listview. Die hat ca 17 Spalten aber nur die erste soll beschrieben werden.

Jetzt hast du mich komplett abgehängt: Wieso 17 Spalten, wenn du nur die erste beschreiben willst? Willst du jede Zeile der CSV-Datei unzerlegt komplett in der 1.Spalte anzeigen? Und du willst die Captions nicht beschreiben. Sollen die leer bleiben? Warum nimmst du dann überhaupt den vsReport Style der Listview und nicht vsList? Oder stehen da schon andere Informationen?

Bitte mache eine vernünftige Beschreibung deines Problems, vielleicht eine Skizze dazu. So verstehe ich nur Bahnhof.
wp_xyz
 
Beiträge: 2642
Registriert: 8. Apr 2011, 08:01

Beitragvon af0815 » 16. Aug 2018, 20:36 Re: CSV in ListView lesen

Aphadias hat geschrieben:oder liegt es an der csv Datei? Die sieht ca. so aus
Text Art; Wort Wort, Schrift, Text"
Text Art; Wort Wort, Schrift, Text"
Text Art; Wort Wort, Schrift, Text"

Das ist keine CSV, das ist kunterbunter Müll. Und genauso wie beim Müll, den muss man von Hand aus zerlegen, damit man ihn recyclen kann.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
af0815
 
Beiträge: 3479
Registriert: 7. Jan 2007, 10:20
Wohnort: Niederösterreich
OS, Lazarus, FPC: FPC 3.2 Lazarus 2.0 per fpcupdeluxe | 
CPU-Target: 32Bit (64Bit)
Nach oben

Beitragvon Aphadias » 17. Aug 2018, 13:56 Re: CSV in ListView lesen

wp_xyz hat geschrieben:
Aphadias hat geschrieben:Zur meiner Listview. Die hat ca 17 Spalten aber nur die erste soll beschrieben werden.

Jetzt hast du mich komplett abgehängt: Wieso 17 Spalten, wenn du nur die erste beschreiben willst? Willst du jede Zeile der CSV-Datei unzerlegt komplett in der 1.Spalte anzeigen? Und du willst die Captions nicht beschreiben. Sollen die leer bleiben? Warum nimmst du dann überhaupt den vsReport Style der Listview und nicht vsList? Oder stehen da schon andere Informationen?

Bitte mache eine vernünftige Beschreibung deines Problems, vielleicht eine Skizze dazu. So verstehe ich nur Bahnhof.


Ich versuche es mal bildlich zu erklären. Die ListView ist dazu da um Materialien in eine Datenbank zu speichern bzw auszulesen. Diese Materialien haben Chargen Abläufe Nummer usw... Sprich in der 1. Spalte kommt das Material 2. Spalte wieviel davon da sein soll 3. Wie viel da ist 4. Charge usw usw usw.. Die CSV Liste soll nur die Materialien enthalten. Sozusagen möchte ich das beim 1. Start der Nutzer die Materialien alle einlesen kann (aus der CSV-Liste) und danach zu jedem Material die Charge Datum usw einschreiben kann (weil es bei jedem Unterschiedlich ist). Deswegen soll nur die 1. Spalte aufgelistet werden weil der Name des Materials bei jedem gleich ist aber alle anderen Daten immer anders sind. Also eine Vorabmaske zur Arbeitserleichterung.

Die Captions sind schon bei der Erstellung der ListView vorgegeben und brauchen deswegen nicht beschrieben werden. Dort stehen die Reiter drin wie eben erwähnt.....

ist die Erklärung jetzt etwas einsichtiger?
Aphadias
 
Beiträge: 123
Registriert: 28. Okt 2015, 18:28

Beitragvon wp_xyz » 17. Aug 2018, 15:46 Re: CSV in ListView lesen

Ja, so ist es klar.

Studiere mal das beigefügte Demo. Vielleicht kannst du darauf aufbauen.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
wp_xyz
 
Beiträge: 2642
Registriert: 8. Apr 2011, 08:01

» Weitere Beiträge siehe nächste Seite »
Nächste

Zurück zu Freepascal



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste

porpoises-institution
accuracy-worried