![]() |
Re: StringGrid Zeile per Mausclick auslesen
Probiers gleich mal aus.
Wäre prima, wenn du mir die Syntax für RenameFile verraten könntest. Sag schon mal Danke :) |
Re: StringGrid Zeile per Mausclick auslesen
Delphi-Quellcode:
Einfach "RenameFile" eintippen, Caret drauf setzen und F1 drücken, dann zeigt die Hilfe (meist) was du wissen möchtest.
function RenameFile(const OldName,NewName:String):Boolean;
|
Re: StringGrid Zeile per Mausclick auslesen
Bin wie gesagt ein absoluter Newbie (bis vor `nem halben Jahr lag Delphi in Griechenland) und auch nicht mehr der Jüngste. Mache das Ganze Nebenbei. Deshalb bleibts nicht aus, dass ich mich dusselig anstelle. Bin auf folg. Probleme gestoßen:
-habe Dateiname folgendermaßen deklariert
Delphi-Quellcode:
Dann müsste
Dateiname:=Opendialog1.FileName;
If Dateiname<>'' then begin AssignFile(ChemDat,Dateiname+'.dat'); rewrite(chemdat); end;
Delphi-Quellcode:
korrekt sein
DeleteFile(Dateiname+'.dat');
-Hilfsdatei wurde über
Delphi-Quellcode:
erstellt
Assignfile(ChemDatH,'Hilf');
Ergo müsste
Delphi-Quellcode:
die Umbenennung erledigen
RenameFile('Hilf',Dateiname+'.dat');
-vor dem Delete hab ich beide Dateien per CloseFile geschlossen -Nun noch
Delphi-Quellcode:
Und es sollte gehen. Tuts aber leider nicht.
AssignFile(ChemDat,Dateiname+'.dat');
edit: Merke gerade: Kann ja gar nicht gehen. Woher soll er den neuen Namen kennen? Oder liege ich da falsch? |
Re: StringGrid Zeile per Mausclick auslesen
Tja, das könnte an (unterschiedlichen) Pfadangaben liegen. TOpenDialog gibt einen Dateiname inklusive eines Pfades zurück. Diese Information verwendest du für "Dateiname". Den Namen der Hilfsdatei erstellst du direkt im Programmcode - aber ohne eine Pfadangabe. Dadurch wird die Hilfsdatei im gerade aktuellen Verzeichnis angelegt. In diesem Verzeichnis wird die Hilfsdatei dann auch umbenannt. Das könnte das gleiche Verzeichnis sein, wird's aber wohl nicht. Die erneute Verwendung von "Dateiname" greift dann ins Leere, da sich die umbenannte (ehemalige) Hilfsdatei ganz woanders befindet.
So, das ist jetzt natürlich Spekulation. Um besser Helfen zu können, musst du konkreter berichten, was nicht funktioniert. |
Re: StringGrid Zeile per Mausclick auslesen
Die Hilf-Datei liegt im selben Pfad wie die eigentliche Datei. Ich poste hier nochmal die komplette Prozedur. Vermutlich hab ich einen Syntaxfehler gemacht, den der Debugger nicht zeigt.
Delphi-Quellcode:
Das Programm wird in einem anderen Verzeichnis gestartet. Die Dateien werden z.Zt. direkt auf Laufwerk D abgelegt. Dort finde ich sowohl die angelegte Datei als auch die Hilf-Datei.
procedure TForm1.DatenLoeschenClick(Sender: TObject);
var i:SmallInt; begin seek(ChemDat,0); Assignfile(ChemDatH,'Hilf'); rewrite(ChemDatH); for i:=0 to Stelle-1 do begin read(ChemDat,Chem) ; write(ChemDatH,Chem); end; seek(ChemDat,Stelle+1); while not eof (Chemdat) do begin read(ChemDat,Chem); write(ChemDatH,Chem); end; // bis hierhin klappts CloseFile(ChemDat) ; CloseFile(ChemDatH) ; DeleteFile(Dateiname+'.dat'); RenameFile('Hilf',Dateiname+'.dat'); AssignFile(ChemDat,Dateiname+'.dat'); end; Allerdings muss ich mich jetzt verabschieden. Mein Kind braucht einen Chauffeur. Werd mal drüber schlafen. Melde mich morgen wieder. Vielen Dank für deine bisherige Hilfe. |
Re: StringGrid Zeile per Mausclick auslesen
Zitat:
Anmerkung: Du arbeitest offenbar gern mit globalen Variablen, z.B. Chem, ChemDat, ChemDatH - ist vielleicht am Anfang recht bequem. Man sollte es aber tunlichst vermeiden (und sich gar nicht erst angewöhnen)! Wird das Programm umfangreicher sind das die "besten" Fehlerquellen. Auch gehört zum "rewrite()" eine Fehlerbehandlung, schau' mal in die DelphiHilfe unter dem Stichwort "IOResult". |
Re: StringGrid Zeile per Mausclick auslesen
@taaktaak
Sorry, hat ein bisschen länger gedauert. Dein Hinweis zur Globalisierung hat insofern geholfen, dass ich einen anderen Fehler beseitigen konnte. Da du den Quelltext für Fehlerfrei erachtet hast, bin ich nochmal alles durchgegangen und siehe da, der Fehler lag woanders. Beim Löschen schließe ich die Datei. Der nachfolgende Aufruf im Programm erwartet aber eine geöffnete Datei. Da ich Probleme mit dem Umbenennen hatte bin ich wieder zur ursprünglichen Variante zurückgekehrt. Funktioniert theoretisch. Folgendes Problem: -Reihenfolge der eingegebenen Datensätze: zeile1 / zeile2 / losch/ zeile3 / zeile4 -nach Aufruf der Löschprozedur für Datensatz losch lautet die Reihenfolge: zeile2 / zeile2 / losch/ zeile3 / zeile4 -in der Hilf-Datei steht die Reihenfolge: zeile2 / losch/ zeile3 / zeile4 Schlußfolgerung: In der ChemDat wurde statt des 3.Datensatzes der 1. gelöscht und der 2. Datensatz als 1. eingetragen. Vielleicht kannst du rausfinden wo es da hakt. Hier zunächst die Prozedur für die verwendete Suchfunktion:
Delphi-Quellcode:
Folg. Quellcode soll löschen (Hab mal kommentiert, was ich damit erreichen will):
procedure suchNam(Name:string; var ex:boolean; var Position:SmallInt);
//Chemikaliensuche nach Namen begin seek(ChemDat,0); while not Eof(ChemDat) do begin read(ChemDat,Chem); If Name=Chem.Name then begin ex:=true; Position:=Filepos(ChemDat)-1; end; end; end;
Delphi-Quellcode:
Die Hilfsdatei habe ich nach deinem Tipp lokal definiert. Die ChemDat muss m.E. global bleiben, da viele Prozeduren darauf zugreifen.
procedure TForm1.DatenLoeschenClick(Sender: TObject);
var such:string; exist:boolean; Stelle:SmallInt; i:SmallInt; z,s:Integer; ChemDatH: TChemDat; begin Stelle:=0; seek(ChemDat,0); Assignfile(ChemDatH,'Hilf'); rewrite(ChemDatH); such:=EditName.Text; suchNam(Chem.Name, exist, Stelle); //Aufruf Suchprozedur (s.o.) If exist then for i:=0 to Stelle-1 do begin seek(ChemDat,0); read(ChemDat,Chem) ; //Bis zur gesuchten Stelle (Name aus Edits) write(ChemDatH,Chem); //Bis dahin gelesenes in die Hilfsdatei schreiben end; seek(ChemDat,Stelle+1); // zu löschenden Datensatz überspringen while not eof (Chemdat) do begin read(ChemDat,Chem); //Rest lesen und schreiben write(ChemDatH,Chem); end; seek(ChemDatH,0); read(ChemdatH,Chem); // HilfsDatei auslesen seek(ChemDat,0); write(ChemDat,Chem); //ChemDat neu schreiben CloseFile(ChemDatH); //Erase(ChemDatH); seek(ChemDat,0); for i:=0 to FileSize(ChemDat)-1 do begin StringGrid1.Cells[0,i]:=IntToStr(FilePos(ChemDat)); read(ChemDat,Chem); with Chem do //komplette ChemDat lesen und im StringGrid ausgeben begin StringGrid1.Cells[1,i+1]:=IntToStr(Chem.BNum); StringGrid1.Cells[2,i+1]:=Chem.Name; StringGrid1.Cells[3,i+1]:=IntToStr(Chem.Bestand); StringGrid1.Cells[4,i+1]:=Chem.Datum; end; Gruß Michael |
Re: StringGrid Zeile per Mausclick auslesen
Moin, Moin Michael.
Zur Suchfunktion: Du hast eine Prozedur daraus gemacht. Typischerweise würde das tatsächlich eine Funktion sein, die als Ergebnis die gefundene Position zurückgibt. Wird der Datensatz nicht gefunden, wäre das Ergebnis -1 (da der erste Datensatz die Position 0 hat). Die Lösch-Prozedur ist zumindest an dieser Stelle falsch:
Delphi-Quellcode:
Da in jedem Schleifendurchlauf seek() aufgerufen wird, bewegst du dich nicht durch die Datei, sondern bleibst immer an der ersten Position. Das Auslesen der Hilfsdatei und (Neu)Schreiben von ChemDat ist falsch, da nur der erste Datensatz gelesen und geschrieben wird.
for i:=0 to Stelle-1 do begin
seek(ChemDat,0); read(ChemDat,Chem) ; write(ChemDatH,Chem); end; Vorschlag für neue Variante:
Delphi-Quellcode:
Wesentlicher Unterschied ist vielleicht, das die Prozedur in mehrere "Häppchen" unterteilt ist. Das ist in diesem Fall vielleicht übertrieben, hilft aber immer, den Überblick zu behalten und Fehler zu vermeiden oder schneller eingrenzen zu können. Auch werden die Dateien in jeder Funktion/Prozedur geöffnet und wieder geschlossen. Auch das vermeidet Fehler. Das assignfile() müsste natürlich nicht jedesmal wieder erfolgen, schadet aber auch nicht. Es gibt für den Grad der Unterteilung wohl kein RICHTIG und FALSCH, das muss jeder für sich entscheiden.
procedure TForm1.DatenLoeschenClick(Sender:TObject);
var DelPos : Integer; function NamePos(Name:String):Integer; begin Result:=-1; assignfile(ChemDat,Dateiname+'.dat'); reset(ChemDat); while not Eof(ChemDat) do begin read(ChemDat,Chem); if Chem.Name=Name then begin Result:=FilePos(ChemDat); Break end end; closefile(ChemDat) end; procedure DeleteRecord(DelIdx:Integer); var RecIdx : Integer; begin assignfile(ChemDat,Dateiname+'.dat'); reset(ChemDat); assignfile(ChemDatH,'Hilf'); rewrite(ChemDatH); RecIdx:=-1; while not Eof(ChemDat) do begin read(ChemDat,Chem); inc(RecIdx); if RecIdx<>DelIdx then write(ChemDatH,Chem) end; closefile(ChemDat); closefile(ChemDatH) end; procedure RebuildDataFile; begin assignfile(ChemDat,Dateiname+'.dat'); rewrite(ChemDat); assignfile(ChemDatH,'Hilf'); reset(ChemDatH); while not(eof(ChemDatH)) do begin read(ChemDatH,Chem); write(ChemDat,Chem); end; closefile(ChemDat); closefile(ChemDatH); erasefile(ChemdatH) end; procedure RefillGrid; var i : Integer; begin assignfile(ChemDat,Dateiname+'.dat'); reset(ChemDat); for i:=1 to FileSize(ChemDat) do begin read(ChemDat,Chem); with StringGrid1 do with Chem do begin Cells[0,i1]:=Format('%.3d',[i]); Cells[1,i1]:=IntToStr(BNum); Cells[2,i1]:=Name; Cells[3,i1]:=IntToStr(Bestand); Cells[4,i1]:=Datum end end; closefile(ChemDat); end; begin DelPos:=NamePos(EditName.Text); if DelPos>=0 then begin DeleteRecord(DelPos); RebuildDataFile; RefillGrid end end; Den Code konnte ich nicht testen, da es ja nur ein Ausriss ist. Würde mich auch wundern, wenn gar kein "Fehlerchen" drin ist. Aber wenn, dann sollte er schnell zu entdecken sein. Lass mich mal überraschen, ob es dir hilft... :hi: PS: Meine Codeformatierung weicht vom Standard ab. Das mache ich aber schon so lange so, dass ich in meinem Alter davon nicht mehr abweichen mag |
Re: StringGrid Zeile per Mausclick auslesen
@ taaktaak
Großes Dankeschön für deine Mühe. Kann das Ganze aber leider erst am WE testen (büffel z. Zt. für `ne Klausur). Melde mich, sobald ich ein Ergebnis habe. Schönen Abend noch! Michael PS: Deine Formatierung erscheint mir logischer, aber da der Empfänger des Proggis die Formatierung so möchte, mach ich es halt so. PPS: Habe in einigen Tagen das 46. Jahr geschafft. Und jetzt gehts in die Heia. |
Re: StringGrid Zeile per Mausclick auslesen
Guten Morgen Ralph,
die Neugier hat mich nicht losgelassen. Du hattest recht, mit ein paar kleinen Änderungen läuft deine Prozedur prima durch. Habe noch ein kleines Problem, für das ich nach 3 Stunden probieren noch keine Lösung habe: Beim Refill wird der dem gelöschten Datensatz nachfolgende Datensatz doppelt im StringGrid ausgegeben. In der Rebuild-Datei (und auch in 'Hilf') ist alles i.O. Beim Schließen der Datei lasse ich das StringGrid entsprechend der Anzahl der Einträge leeren. Wg. dem doppelten Datensatz bleibt dann aber der letzte im StringGrid stehen und ist dann beim erneuten öffnen der Datei natürlich immer noch da. Wäre super, wenn du mir noch ein letztes Mal helfen könntest. Irgendwie bin ich blind und finde den Fehler nicht. Meines Erachtens sollte er ja in der Refill-Prozedur stecken. Nachfolgend der aktuelle Quelltext deiner Löschprozedur. Die kommentierten Zeilen habe ich geändert.
Delphi-Quellcode:
Übrigens habe ich deine Prozedur zum Anlass genommen, das Programm zu überarbeiten. Mittlerweile ist mir klar, warum das Proggi, je länger es wurde, umso mehr Fehlermeldungen produzierte. Habe rigoros reset und closeFile benutzt. Und schon verringerte sich die Fehlerzahl.
procedure TForm1.DatenLoeschenClick(Sender: TObject);
var DelPos : Integer; ChemDatH : TChemDat; //nicht mehr global function NamePos(Name:String):Integer; begin Result:=-1; //assignfile(ChemDat,Dateiname+'.dat'); //Fehlermeldung - nach auskommentieren i.O. reset(ChemDat); while not Eof(ChemDat) do begin read(ChemDat,Chem); if Chem.Name=Name then begin Result:=FilePos(ChemDat)-1; //Filepos -1 (löscht sonst nachfolgenden Satz) Break end end; closefile(ChemDat) end; procedure DeleteRecord(DelIdx:Integer); var RecIdx : Integer; begin //assignfile(ChemDat,Dateiname+'.dat'); //Fehlermeldung - nach auskommentieren i.O. reset(ChemDat); assignfile(ChemDatH,'Hilf'); rewrite(ChemDatH); RecIdx:=-1; while not Eof(ChemDat) do begin read(ChemDat,Chem); inc(RecIdx); if RecIdx<>DelIdx then begin write(ChemDatH,Chem) end; end; closefile(ChemDat); closefile(ChemDatH); end; procedure RebuildDataFile; begin assignfile(ChemDat,Dateiname); //+'.dat' entfernt , da er sonst lauter dat anhängt rewrite(ChemDat); assignfile(ChemDatH,'Hilf'); reset(ChemDatH); while not(eof(ChemDatH)) do begin read(ChemDatH,Chem); write(ChemDat,Chem); end; closefile(ChemDat); closefile(ChemDatH); // erase(ChemdatH) nur auskommentiert, um Inhalt zu checken end; procedure RefillGrid; var i : Integer; begin assignfile(ChemDat,Dateiname); reset(ChemDat); for i:=1 to FileSize(ChemDat) do begin read(ChemDat,Chem); with StringGrid1 do with Chem do begin Cells[1,i]:=IntToStr(BNum); Cells[2,i]:=Name; Cells[3,i]:=IntToStr(Bestand); Cells[4,i]:=Datum end end; closefile(ChemDat); end; begin DelPos:=NamePos(EditName.Text); if DelPos>=0 then begin DeleteRecord(DelPos); RebuildDataFile; RefillGrid end ; EditNr.Clear; EditName.Clear; EditZugang.Text:=IntToStr(0); EditAbgang.Text:=IntToStr(0); DateTimePicker1.Date:=Date(); end; Beste Grüße Michael PS: hatte beim nochmaligen durchlesen gerade `ne Idee fürs RefillGrid: vorher alles leeren(habe RowCount festgelegt). Dann sollte es doch leer sein. Probiere es aber erst heute nachmittag aus. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:44 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-2025 by Thomas Breitkreuz