![]() |
Datenbank: Access • Zugriff über: ADO
CSV --> Stringlist --> Stringlist zerlegen --> in D
Hallo Leute,
ich bin (wiedermal) Newbie. Das hängt daran, dass ich gezwungen war fast ein Jahr mit Delphi auszusetzen. ;o( Jetzt zu meinem Problem. Ich sitze seit 2 Tagen dran, habe viele Lösungen hier und sonst wo gefunden aber es wird einfach kein Licht in meinem Hirn. Ich habe eine CSV-Datei, die ich in einer Stringlist Zeile für Zeile einlesen will. Nun das Funzt schon. *na toll* Ich muss aber noch einiges verstehen. 1. Wie stelle ich fest, wieviele Spalten die CSV hat. Die Trennung hier ist ein Semikolon (;) 2. Dann muss ich erfahren, wie diese Spalten heißen. Diese Info stehen ja in der ersten Zeile. Mir ist einfach nicht klar, wie ich die Namen (Werte) vor dem Semikolon erfahre. 3. Ist fast die Nummer 2. Ich muss dann die jeweiligen Werte (der folgenden Zeilen) in Variablen stecken und diese in mehrere Tabellen meiner DB einlesen. Das Teilen und einfügen wird wohl nicht so sehr das Problem sein aber die Punkte 1 - 3 sind für mich seit 48 Stunden ein großes schwarzes Loch. Bitte helft mir den Lichtschalter zu finden. In diesem Sinne Danke schon mal. Leon |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Zitat:
Zitat:
Delphi-Quellcode:
3. Ist fast die Nummer 2. Ich muss dann die jeweiligen Werte (der folgenden Zeilen) in Variablen stecken und diese in mehrere Tabellen meiner DB einlesen.
for i := 0 to StringList.Count -1 do
begin ... s := StringList.Strings[i]; ... end; Leon[/quote] Wie 2. in jeder weiteren Zeile kannst du die Werte wie in 2. die Name auslesen |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Hallo Leon,
vielleicht hilft es dir, wenn du eine kleine Beispielanwendung studierst: ![]() Grüße vom marabu |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Hi Marabu,
danke für die Unterstützung aber ich kann das nicht ansehen. Komponennten fehlen mir.. naja, ich beiß mich schon durch die angaben von euch durch... :o) @MKinzler: Wie meinst du das mit StringList.Count zu punkt 1? |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Wenn du die erste Zeile der CSV-Datei geladen hast und diese mit Hilfe der Eigenschaft DelimitedText der Stringlist zugewiesen hast, dann enthält die Eigenschaft Count die Anzahl der Spalten.
|
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Hi,
schau Dir mal die Routine in diesem Thread an ![]() |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Ääähhh jaaa... :o)
Okay. ich schreib mal was mein prog bis her macht und dann weiß ich nicht mehr weiter wie ich es schreiben soll...
Delphi-Quellcode:
Sicher fehlen hier noch schleifen das ist klar. Kannst du damit was anfangen?
var
sl: TStringList; zeilennr: integer; DateiName, S: String; F: TextFile; begin OpenDialog1.Execute; // Das Ergebnis steht in FileName // ShowMessage(OpenDialog1.FileName); DateiName := OpenDialog1.FileName; //Der Pfad wird in die Datei gestellt // ShowMessage(DateiName); sl:=TStringList.Create; //Objekt erzeugen try sl.LoadFromFile(DateiName); //Datei in Stringliste laden AssignFile(F, OpenDialog1.FileName); Reset(F); Readln(F, S); Edit1.Text := S; finally sl.free; //Objekt wieder freigeben end; |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Hi Leon,
Du liest ja nur die erste Zeile in ein Editfeld ein. Und dann noch mal die ganze Datei in die Stringliste. Die soll aber dem komfortablen "Zerpflücken" der einzelnen Zeilöen dienen. Warum hast Du das Beispiel nicht übernommen? |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Delphi-Quellcode:
var
sl: TStringList; zeilennr: integer; DateiName, S: String; F: TextFile; begin OpenDialog1.Execute; // Das Ergebnis steht in FileName // ShowMessage(OpenDialog1.FileName); DateiName := OpenDialog1.FileName; //Der Pfad wird in die Datei gestellt // ShowMessage(DateiName); sl:=TStringList.Create; //Objekt erzeugen sl.Delimiter := ';'; try //sl.LoadFromFile(DateiName); //Datei in Stringliste laden AssignFile(F, OpenDialog1.FileName); Reset(F); Readln(F, S); //Erste Zeile laden sl.DelimitedText := s; //Zeile der StringListe zuweisen, nun kann man mit der Eigenschaft Count die Anzal der Spalten auslesen, die Spaltenname sthen dann in der Stringliste //sl.Strings[0] enthält Namen erste Spalte usw. While not Eof(F) do //Daten laden begin Readln(F, S); Edit1.Text := S; sl.DelimitedText := s; // Datenzeile wird in Stringliste geschrieben -< Auslesen wie Kopfspalte end; finally sl.free; //Objekt wieder freigeben end; |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
@Union:
weil ich deinen thread erst gelesen habe nachdem ich geantwortet hatte. ;o) zumindest läuft es erst mal ohne fehlermeldung, wobei ich deine zeilen mit der datenbank noch ausgemarkert habe. ich muss das ergebnis vorerst mal visuell überwachen. damit ich verstehe was das prog macht. wie kann ich also die informationen sichtbar machen? also zum beispiel: wie viele spalten? wie heißen diese Spalten? wie heißen die restlichen Inhalte? das ist für mich wichtig, weil ich die sichtbaren ergebnisse besser verstehen kann. wenn das geschafft ist, kann ich mich auch im geiste damit auseinander setzen. danke für eure geduld. ich bemühe mich... |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Hallo Leon,
Die Zeilen kannst Du Dir am simpelsten visualisieren, indem Die Zwischenergebnisse in ein Memo schiebst:
Delphi-Quellcode:
Das müsstest Du dann anstelle des Append einsetzen. So werden Dir die Feldinhalte im Memo dann zeilenweise angezeigt.
Memo1.Lines.Clear;
Memo1.Lines.AddStrings(SL); |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
aha okay. nun habe ich auch diese blöde problem mit den leerzeichen...
ist es okay, dass er mir jedes feld in eine neue zeile schreibt oder hab ich was falsch gemacht? die logik sagt mir das ist richtig. |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Das ist so gewollt. Die Stringliste zerlegt Dir aj durch Angabe des Delimiters die Zeile in die einzelnen Felder/Inhalte. Du kannst dann die Stringliste durchlaufen und Dir die Inhalte rausholen. Das Memo als Vorschlag hatte ich gerade deswegen gemachtm damit man die Felder besser sehen kann. Denn wenn die alle wieder in einer Zeile stehen, hast Du ja keine Überpfrüfungsmöglichkeit.
|
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Okay,
aber wie löse ich nun mein Leerzeichenproblem? Da ja in den Codeschnipseln leider selten Dokus dabei sind, ist das recht schwierig... Die csv die ich einlese ist ein Straßenverzeichnis. Toller Weise haben schon die Spaltennamen Leerzeichen. und Straßennamen ja auch ab und an. Wie zum Beispiel Kurfürsten Damm... |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Villeicht vor dem zuweisen die Leerzeiceh und seltene Zeichen ersetzen. Später zurücksetzen.
|
Re: CSV --> Stringlist --> Stringlist zerlegen -->
ja danke. das kann ich probieren. dazu verwende ich if then oder? oder gibt es einen replace-befehl? ich probiere das mal...
noch eine frage. das mit dem count habe ich nicht verstanden. was muss ich genau eigenben? sl.count....? und wie bekomme ich das dann visualisiert? und wie nutze ich das dann für den befehl sl.Strings[0] wobei 0 dann ja durch eine variable ersetzt werden muss. |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Besser ist es die Funktion StringReplace zu verwenden, die ersetzt alle Vorkommen auf einen Streich.
|
Re: CSV --> Stringlist --> Stringlist zerlegen -->
jo hat geklappt. ;o)
ich muss nun versuchen - und das ist mein problem warum ich das mit der stringlist kapieren muss - den inhalt der ersten spalte in eine db-tabelle zu schreiben, davor aber prüfen ob der wert schon einmal darin steht. wenn ja dann in der zweiten tabelle einen entsprechend anderen wert einschreiben. dafür ist mir wichtig zu erkennen, wie das prog weiß, dass die erste spalte z.b. PLZ ist ohne dass ich ihm sage: pass auf, du hast 7 spalten und die erste ist plz... ??? der aufbau der csv ist schon komisch genug: PLZ;Straße;v Hnr;v Hunr;b Hnr;b Hunr;G/U;Tour aber die DB-Struktur ist wirklich klasse... ;o) ich muss versuchen die Infos der csv in 4 tabellen zu bekommen. tab 1: PLZ-ID PLZ Tab 2: Str-ID StrName Tab 3: TourID Tour Tab 4: PLZ Straße vonHausnr vonHausnr-zusatz bisHausnr bisHausnr-zusatz GU Tour In Tab 4 werden für PLZ, Tour und Straße nur IndexNummern gesetzt. Beispiel: 2 versch. PLZ. alle in Tab 1. PLZ1 -> Index1 PLZ2 -> Index2 Das selbe analog für Tour und Straße In Tab 4 sieht eine zeile dann so aus: PLZIndex1, StrIndex2,25,a,100,c, ,TourIndex2 um das umzusetzen muss ich verstehen was genau wie angesteuert werden kann. War das verständlich? kannst du damit was anfangen? |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Also die PLZ(Klartext) befindet sich in SL.Strings[0], die Straße(Klartext) in SL.Strings[1] usw. Ich würde an deiner Stelle parametrisierte Abfragen für die Auflösen der Klartexte in IDs schreiben.
|
Re: CSV --> Stringlist --> Stringlist zerlegen -->
aha, ich weiß nicht ob du meinen ersten eintrag gelesen hast. ;o)
ich bin newbie - zugegeben mit einem gewaltigem projekt - aber wenn du mir das etwas bunter erklären könntest würde ich sicher das verstehen, was du mir in deinem einen satz versucht hast zu sagen. |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Ich gehe mal davon aus, dass das Füllen der Tabellen nicht im Mehrbenutzerbetrieb stattfindet. Unter dieser Randbedingung würde ich die drei Lookup-Tabellen in jeweils einer sortierten StringList komplett zwischenspeichern.
Delphi-Quellcode:
marabu
var
slPlz: TStringList; begin slPlz := TStringList.Create; with slPlz do begin Sorted := true; Duplicates := dupIgnore; end; slPlz.Values['74072'] := '1'; slPlz.Values['60325'] := '2'; ShowMessage(slPlz.Values['74072']); end; |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Zitat:
Aus der CSV-datei erhälst du die Klartexte, damit meine ich z.b. sie Straße, und nicht die ID, welche du in die zuerstellende Tabelle einfügen willst. Deshalb mußt du ja eine Abfrage mache, welche dir die dazugehörige ID liefert. Am besten macht man das mit einer parametrisierten Abfrage. Dies ist eine Abfrage welche einen/mehrere Parameter enthält, welche(n) Wert(e) man später leicht verändern kann ohen die Abfrage neu formullieren zu müssen.
SQL-Code:
Den Paramter PLZ ( Im Querystring durch das vorangestellte : gesetzt) kannst su in der Schleife dann mit verändern.
z.B. SELECT PLZ_ID from Tab1 where PLZ = :PLZ;
Delphi-Quellcode:
Oder Lösung von marabu verwenden
AdoQuery.Parameters.ParamByName('PLZ').Value := 'Hauptstraße';
|
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Nein ich hatte vor gut einem jahr angefangen und war schon recht weit mit db-proggen. dann der cut und alles ist weg. ich sitze hier in meinem homeoffice umgeben von massen papier aus denen ich mir schnipsel heraussuchen muss oder darf - wie man es nimmt. ich kann programmieren - theoretisch. ich bin in der lage paps und struktugramme zu lesen und diese in einer sprache - wenn ich sie denn kann - umsetzen.
das deprimierende an der sache ist, daß ich euch verstehe nur nicht weiß wie ich und wo ich das einsetzen muss. das beispiel von marabu scheint so zu funktionieren. Berichtigt mich bitte wenn ich falsch liege: 1. nachdem ich - wie bisher meine datei in die Stringliste eingelesen habe, sortiere ich sie nach PLZ? oder sortiere ich sie gleich von vorn herein danach? 2. anschließend ignoriere ich die duplicate? 3. und ich übergebe den PLZ eindeutige ID's? was ich an dem schnipsel wieder nicht verstehe ist die klartextausgabe (wenn ich das richtig lese) und wie ich es an meinem code anwende, der im grunde von marabu übernommen wurde...??? mir platzt der schädel. ;o/ |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Zitat:
Du willst also die Tab1,Tab2 usw. auch durch die Werte der CSV-Datei aufbauen. Dann ist es am besten nach dem aktuellen Wert zu suchen (ob in der Datenbank oder einer Stringliste im Speicher ) wenn gefunden diese ID verwenden, sonst neuen Eintrag erzeugen. Zitat:
|
Re: CSV --> Stringlist --> Stringlist zerlegen -->
oki, ich bastel da mal was. mal sehen wie weit mich das bringt. ;o)
also mir ist es gelungen die daten des StringLists in eine tabelle zu schreiben. jedoch muss ich ja 4 anfassen. wenn ich mir das aber zusammenklicke, dann kann ich nur eine tabelle der db pro dbgrid anfassen. wie war es nochmal möglich in einem dbgrid mehrere tabellen zusammen anzuzeigen und diese dann zu bestücken oder im hintergrund diese gesondert anzusprechen? Mein Hintergrund: ich muss ja die DB ansprechen. das funzt. aber ich muss doch bitte nicht für jede tabelle eine neue ADOTable machen! Ich muss ja mit einem SQL-Statement in 4 verschiedene Tabellen schreiben... |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Ich würde nicht mit ADOTable sondern für jede Tabelle ein ADOQuery für das SELECT und eine für den INSERT erstellen, oder wenn natürlich Stringlisten verwenden.
Ich würde nicht über ein Grid auf die Daten zugreifen, sondern direkt auf die DataSet-Kompoenente (ADOTable,ADOQuery usw). Wenn du nicht weiterkommst kannst du ja mal deine Projekt hier einstellen. |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Delphi-Quellcode:
for i := 0 to SL.Count-1 do // ?
ADOQuery1. // ADOTable1.Fields[I].AsString := SL.Strings[i]; //? // ADOTable1.Post; // ? end; Okay. ich streich gleich die segel... Wie mache ich meinem Script an dieser stelle klar, welche SL.Strings[i] er in welche Tabelle in welches Feld zu schreiben hat? Das schlimme ist ja, ich müsste dann auch noch vergleiche anstellen. |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Poste mal den ganzen Source, ich habe so das Gefühl wir reden aneinander vorbei ;-)
|
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Okay, ist aber noch mächtig baustelle hier. Ich weiß nicht wo ich genau ansetzen soll. Also nicht wundern.
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ActnList, ActnMan, ToolWin, ActnCtrls, ActnMenus, StdCtrls, Grids, DBGrids, DB, ADODB; type TForm1 = class(TForm) ActionMainMenuBar1: TActionMainMenuBar; ActionManager1: TActionManager; StrassenverzNeu: TAction; OpenDialog1: TOpenDialog; Memo2: TMemo; Edit1: TEdit; ADOQuery1: TADOQuery; DataSource1: TDataSource; DBGrid1: TDBGrid; StringGrid1: TStringGrid; procedure StrassenverzNeuExecute(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.StrassenverzNeuExecute(Sender: TObject); var SL: TStringList; SG: TStringGrid; i: Integer; T: Textfile; SInString: String; begin if (OpenDialog1.Execute) then begin SL := TStringList.Create; // Objekt erzeugen try AssignFile(T,OpenDialog1.FileName); // öffnet die Datei Reset(T); Readln(T, SInString); // Erste Zeile laden // kann später gelöscht werden SInString := StringReplace(SInString, // Ersetze ' ' mit '~~' ' ', '~~', [rfReplaceAll, rfIgnoreCase]); SL.Delimiter := ';'; // Festlegung des Trennzeichens SL.DelimitedText := SInString; // Inhalt der Zeile Schreiben SL.Text := StringReplace(Sl.text, // Ersetze '~~' mit ' ' '~~', ' ', [rfReplaceAll, rfIgnoreCase]); Memo2.Lines.Clear; // Löscht das Memo2 Memo2.Text := SL.Text; // Zeigt erste Zeile in Memo2 // bis hier hin while (not Eof(T)) do begin // solange nicht EOF erreicht ReadLn(T,SInString); // lies die nächste Zeile SInString := StringReplace(SInString, // Ersetze ' ' mit '~~' ' ', '~~', [rfReplaceAll, rfIgnoreCase]); SL.Delimiter := ';'; // Festlegung des Trennzeichens SL.DelimitedText := SInString; // Inhalt der Zeile Schreiben SL.Text := StringReplace(Sl.text, // Ersetze '~~' mit ' ' '~~', ' ', [rfReplaceAll, rfIgnoreCase]); // kann später gelöscht werden Memo2.Lines.AddStrings(SL); // Listet die Felder in Memo2 //******* Tabelle ansprechen ********* // ADOTable1.TableName:='StrVerzeichnis'; // ADOTable1.Active:=true; // ADOTable1.Append; // ? // bis hier hin for i := 0 to SL.Count-1 do // ? ADOQuery1.Insert; ADOQuery1.SQL.Text:='INSERT // ADOTable1.Fields[I].AsString := SL.Strings[i]; //? // ADOTable1.Post; // ? end; finally i := SL.Count; ShowMessage(IntToStr(i)); SL.Free; // Objekt schließen end; end; CloseFile(T); // Datei schließen end; procedure TForm1.FormCreate(Sender: TObject); begin end; end. wenn ich nur mit ADOTable arbeite löft es nur werden die daten dann nicht dahin verschoben wo sie sollen, denn es ist ja nur eine Tabelle. Aber mit ADOQuery komm ich gar nicht klar... |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Also wenn du unbedingt alles über eine AdoTable arbeiten willst( wie gesagt parametrisierte Queries wären besser) dann mußt du mit Filtern arbeiten.
Schleife über die Felder entfernen.
Delphi-Quellcode:
oder in der IDE setzten : Erzeugt einen param. Query
ADOQuery1.Sql.Text := 'insert into PLZ, Straße, vonHausnr, vonHausnr_zusatz, bisHausnr, bisHausnr-zusatz, GU, Tour) values( :plz, ;str, ;von, ;von_zu, :bis, :bis_zu, :gu ,tour)';
Delphi-Quellcode:
ADOTable1.TableName:='PlzVerzeichnis';
ADOTable1.Filter='plz='''+ SL.Strings[0]+'''; ADOTable1.Filtered := true; ADOTable1.Open; AdoQuery1.Parameters.ParamByName('plz').value := AdoTable1.FieldByName('plzid').value; ADOTable1.TableName:='StrVerzeichnis'; ADOTable1.Filter='strasse='''+ SL.Strings[1]+'''; ADOTable1.Filtered := true; ADOTable1.Open; AdoQuery1.Parameters.ParamByName('str').value := := AdoTable1.FieldByName('plzid').value; //usw. für weitere Felder AdoQuery1.ExecSql; |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Hallo Leon,
vielleicht habe ich es überlesen, aber wie oft und zu welchen Gelegenheiten wird dieses Programm laufen? Wieviele Sätze stehen in der Eingabedatei? Greifen mehrere Benutzer gleichzeitig auf die Daten zu? marabu |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
NEIN NEIN! ;o)
Ich will ja mit Query's arbeiten! In deinem Beispiel (oberen) sprichst du von ADOTable1. und fügst alle felder auch nur dieser tabel zu. ich muss mehrere anfassen, den in tabelle 1 kommt nur die PLZ rein, in die tabelle 2 nur der strassenname usw. kann ich das entsprechend angleichen? ich denke doch..., oder? @Marabu: Immer dann wenn das Programm in einer neuen Filiale installiert wird. das kann für jahre nur einmal sein. es kann aber auch sehr oft im jahr vorkommen. das Problem ist einfach, dass ich ein prog brauche, das diese CSV-Datei eigenhändig konvertiert und jeder Sekräterin es ermöglicht selbst damit zu arbeiten. das ist nur das kleinste stück des programms. aber für den start das wichtigste! |
Re: CSV --> Stringlist --> Stringlist zerlegen -->
Mit Queries würde es dann so aussehen:
Vorbelegen der Queries am Beispiel von getPlz:
Delphi-Quellcode:
Weiter unten in der Schleife über die Zeilen dann
getPlz.Sql.Text := 'select plzid from plzVerzeichnis where plz= :plz';
getPlz.Prepared := True;
Delphi-Quellcode:
getPlz.Parameters.ParamByName('plz').Value := SL.Strings[0];
getPlz.Reopen; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:43 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz