| 
| Autor | Beitrag |  
| Hänsel 
          Beiträge: 152
 
 
 
 
 | 
Verfasst: Mo 08.09.25 06:15 
 
Hallo, kann jemand helfen ?
 Ich arbeite mit Delphi 10.
 Ich möchte eine .csv-Datei in eine Datenbank schreiben.
 Bekomme aber ständig die Fehlermeldung: "Listenindex außerhalb gültigen Bereich"
 Was habe ich hier vergessen bzw. falsch gemacht?
 			Moderiert von									| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 
 | procedure TForm_RWM.Import1FromCSVfile(sFile: string);var   ON,su,aus,be: string;
 tb,zah: Integer;
 tfDatei: TextFile;
 sZInhalt,D,ob : string;
 slWerte: TStringList;
 iZeile,zähler: Integer;
 Begin
 AssignFile(tfDatei, sFile);
 Reset(tfDatei);
 slWerte := TStringList.Create;
 slWerte.StrictDelimiter:=true;
 slWerte.Delimiter := #9;
 slWerte.DelimitedText := sZInhalt;
 slWerte.QuoteChar := ';';
 Readln(tfDatei,sZInhalt);
 inc(iZeile);
 iZeile:= 0;
 while not EoF(tfDatei) do
 begin
 Inc(iZeile);          if iZeile > 5 then            begin
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Open;
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Last;
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Append;
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Edit;
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_01']:='Test';
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_02'] := slWerte.Strings[2];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_02'] := slWerte.Strings[4];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_03']  := slWerte.Strings[7];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_04']  := slWerte.Strings[8];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_05']  := slWerte.Strings[9];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Post;
 end;
 end;
 zähler:= DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.RecordCount;
 Edit1.Text:=inttoStr(zähler);
 
 End;
 |   Th69: Delphi-Tags hinzugefügt |  |  |  
| jaenicke 
          Beiträge: 19326
 Erhaltene Danke: 1749
 
 W11 x64 (Chrome, Edge)
 Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
 
 | 
Verfasst: Mo 08.09.25 07:35 
 
Du weist den Wert sZInhalt (noch leer) der Stringliste slWerte zu und liest den Wert erst danach aus der Datei:
 		                       Delphi-Quelltext 
 									| 1:2:
 3:
 
 | slWerte.DelimitedText := sZInhalt;slWerte.QuoteChar := ';';
 Readln(tfDatei,sZInhalt);
 |  Dazu kommt, dass du in der Schleife gar nicht mehr aus der Datei liest.
 Du solltest dir vielleicht erst einmal überlegen, was du in welcher Reihenfolge machen musst, ohne Quelltext. Und danach dann schauen, wie du das umsetzt. Das ist kein Programmierproblem, sondern ein Logikproblem!
 Nebenbei:
 Warum lädst du nicht einfach alles in eine Stringlist und gehst dann zeilenweise durch deren Werte durch? Sprich dann hättest du zwei Stringlisten, eine für die Datei und eine für die einzelne Zeile. Für diesen Beitrag haben gedankt: Th69
 |  |  |  
| Hänsel  
          Beiträge: 152
 
 
 
 
 | 
Verfasst: Mo 08.09.25 10:11 
 
Danke für die Hinweise.
Da mir hier offensichtlich die Kenntnisse fehlen, wäre es schön ein Grundgerüst an Code zu bekommen. So dass ich die Vorgehensweise nachvollziehen kann.
 
 Danke im Voraus
 Hänsel
 |  |  |  
| jaenicke 
          Beiträge: 19326
 Erhaltene Danke: 1749
 
 W11 x64 (Chrome, Edge)
 Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
 
 | 
Verfasst: Mo 08.09.25 12:01 
 
Die wichtigste Frage ist erst einmal, ob das eine Aufgabe für einen Schulunterricht oder ähnliches ist? Denn im Code kommen Dinge vor wie die ungarische Notation (sl für Stringliste usw. bei den Variablen), die in Delphi absolut unüblich sind, die aber niemand einfach so macht. Denn wenn du eine bestimmte Aufgabenstellung hast, hilft dir eine andere Lösung vielleicht gar nicht weiter.
 Zeilenweise geht z.B. so: 		                       Delphi-Quelltext 
 									| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 
 | vari: Integer;
 slDatei: TStringList;
 begin
 slDatei := TStringList.Create;
 slDatei.LoadFromFile(sFile);
 for i := 0 to slDatei.Count - 1 do
 ShowMessage(slDatei[i]);
 ...
 |  Für diesen Beitrag haben gedankt: Hänsel
 |  |  |  
| Hänsel  
          Beiträge: 152
 
 
 
 
 | 
Verfasst: Mo 08.09.25 12:19 
 
Nein das ist nicht für die Schule.
Ich möchte für einige Rauchwarnmelder welche funken, die ecsv-Datei in eine Datenbank schreiben.
 |  |  |  
| Hänsel  
          Beiträge: 152
 
 
 
 
 | 
