AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

StringGrid Zeile per Mausclick auslesen

Ein Thema von klausmaus · begonnen am 27. Sep 2008 · letzter Beitrag vom 10. Okt 2008
Antwort Antwort
Seite 3 von 4     123 4      
klausmaus

Registriert seit: 18. Sep 2008
17 Beiträge
 
#21

Re: StringGrid Zeile per Mausclick auslesen

  Alt 1. Okt 2008, 14:39
Probiers gleich mal aus.
Wäre prima, wenn du mir die Syntax für RenameFile verraten könntest.

Sag schon mal Danke
  Mit Zitat antworten Zitat
taaktaak

Registriert seit: 25. Okt 2007
Ort: Radbruch
1.990 Beiträge
 
Delphi 7 Professional
 
#22

Re: StringGrid Zeile per Mausclick auslesen

  Alt 1. Okt 2008, 14:43
function RenameFile(const OldName,NewName:String):Boolean; Einfach "RenameFile" eintippen, Caret drauf setzen und F1 drücken, dann zeigt die Hilfe (meist) was du wissen möchtest.
Ralph
  Mit Zitat antworten Zitat
klausmaus

Registriert seit: 18. Sep 2008
17 Beiträge
 
#23

Re: StringGrid Zeile per Mausclick auslesen

  Alt 1. Okt 2008, 15:12
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:
Dateiname:=Opendialog1.FileName;
      If Dateiname<>'then
        begin
          AssignFile(ChemDat,Dateiname+'.dat');
          rewrite(chemdat);
        end;
Dann müsste DeleteFile(Dateiname+'.dat'); korrekt sein

-Hilfsdatei wurde über Assignfile(ChemDatH,'Hilf'); erstellt
Ergo müsste RenameFile('Hilf',Dateiname+'.dat'); die Umbenennung erledigen

-vor dem Delete hab ich beide Dateien per CloseFile geschlossen

-Nun noch AssignFile(ChemDat,Dateiname+'.dat'); Und es sollte gehen. Tuts aber leider nicht.

edit: Merke gerade: Kann ja gar nicht gehen. Woher soll er den neuen Namen kennen? Oder liege ich da falsch?
  Mit Zitat antworten Zitat
taaktaak

Registriert seit: 25. Okt 2007
Ort: Radbruch
1.990 Beiträge
 
Delphi 7 Professional
 
#24

Re: StringGrid Zeile per Mausclick auslesen

  Alt 1. Okt 2008, 15:45
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.
Ralph
  Mit Zitat antworten Zitat
klausmaus

Registriert seit: 18. Sep 2008
17 Beiträge
 
#25

Re: StringGrid Zeile per Mausclick auslesen

  Alt 1. Okt 2008, 16:19
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:
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;
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.

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.
  Mit Zitat antworten Zitat
taaktaak

Registriert seit: 25. Okt 2007
Ort: Radbruch
1.990 Beiträge
 
Delphi 7 Professional
 
#26

Re: StringGrid Zeile per Mausclick auslesen

  Alt 1. Okt 2008, 17:59
Zitat:
Dort finde ich sowohl die angelegte Datei als auch die Hilf-Datei.
Ok - das bedeutet wohl, dass weder DeleteFile() noch RenameFile() erfolgreich sind. In deiner Prozedur kann ich allerdings nichts finden, was Ursache für dieses Funktionsversagen sein könnte. Vielleicht hilft ein "Application.ProcessMessages" hinter dem 2ten CloseFile()? Ausprobieren...

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".
Ralph
  Mit Zitat antworten Zitat
klausmaus

Registriert seit: 18. Sep 2008
17 Beiträge
 
#27

Re: StringGrid Zeile per Mausclick auslesen

  Alt 5. Okt 2008, 15:35
@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:
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;
Folg. Quellcode soll löschen (Hab mal kommentiert, was ich damit erreichen will):
Delphi-Quellcode:
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;
Die Hilfsdatei habe ich nach deinem Tipp lokal definiert. Die ChemDat muss m.E. global bleiben, da viele Prozeduren darauf zugreifen.

Gruß Michael
  Mit Zitat antworten Zitat
taaktaak

Registriert seit: 25. Okt 2007
Ort: Radbruch
1.990 Beiträge
 
Delphi 7 Professional
 
#28

Re: StringGrid Zeile per Mausclick auslesen

  Alt 5. Okt 2008, 18:20
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:
for i:=0 to Stelle-1 do begin
  seek(ChemDat,0);
  read(ChemDat,Chem) ;
  write(ChemDatH,Chem);
  end;
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.

Vorschlag für neue Variante:

Delphi-Quellcode:
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;
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.

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...


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
Ralph
  Mit Zitat antworten Zitat
klausmaus

Registriert seit: 18. Sep 2008
17 Beiträge
 
#29

Re: StringGrid Zeile per Mausclick auslesen

  Alt 6. Okt 2008, 21:49
@ 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.
  Mit Zitat antworten Zitat
klausmaus

Registriert seit: 18. Sep 2008
17 Beiträge
 
#30

Re: StringGrid Zeile per Mausclick auslesen

  Alt 9. Okt 2008, 23:37
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:
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;
Ü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.

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.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 4     123 4      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:13 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz