Entwickler-Ecke
Dateizugriff - mehrere StringGrids in Textdatei speichern und öffnen
addlehead - Do 02.03.06 20:24
Titel: mehrere StringGrids in Textdatei speichern und öffnen
Hallo Leute!
hier sind meine Typen, die dazu dienen meine daten, die ich aus 3 stringgrids auslese, speichere:
Delphi-Quelltext
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:
| unit Unit2; interface type t_rechnung=record Datum:string[10]; Typ:string[15]; Betrag:integer; Zahlungsweise:string[15]; end;
t_feld2004 =array[0..1000] of t_rechnung; t_feld2005 =array[0..1000] of t_rechnung; t_feld2006 =array[0..1000] of t_rechnung; t_datei= file of t_rechnung; t_datname=string; var v_rechnung2004:t_feld2004; v_rechnung2005:t_feld2005; v_rechnung2006:t_feld2006; v_dat:t_datei; v_dateiname:t_datname;
implementation
end. |
...in v_rechnung2004,v_rechnung2005,v_rechnung2006 schreibe ich im folgenden Code die Daten der entsprechenden StringGrids...
Delphi-Quelltext
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:
| procedure TForm1.Speichern1Click(Sender: TObject); var rechnung2004,rechnung2005,rechnung2006: t_rechnung; i,j: integer; begin for i:=1 to (stringgrid1.RowCount-1) do begin v_rechnung2004[i].Datum:=stringgrid1.Cells[1,i]; v_rechnung2004[i].Typ:=stringgrid1.Cells[2,i]; v_rechnung2004[i].Zahlungsweise:=stringgrid1.Cells[4,i]; v_rechnung2005[i].Datum:=stringgrid2.Cells[1,i]; v_rechnung2005[i].Typ:=stringgrid2.Cells[2,i]; v_rechnung2005[i].Zahlungsweise:=stringgrid2.Cells[4,i]; v_rechnung2006[i].Datum:=stringgrid3.Cells[1,i]; v_rechnung2006[i].Typ:=stringgrid3.Cells[2,i]; v_rechnung2006[i].Zahlungsweise:=stringgrid3.Cells[4,i]; end; if savedialog1.execute then begin assignfile(v_dat,savedialog1.Filename); rewrite(v_dat); for j:=1 to (Stringgrid1.RowCount) do begin rechnung2004:=v_rechnung2004[j]; rechnung2005:=v_rechnung2005[j]; rechnung2006:=v_rechnung2006[j]; write(v_dat,rechnung2004); write(v_dat,rechnung2005); write(v_dat,rechnung2006); end; closefile(v_dat); end; end; |
...Allerdings erscheint beim Öffnen mit dem folgenden Quelltext die Fehlermeldung "Versuch hinter dem Dateiende zu lesen"! Woran mag das liegen?...
Delphi-Quelltext
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:
| procedure TForm1.Oeffnen2Click(Sender: TObject); var rechnung2004,rechnung2005,rechnung2006: t_rechnung; i,j:integer;
begin if opendialog1.execute then begin assignfile(v_dat,opendialog1.Filename); reset(v_dat);
stringgrid1.RowCount:=filesize(v_dat);
for i:=1 to stringgrid1.RowCount do begin read(v_dat,rechnung2004); read(v_dat,rechnung2005); read(v_dat,rechnung2006); v_rechnung2004[i]:=rechnung2004; v_rechnung2005[i]:=rechnung2005; v_rechnung2006[i]:=rechnung2006; end; closefile(v_dat); end; for j:=1 to stringgrid1.RowCount do begin stringgrid1.cells[1,j]:=v_rechnung2004[j].Datum; stringgrid1.cells[2,j]:=v_rechnung2004[j].Typ; stringgrid1.cells[4,j]:=v_rechnung2004[j].Zahlungsweise; stringgrid2.cells[1,j]:=v_rechnung2005[j].Datum; stringgrid2.cells[2,j]:=v_rechnung2005[j].Typ; stringgrid2.cells[4,j]:=v_rechnung2005[j].Zahlungsweise; stringgrid3.cells[1,j]:=v_rechnung2006[j].Datum; stringgrid3.cells[2,j]:=v_rechnung2006[j].Typ; stringgrid3.cells[4,j]:=v_rechnung2006[j].Zahlungsweise; end; end |
Ich bitte euch ujm Hilfe. Ich möchte nicht noch einaml die ganze Nacht durchsitzen und rätseln:) Jetzt seid ihr gefragt mit neuen Ideen:)
Moderiert von
Christian S.: I- durch Delphi-Tags ersetztModeriert von
raziel: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Do 02.03.2006 um 21:03
Sinspin - Do 02.03.06 20:42
bitte mach als erstes mal aus dem einfach text delphi quelltext. dann kann ich das ganze besser lesen. das geht in dem du
unter "bereiche" oberhalb des textfeldes delphi wählst, den cursor vor deinen quelltext stellst, und "+" clickst, dann gehts du hinter deinen quelltext und clickst wieder "+".
dann fällt mir auf das du hinter rewrite und reset als zweiten parameter immer "1" angeben musst! die record größe sollte immer angegeben werden. das führt häufig zu problemen das das in pascal/delphi so dumm gelößt ist.
Sinspin - Do 02.03.06 20:56
fein!
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| if opendialog1.execute then begin assignfile(v_dat,opendialog1.Filename); reset(v_dat);
stringgrid1.RowCount:=filesize(v_dat);
for i:=1 to stringgrid1.RowCount do begin read(v_dat,rechnung2004); read(v_dat,rechnung2005); read(v_dat,rechnung2006); v_rechnung2004[i]:=rechnung2004; v_rechnung2005[i]:=rechnung2005; v_rechnung2006[i]:=rechnung2006; end; closefile(v_dat); |
dein fehler ist die zeile:
stringgrid1.RowCount:=filesize(v_dat);
das muss lauten
stringgrid1.RowCount:=filesize(v_dat) div 3;
denn du verteilst deine daten ja auf drei tabellen und nicht auf eine!
es werden ja auch drei einträge für je eine füllung einer zeile von stringgrid1, stringgrid2, stringgrid3 verwendet.
wo setzt du eigentlich die größen der anderen beiden (stringgrid2, stringgrid3)?
addlehead - Fr 03.03.06 04:12
Ich habe bis jetzt geknobelt! Wie kann ich für jedes StringGrid 1-3 die Eigenschaft "rowcount" speichern und diese abrufen beim Öffnen, sodass mein StringGrid beim Öffnen so viel Zeilen bereit stellt, wie Daten vorhanden sind? Mit filesize kann ich das ja wohl schlecht machen, oder? Muss ich den Wert von "rowcount" evtl. in meinen arrays speichern und dann auslesen?
Nochmal: Mein Ziel ist es, in einer Datei die Werte von 3 StringGrids eines Formulars zu speichern und diese Werte genau so auszulesen, wie sie gespeichert sind.
Mein Quelltext hat sich verändert. Ich wollte aber nicht gleich alles reinhauen, um nicht alles zuzumüllen hier...Ich kann nur sagen, dass sich an dem Problem noch nichts effektives geändert hat.
Das Hauptproblem liegt sicherlich beim Öffnen. Ich weis nicht, wie ich jedem StringGrid seine alten Daten zuweisen kann!
Logikmensch - Fr 03.03.06 11:10
Hallo,
zum Speichern von beliebig vielen Stringgrids in nur eine Datei kannst Du auch folgende Routinen verwenden:
Delphi-Quelltext
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: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65:
| function WriteStringGridToFileStream(grid:TStringGrid; var f:TFileStream):boolean; var xsize,ysize,x,y,len:integer; s:string; begin result:=false; ysize:=grid.RowCount; xsize:=grid.ColCount; if (f.Write(ysize,sizeof(ysize))=sizeof(ysize)) and (f.Write(xsize,sizeof(xsize))=sizeof(xsize)) then begin for y:=0 to grid.RowCount-1 do for x:=0 to grid.ColCount-1 do begin s:=grid.cells[x,y]; len:=length(s); if (f.write(len,sizeof(len))<>sizeof(len)) or (f.Write(s[1],length(s))<>length(s)) then break; end; result:=true; end; end;
function ReadStringGridFromFileStream(grid:TStringGrid; var f:TFileStream):boolean; var xsize,ysize,x,y,len:integer; s:string; begin result:=false; if (f.Read(ysize,sizeof(ysize))=sizeof(ysize)) and (f.Read(xsize,sizeof(xsize))=sizeof(xsize)) then begin grid.RowCount:=ysize; grid.ColCount:=xsize; for y:=0 to grid.RowCount-1 do for x:=0 to grid.ColCount-1 do begin if f.Read(len,sizeof(len))=sizeof(len) then begin setlength(s,len); if f.Read(s[1],len)=len then grid.Cells[x,y]:=s else exit; end else exit; end; result:=true; end; end;
procedure TForm1.WriteStringGridsToFile(const fname:string); var fs:TFileStream; begin fs:=TFileStream.Create(fname,fmCreate); if writestringgridtofilestream(StringGrid1,fs) then showmessage('ok') else showmessage('Schreibfehler!'); fs.Free; end;
procedure TForm1.ReadStringGridsFromFile(const fname:string); var fs:TFileStream; begin fs:=TFileStream.Create(fname,fmOpenRead); fs.Position:=0; if readstringgridfromfilestream(StringGrid1,fs) then showmessage('ok') else showmessage('Lesefehler!'); fs.Free; end; |
Viel Erfolg!
damadmax - Fr 03.03.06 12:48
ich habe es so gelöst...
TStringGrid um folgende funktionen erweitert:
Delphi-Quelltext
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:
| procedure TmyStringGrid.LoadCSV(aFilename: String); var f : TStrings; idx : Integer; begin if fileexists(aFilename) then begin f := TStringList.Create; try f.LoadFromFile(aFilename); RowCount := f.Count; if RowCount > 0 then with TStringList.Create do begin CommaText := f[0]; ColCount := Count; end; for idx := 0 to RowCount - 1 do begin Rows[idx].CommaText := f[idx]; end; finally f.Free; end; end; end;
procedure TmyStringGrid.SaveCSV(aFilename: String); var f : TStrings; idx : integer; begin f := TStringList.Create; try for idx := 0 to RowCount - 1 do begin f.Add(Rows[idx].CommaText); end; f.SaveToFile(aFilename); finally f.Free; end; end; |
addlehead - Fr 03.03.06 18:29
Danke für eure Hilfe. Ich habe mal Code aus einem alten Thread kopiert. Den habe ich implementiert und es funktioniert auch. Allerdings kann ich nur ein StringGrid speichern. Kann mir jemand verraten anhand des unten stehenden codes, wie ich damit mehrere StringGrids speichern/öffnen kann? Das habe ich bei euren 2 obigen Varianten schon nicht gerafft:(
Würde ich 3 mal die SpeichernFunktion ausführen, dann überschreibt er ja das vorige und kann somit nur die daten des dritten stringgrids auch wieder öffnen.
Delphi-Quelltext
1: 2: 3:
| gridspeichern(StringGrid1,'c:\test.txt'); gridspeichern(StringGrid2,'c:\test.txt'); gridspeichern(StringGrid3,'c:\test.txt'); |
Delphi-Quelltext
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: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70:
| procedure gridspeichern(grd:TStringGrid;Datei:string); var sl:TStringlist; x,y:integer; begin sl:=TStringlist.create; sl.add(inttostr(grd.colcount)); sl.add(inttostr(grd.rowcount)); for x:=0 to grd.ColCount-1 do for y:=0 to grd.RowCount-1 do sl.add(grd.cells[x,y]); for x:=0 to grd.ColCount-1 do sl.add(inttostr(grd.ColWidths[x])); for x:=0 to grd.RowCount-1 do sl.add(inttostr(grd.RowHeights[x])); sl.add(inttostr(grd.clientwidth)); sl.add(inttostr(grd.clientheight)); sl.add(inttostr(ord(grd.ScrollBars))); sl.savetofile(datei); sl.free; end; procedure gridladen(grd:TStringGrid;Datei:string;angleichen:boolean); var sl:TStringlist; x,y,z:integer; begin sl:=TStringlist.create; sl.loadfromfile(datei); grd.colcount:=strtoint(sl.strings[0]); grd.rowcount:=strtoint(sl.strings[1]); z:=2; for x:=0 to grd.ColCount-1 do for y:=0 to grd.RowCount-1 do begin grd.cells[x,y]:=sl.strings[z]; inc(z); end; if angleichen then begin for x:=0 to grd.ColCount-1 do begin grd.ColWidths[x]:=strtoint(sl.strings[z]); inc(z); end; for x:=0 to grd.RowCount-1 do begin grd.RowHeights[x]:=strtoint(sl.strings[z]); inc(z); end; grd.clientwidth:=strtoint(sl.strings[z]); grd.clientheight:=strtoint(sl.strings[z+1]); grd.ScrollBars:=TScrollStyle(strtoint(sl.strings[z+2])); end; sl.free; end;
procedure TForm1.Button1Click(Sender: TObject); begin gridspeichern(StringGrid1,'c:\test.grd'); end; procedure TForm1.Button2Click(Sender: TObject); begin gridladen(StringGrid1,'d:\test2.grd',true); end; |
damadmax - So 05.03.06 19:00
der einfachheit wegen würd ich drei dateien nehmen...
oder du schreibst die stringgrids abschnittsweise rein und stellst jedem einen eindeutigen string z.b. '[STRINGGRID1]' voran der angibt woher der folgende abschnitt stammt
Logikmensch - Do 09.03.06 10:51
Hallo addlehead!
meine Variante ist (ohne jetzt die anderen Vorschläge abwerten zu wollen), in der Lage, mehrere StringGrids in eine Datei zu packen. Vielleicht wäre es nicht unklug, so manche Beiträge auch mal zu lesen. ;-)
Beispiel:
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 TForm1.WriteStringGridsToFile(const fname:string); var fs:TFileStream; begin fs:=TFileStream.Create(fname,fmCreate); if writestringgridtofilestream(StringGrid1,fs) and writestringgridtofilestream(StringGrid2,fs) then showmessage('ok') else showmessage('Schreibfehler!'); fs.Free; end; procedure TForm1.ReadStringGridsFromFile(const fname:string); var fs:TFileStream; begin fs:=TFileStream.Create(fname,fmOpenRead); fs.Position:=0; if readstringgridfromfilestream(StringGrid1,fs) and readstringgridfromfilestream(StringGrid2,fs) then showmessage('ok') else showmessage('Lesefehler!'); fs.Free; end; |
Liebe Grüße,
Claus.
damadmax - Do 09.03.06 23:45
Zitat: |
Vielleicht wäre es nicht unklug, so manche Beiträge auch mal zu lesen. |
Lesen? Wer kann lesen? Ich nicht! :) :) :)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!