Verfasst: Di 09.09.25 08:07 
 
Zu meiner oben gestellten Frage habe ich folgendes herausgefunden: Wenn ich nach den Einstellungen eine .csv Datei einlesen möchte, gibt es eine Fehlermeldung wie beschreiben. Wenn ich eine .rep Datei einlesen möchte, klappt bestens. Welche Voreinstellung habe ich vergessen bzw. falsch gemacht?
 Gruß Hänsel
 |  |  |  
| mandras 
          Beiträge: 434
 Erhaltene Danke: 107
 
 Win 10
 Delphi 6 Prof, Delphi 10.4 Prof
 
 | 
Verfasst: Di 09.09.25 23:19 
 
- Könntest Du einmal die CSV-und die andere Datei (ausschnittsweise) hier einstellen?
 - stimmt Dein Listing?
 Eigentlich dürfte es gar nicht funktionieren, egal mit was für einer Datei. Grund:
 		                       Delphi-Quelltext 
 									| 1:2:
 3:
 
 | slWerte.DelimitedText := sZInhalt;slWerte.QuoteChar := ';';
 Readln(tfDatei,sZInhalt);
 |  Bei dem von Dir gezeigten Code bekommt die StringList gar nichts davon mit, was in der Datei steht,
 da die Zuweisung an DelimitedText erfolgt, bevor aus der Datei gelesen wird. |  |  |  
| Hänsel  
          Beiträge: 152
 
 
 
 
 | 
Verfasst: Mi 10.09.25 06:47 
 
Anbei die .csv Datei zur Einsicht.
Hänsel
 |  |  |  
| Hänsel  
          Beiträge: 152
 
 
 
 
 | 
Verfasst: Mi 10.09.25 07:19 
 
So geht es vielleicht besser:
 		                       CSV 
 									| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 
 | Programmname;   Ablesungsdatum;  Funkadresse;  Benutzerfeld;  Ausgangskode (Fehler);   Seriennummer;  Identifikationsnummer;  HerstellercodeSonSa2O-ANDROID;03.09.2025 13:30;  30802114;    Ablesung OK;    30802114;  SON;
 SonSa2O-ANDROID;03.09.2025 13:30;  30802115;    Ablesung OK;    30802115;  SON;
 SonSa2O-ANDROID;03.09.2025 13:30;  30802110;    Ablesung OK;    30802110;  SON;
 SonSa2O-ANDROID;03.09.2025 13:30;  30802112;    Ablesung OK;    30802112;  SON;
 SonSa2O-ANDROID;03.09.2025 13:30;  30802106;    Ablesung OK;    30802106;  SON;
 SonSa2O-ANDROID;03.09.2025 13:30;  30802109;    Ablesung OK;    30802109;  SON;
 SonSa2O-ANDROID;03.09.2025 13:30;  30802111;    Ablesung OK;    30802111;  SON;
 SonSa2O-ANDROID;03.09.2025 13:30;  30802108;    Ablesung OK;    30802108;  SON;
 SonSa2O-ANDROID;03.09.2025 13:30;  30802101;    Ablesung OK;    30802101;  SON;
 SonSa2O-ANDROID;03.09.2025 13:30;  30802102;    Ablesung OK;    30802102;  SON;
 |  getrennt sind die Felder mit  ';'
Moderiert von  Th69: Code-Tags hinzugefügt |  |  |  
| jasocul 
          Beiträge: 6395
 Erhaltene Danke: 149
 
 Windows 7 + Windows 10
 Sydney Prof + CE
 
 | 
Verfasst: Mi 10.09.25 11:01 
 
