Entwickler-Ecke

Dateizugriff - Daten aus 2 Dateien verbinden


Jocke - Fr 12.09.08 11:17
Titel: Daten aus 2 Dateien verbinden
Guten Morgen,

ich bräuchte mal Unterstützung.

Ich habe 2 csv Dateien, die ich verbinden möchte.
Die erste Datei folgende Daten :

Fremdnummer,Auftragnummer, ......
100000,20000,......
100001,20097,......
100002,20010,......
usw.

Die 2.Datei ist nun über die Fremdnummer verknüpf, wobei es allerdings zu jeder Fremdnummer 3 Datensätze gibt.

Fremdnummer,Art,Betrag,.....
100000,RG,100,....
100000,GS,50,.....
100000,DIFF,50,...
100001,RG,200,....
100002,GS,90,.....
100003,DIFF,110,...
usw.

Als Ergebnis möchte ich nun eine Tabelle haben (z.B. Stringgrid), die wie folgt aussieht :

Quelltext
1:
2:
3:
4:
Auftragnummer BetragRG BetragGS  BetragDiff
20000           100      50       50
20097           200      90       110
....


Ich habe als erstes die 1.Datei in ein Stringgrid eingelesen. Danach habe ich 2 verschachtelten Schleifen die 2.Datei verknüpft, wobei die äussere Schleife die Datensätze der 2.Datei nacheinander durchgeht und die innere Schleife jeden einzelnen Datensatz mit allen Einträgen im Stringgrid vergleicht.

Das ganze funktioniert im Prinzip, ist allerdings nicht praktikabel, wenn die Dateien sehr grosse Datenmengen enthalten. Hat die 1.Datei 10000 Datensätze und die 2.Datei 30000, dann wird die äussere Schleife 30000 mal durchlaufen und bei jedem Durchlauf wird die innere Schleife dann x-mal durchlaufen, bis der dazugehörige Eintrag im Stringgrid gefunden wurde.

D.h. ich muss die Sache irgendwie anders anpacken.
Vielleicht kann mir hier jemand einen Denkanstoß geben.

Vielen Dank.


Narses - Fr 12.09.08 11:30

Moin!

user profile iconJocke hat folgendes geschrieben:
Vielleicht kann mir hier jemand einen Denkanstoß geben.
Ein TStringGrid ist eine Anzeige, kein Datenlager... :roll: ;)

Lies die Daten in interne Datenstrukturen oder eine Datenbank ein und gib nur das Ergebnis aus. :idea:

cu
Narses


Jocke - Fr 12.09.08 11:35

Hallo Narses,
kannst du mir zu
user profile iconNarses hat folgendes geschrieben:
Lies die Daten in interne Datenstrukturen

mal ein Stichwort geben ?


Narses - Fr 12.09.08 12:55

Moin!

Schau mal, ob du mit Suche in: Delphi-Forum, Delphi-Library CSV DATEI LADEN weiter kommst. :lupe: :les: Wenn nicht, schauen wir hier weiter. ;)

cu
Narses


Jocke - Fr 12.09.08 13:59

Hallo Narses,

erst mal vielen Dank für deine Antwort.

Also das eigentliche Einlesen der CSV-Datei macht keine Probleme, dass läuft schon.
Deinen Hinweis, dass ein Stringgrid kein Datenspeicher ist, werde ich in Zukunft auf jeden Fall beherzigen, dass war mir bisher nicht so klar.
Ich könnte ja hier ein Array oder Record nehmen, dass ist kein Problem.

Die eigentliche Problemstellung für mich ist hier nur, wie ich, wenn ich einen Datensatz aus der 2. Datei habe, am schnellsten den Index des passenden Datensatzes aus dem Array herausfinde.

also :

array[1]=100000
array[2]=100001
array[3]=100002
array[4]=100003
....
array[10000]=1xxxxx


Nun habe ich in der 2.Datei die 100002. Wie komme ich nun am schnellsten zu dem Index 3 ?

Meine Überlegung, hier mit einer Schleife alle Datensätze zu durchsuchen, ist ja nicht effektiv.
Mittlerweile bin ich auch auf die binäre Suche gekommen, die ja schon wesentlich effektiver sein würde.
Aber letztendlich müsste auch hier das array bei jedem Datensatz der 2.Datei durchsucht werden.

Geht das nicht anders ?

Ich habe mal folgende Idee:
Beim Einlesen der ersten Datei schreibe ich die Fremdnummer, über die ja verknüpft wird, als eigene Section in ein INI-Datei

Quelltext
1:
ini.WriteString('100000','Index','1');                    

Wenn ich nun in der 2. Datei auf einen Datensatz mit 100000 treffe, finde ich den Index mit

Quelltext
1:
ini.readString('100000','Index','0');                    

sofort heraus, ohne dass Array durchsuchen zu müssen.
Oder ist das totaler Quatsch und man kommt um eine Suche im Array nicht herum ?


Boldar - Fr 12.09.08 14:13

Das mit der ini ist noch langsamer. Nimm doch einfach Tstringlist, in die Strings kopierst du den Text und bei Object die Fremdnummer. Tstringlist bietet schon Methoden zum Sortieren!


Xion - Fr 12.09.08 14:27

Hi, so kannst dus schnell auslesen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
procedure LoadCSV(FileName: String; Divisor: Char); //Divisor=,
var CSV: TextFile; S: String; Part: String;
begin
  AssignFile(CSV,FileName);
  Reset(CSV);
  
  while not EoF(CSV) do //EoF=End of File
    begin
      ReadLn(CSV,S);



      while Pos(Divisor,S)>0  do
        begin 
          Part:=Copy(S,1,Pos(Divisor,S)-1); //bis zum , abschneiden
          S:=Copy(S,Pos(Divisor,S)+1,Length(S));  //reststring=ab dem ,
        end;
      Part:=S; //falls in deiner CSV das letzte Zeichen kein , ist
    end;

  CloseFile(CSV);
end;


Part kannst du dann in ein array of array of String schreiben, das hab ich der übersichtlichkeit wegen weggelassen

Wenn du dann 2 von diesen Arrays hast (2 Dateien):

Delphi-Quelltext
1:
2:
3:
4:
for F1:= 0 to High(Arr1[0]) do
  for F2:= 0 to High(Arr2[0]) do
     if (Arr1[0,F1]=Arr2[0,F2] then
        {Feld1 von Datei 1 = Feld1 von Datei 2. Jetzt einfach eine neue Row in einem StringGrid nehmen und die beiden Array-Spalten eintragen => Fertig}


jaenicke - Fr 12.09.08 14:55

Ein ähnliches Problem (was CSVs angeht) gabs vor Kurzem [http://www.delphi-forum.de/viewtopic.php?p=521844#521844], dort wurde auf diese Klasse verwiesen, die dein Problem vereinfachen dürfte:
http://www.delphipraxis.net/topic130402_csvreader+schnelles+lesen+von+csvdateien.html