Oh je, wo soll ich anfangen?     Erstmal grundlegendes im Ausgangssource (Ich habe da ein paar Kommentare eingetragen):
 												| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 42:
 43:
 44:
 
 | procedure TForm_RWM.Import1FromCSVfile(sFile: string);var   ON,su,aus,be: string;
 tb,zah: Integer;
 tfDatei: TextFile;
 sZInhalt,D,ob : string;
 slWerte: TStringList;
 iZeile,zähler: Integer;
 Begin
 AssignFile(tfDatei, sFile);
 Reset(tfDatei);
 slWerte := TStringList.Create;
 slWerte.StrictDelimiter:=true;
 slWerte.Delimiter := #9;          slWerte.DelimitedText := sZInhalt;          slWerte.QuoteChar := ';';          Readln(tfDatei,sZInhalt);          inc(iZeile);               iZeile:= 0;      while not EoF(tfDatei) do
 begin
 Readln(tfDatei,sZInhalt);          Inc(iZeile);          slWerte.DelimitedText := sZInhalt;          if iZeile > 5 then            begin
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Open;                DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Last;                DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Append;
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Edit;                DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_01']:='Test';
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_02'] := slWerte.Strings[2];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_02'] := slWerte.Strings[4];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_03']  := slWerte.Strings[7];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_04']  := slWerte.Strings[8];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_05']  := slWerte.Strings[9];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Post;
 end;
 end;
 zähler:= DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.RecordCount;
 Edit1.Text:=inttoStr(zähler);
 
 End;
 |  Dazu kommt, dass die CSV-Datei unvollständig gefüllt ist. Das bedeutet, dass du immer prüfen musst, wieviel Einträge in der StringList sind. Ansonsten greifst du auf Elemente zu, die gar nicht existieren. Das führt dann ebenfalls zu Fehlern beim Listenindex. Die Zählung bei der StringList fängt übrigens bei 0 an. Die CSV-Datei hat 8 Spalten. Das bedeutet, dass du maximal einen Index zwischen 0 und 7 hast. Aktuell sehe ich nur 5 der Spalten besetzt. Das wäre dann Index 0 bis 4. Kommt da dein "if iZeile > 5 then" eventuell her? Dann scheinst du Spalten mit Zeilen zu verwechseln.
 Damit es übersichtlicher wird:
 												| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 42:
 43:
 44:
 45:
 46:
 
 | procedure TForm_RWM.Import1FromCSVfile(sFile: string);var   ON,su,aus,be: string;
 tb,zah: Integer;
 tfDatei: TextFile;
 sZInhalt,D,ob : string;
 slWerte: TStringList;
 iZeile,zähler: Integer;
 Begin
 AssignFile(tfDatei, sFile);
 Reset(tfDatei);
 slWerte := TStringList.Create;
 slWerte.StrictDelimiter:=true;
 slWerte.Delimiter := ';';
 iZeile:= 0;
 
 if not EoF(tfDatei) do
 begin
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Open;
 while not EoF(tfDatei) do
 begin
 Readln(tfDatei,sZInhalt);              Inc(iZeile);
 if iZeile > 1 then                begin
 slWerte.DelimitedText := sZInhalt;                    if slWerte.Count = 6 then                      begin
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Append;
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_01']:= slWerte.Strings[0];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_02'] := slWerte.Strings[1];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_02'] := slWerte.Strings[2];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_03']  := slWerte.Strings[3];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_04']  := slWerte.Strings[4];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM['Feld_05']  := slWerte.Strings[5];
 DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.Post;
 else begin
 end;
 end;
 end;
 zähler:= DataModule_RWM_Auswertung.ADOQuery_Einlesung_RWM.RecordCount;
 Edit1.Text:=inttoStr(zähler);
 
 end;
 End;
 |  Der Source ist ungeprüft reingetippt. Es können also durchaus Fehler vorliegen. Für diesen Beitrag haben gedankt: Hänsel
 |  |  |  
| Hänsel  
          Beiträge: 152
 
 
 
 
 | 
Verfasst: Fr 12.09.25 05:42 
 
Danke für die Hilfe.
wozu wird noch diese IF-Abfrage geschrieben. Denn danach folgt doch die Schleife? (nur für mich zum Verständnis).
 Es steht doch geschrieben, alles was größer 1 ist sind Daten(if iZeile > 1 ). Es wird trotzdem die Überschrift, sprich Spalten/Feldbezeichnung mit geschrieben. Schreibe ich ab Zeile 2 funktioniert es. Aber das wäre ja nicht korrekt, oder?
 |  |  |  
| jasocul 
          Beiträge: 6395
 Erhaltene Danke: 149
 
 Windows 7 + Windows 10
 Sydney Prof + CE
 
 | 
Verfasst: Fr 12.09.25 07:00 
 
if not EoF(tfDatei) do sorgt dafür, dass du nur mit einer Datei arbeitest, die auch Daten enthält. Ansonsten müsstest du weitere Prüfungen im Rest des Sources einbauen, was das Ganze unübersichtlich macht.
 Das if iZeile > 1 then soll dafür sorgen, dass die Zeile mit den Überschriften übersprungen wird. Falls das nicht so funktioniert, musst du mal mit dem Debugger prüfen, was in deinen Variablen steht. Vielleicht hat die CSV-Datei noch Besonderheiten, die wir so nicht erkennen können.
 
 Das if slWerte.Count = 6 then sorgt dafür, dass du nur Daten in die Datenbank schreibst, wenn die Zeile in der CSV-Datei die richtige Anzahl an Einträgen (Spalten) hat.
 
 Unabhängig von der Grundsatzprüfung auf eine brauchbare Datei, haben die anderen if die Aufgabe, sich um Zeilen und Spalten zu kümmern. Dabei ist das erste if für die Zeilen zuständig  und das andere für die Spalten.
 Sollte das nicht passen, musst du den Debugger bemühen und gegebenenfalls selbst die richtigen Vergleichswerte ermitteln.
 Für diesen Beitrag haben gedankt: Hänsel
 |  |  |  
| Hänsel  
          Beiträge: 152
 
 
 
 
 | 
Verfasst: Fr 12.09.25 08:09 
 
Hallo 
nochmals Danke. Hat gut funktioniert.
 
 Gruß Hänsel
 |  |  |  |