DBGrid

Für Fragen von Einsteigern und Programmieranfängern...
l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Re: DBGrid

Beitrag von l0lhaxx »

Diesen Fehler hatte ich bereits behoben. Bei mir ist eingentlich nur die Form2 und Form1 bei deinem Projekt verdreht. Und statt mit einem Tbutton öffne ich Form2 mit einem TMainMenu. Spielt aber ja eigentlich keine Rolle. Das Problem tritt immer noch auf, was könnte mit dem Field not found noch gemeint sein? Bevor ich das Programm schließe und wieder Neustarte kommt der Fehler ja auch nicht....

Außerdem funktioniert meine Rechnung nicht....Hab mich daran versucht min / max Angaben zu berechnen mit einer bestimmten Gramm- und Toleranz Zahl. Mein Ergebnis lautet allerdings immer 0,000.

Code: Alles auswählen

 
 DBEdit2.Text:=FormatFloat ('#,##0.000',         Form3.Dbf1.FieldByName('WERT A [G]').AsFloat / 100 *
                                                 Form3.Dbf1.FieldByName('WERT A [%]').AsFloat +
                                                 Form3.Dbf1.FieldByName('WERT A [G]').AsFloat);
 
 DBEdit3.Text:=FormatFloat ('#,##0.000',         Form3.Dbf1.FieldByName('WERT A [G]').AsFloat -
                                                (Form3.Dbf1.FieldByName('WERT A [G]').AsFloat / 100 *
                                                 Form3.Dbf1.FieldByName('WERT A [%]').AsFloat)); 
 

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: DBGrid

Beitrag von Michl »

Du machst es einem echt schwer. Ich dachte, du redest von dem von mir beigefügten Projekt, meinst aber dein eigenes...

Code: Alles auswählen

Form3.Dbf1.FieldByName('WERT A [G]').AsFloat
Hast du tatsächlich den Fieldnamen "WERT A [G]" vergeben? Ich habe es eben mal in meinem Projekt probiert, man kann tatsächlich so einen Fieldnamen vergeben, das ist mMn aber ein No-Go. Besser ist es eindeutige Fieldnamen ohne Sonder- und Leerzeichen zu vergeben, ansonsten sind später Probleme damit vorprogrammiert.

Hätte ich nicht gedacht, dass sowas mit Dbf problemlos möglich ist:

Code: Alles auswählen

  if not FileExists(Dbf.TableName) then begin
    Dbf.FieldDefs.Clear;
    Dbf.FieldDefs.Add('NR', ftAutoInc, 0, True);
    Dbf.FieldDefs.Add('ADRESSE', ftString, 500, True);
    Dbf.FieldDefs.Add('NAME', ftString, 200, True);
    Dbf.FieldDefs.Add('WERT A [G]', ftFloat, 0, True); // <-- 
    Dbf.FieldDefs.Add('KOSTEN2', ftFloat, 0, True);
 
    Dbf.CreateTable;
  end;  
Ansonsten kommen wir hier, glaube ich, nicht weiter. Versuche mal dein Projekt auf das Wesentlichste zu reduzieren und als Minimalbeispiel gezippt hier hochzuladen (ohne Exe und Verzeichnis lib), ansonsten rede ich von Birnen und du von Äpfeln.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Re: DBGrid

Beitrag von l0lhaxx »

Hi,

im Anhang mein Minimalbeispiel.
Hoffe du kannst mir helfen. Danke vorab!
Zuletzt geändert von l0lhaxx am Mi 3. Feb 2016, 15:04, insgesamt 1-mal geändert.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: DBGrid

Beitrag von Michl »

Ok, ich habe es mir mal angeschaut. Ich hätte viele Anregungen, ich bleibe aber mal bei diesem Thema und beschreibe einfach mal, wie ich diesem Verhalten auf die Spur ging.

Wenn man das Projekt startet, stellt man fest, dass egal, welchen Wert man in der TDBLookupComboBox wählt, keine Änderung in den DBEdit2 Textfeldern zu sehen sind. Diese sollten aber stattfinden bei:

Code: Alles auswählen

procedure TForm1.BerechneSumme (Dataset: TDataset);
begin
  Form1.DBEdit2.Text:=FormatFloat('#,##0.000', Form3.Dbf1.FieldByName('WERT A [G]').AsFloat / 100 *
                                               Form3.Dbf1.FieldByName('WERT A [%]').AsFloat +
                                               Form3.Dbf1.FieldByName('WERT A [G]').AsFloat);
 
  Form1.DBEdit3.Text:=FormatFloat('#,##0.000', Form3.Dbf1.FieldByName('WERT A [G]').AsFloat -
                                              (Form3.Dbf1.FieldByName('WERT A [G]').AsFloat / 100 *
                                               Form3.Dbf1.FieldByName('WERT A [%]').AsFloat));
end;
Nun stellt sich die Frage, warum nicht. Dazu legt man einen Breakpoint auf die erste Zeile der Procedure. Startet man nun das Programm und wählt einen Eintrag in der TDBLookupComboBox, stellt man fest, dass der Breakpoint niemals angesprungen wird. Fazit, die Procedure wird nie aufgerufen.

Dass diese aufgerufen wird, hast du (bzw. ich in meinem Projekt) hier festgelegt:

Code: Alles auswählen

procedure TForm1.FormShow(Sender: TObject);
begin
  Form3.Dbf1.AfterScroll:=@BerechneSumme;
end;  
Leider wird scheinbar TForm1.OnShow zu früh gefeuert, sodaß der Eventhandler nicht richtig eingetragen wird. Als Test für diese Theorie kannst du mal das Projekt starten, Form3 öffnen, Form3 wieder schließen, nun wird OnShow vom Form1 wieder aufgerufen und schon klappt es, wie gewünscht.

Du hast jetzt die Möglichkeit einen späteren Event für die Zuweisung zu suchen (z.B. OnActivate), ein TDatenModul zu verwenden (wie ich), ein TDbf auf dem aktuellen Formular zu platzieren oder einen vierten Weg zu probieren.

Bitte bei dem nächsten Minimalbeispiel den Ordner "lib" und auch die SQLite.dll (zumal nicht genutzt) nicht in das Zip tun.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Re: DBGrid

Beitrag von l0lhaxx »

okay da stimm ich dir zu.
Aber was mich noch etwas verwirrt....Funktioniert bei dir das Programm jetzt einfach so?

Wenn ich es kompiliere steht in Lazarus zwar das alles in Ordnung ist, beim Debuggen kann ich aber 5min warten und nichts passiert....
Die projekt.exe wird aber erstellt.

Wenn ich diese dann im Projektverzeichnis starte öffnen sie sich nicht, ist aber im Taskmanager angegeben.

Wenn ich die Projekt.exe aber aus dem Verzeichnis nehme und z.B. auf den Desktop kopiere, dann startet die Software.
Hast du auch mal probiert das Programm komplett zu schließen und neuzustarten?
Wenn ich dann eine Nummer, bzw. Programm auswählen will, kommt eben die Fehlermeldung...

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: DBGrid

Beitrag von Michl »

l0lhaxx hat geschrieben:Funktioniert bei dir das Programm jetzt einfach so?
Leider nein, ich habe diverse Package-Abhängigkeiten entfernen müssen.
l0lhaxx hat geschrieben:Wenn ich es kompiliere steht in Lazarus zwar das alles in Ordnung ist, beim Debuggen kann ich aber 5min warten und nichts passiert....
Die projekt.exe wird aber erstellt.

Wenn ich diese dann im Projektverzeichnis starte öffnen sie sich nicht, ist aber im Taskmanager angegeben.

Wenn ich die Projekt.exe aber aus dem Verzeichnis nehme und z.B. auf den Desktop kopiere, dann startet die Software.
Hast du auch mal probiert das Programm komplett zu schließen und neuzustarten?
Wenn ich dann eine Nummer, bzw. Programm auswählen will, kommt eben die Fehlermeldung...
So eine Verhalten kann ich nicht nachvollziehen. Klingt mir nach einer verkorksten Lazarusinstallation oder du nutzt die 64bit Version von Lazarus. Diese hat unter Windows Probleme mit dem Debugger. Daher entwickle ich unter Lazarus 32bit und erstelle mir wenn ich fertig bin, wenn nötig, ein 64bit Programm.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Re: DBGrid

Beitrag von l0lhaxx »

Hab Lazarus mal einer Neuinstallation unterzogen, jetzt Funktioniert das kompilieren wieder....Danke!

Ich hab jetzt wirklich nur noch das Problem mit der Fehlermeldung: Dbf1: Field not found:"".
Mir ist dazu folgendes aufgefallen:

1. Wenn ich die Projekt.exe im Projektverzeichnis starte und wähle eine bestimmte Nummer im LookUpComboBox auswähle, kommt
die oben genannte Fehlermeldung. Die DBEdit-Felder werden aber alle korrekt ausgefüllt und berechnet.....

2. Wenn ich vor dem starten der Projekt.exe die Datenbank-Dateien im Verzeichnis lösche, erstellt das Programm bei starten diese Neu (Soll es ja auch). Wenn ich dann Einträge hinzufüge, kann ich mit dem LookUpComboBox zwischen den Programmen wählen bis ich das Programm Neustarte
---> Dann wieder Fehlermeldung.

Was könnte das jetzt wieder sein?

Danke für deine Hifle!

(Debuggernachtricht im Anhang)
Dateianhänge
Unbenannt.PNG
Unbenannt.PNG (9.76 KiB) 2047 mal betrachtet

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: DBGrid

Beitrag von Michl »

Dein Projekt läuft bei mir problemlos mit FPC Trunk und Lazarus Trunk. Habe es eben noch mal mit einer alten Lazarusversion 1.4.0 probiert und tatsächlich wurde das Projekt nicht gestartet. Da das von mir oben gepostete Beispiel auch unter Lazarus 1.4.0 funktioniert muss die Ursache in einem Unterschied von deinem zu meinem Projekt zu suchen sein.

Ich vermute mal stark, dass es hiermit zusammenhängt:
Michl hat geschrieben:

Code: Alles auswählen

Form3.Dbf1.FieldByName('WERT A [G]').AsFloat
Hast du tatsächlich den Fieldnamen "WERT A [G]" vergeben? Ich habe es eben mal in meinem Projekt probiert, man kann tatsächlich so einen Fieldnamen vergeben, das ist mMn aber ein No-Go. Besser ist es eindeutige Fieldnamen ohne Sonder- und Leerzeichen zu vergeben, ansonsten sind später Probleme damit vorprogrammiert.
Versuche doch mal Bezeichner für Fieldnamen zu wählen, die ohne einem Leerzeichen, einem "[", "]" oder "%" auskommen. Ich weiß nicht, ob das die Ursache ist, könnte es mir aber gut vorstellen.

Wenn dir die Anzeige dieser Fieldnamen nicht gefällt, kannst du diese nach Belieben anpassen. Das hat auch den Vorteil, dass die Fieldnamen unabhängig der angezeigten Namen sind und somit in jeder beliebigen Sprache erscheinen können z.B.:

Code: Alles auswählen

procedure TForm3.Dbf1AfterOpen(DataSet: TDataSet);
var
  i: Integer;
begin
  for i := 0 to Dbf1.FieldCount - 1 do
    case Dbf1.Fields[i].Fieldname of
      'PROGRAMM':
      begin
        DBGrid1.Columns[i].Width := 100;
        Dbf1.Fields[i].DisplayLabel := 'Ein schönes Programm';
      end; 
...
end;

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Re: DBGrid

Beitrag von l0lhaxx »

Habe den Fehler (hoffentlich) gefunden.
Bei DBLookComboBox Values Datasource und Keyfield einfach leer geslassen....
und jetzt funktioniert es wie es soll..... Komisch

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: DBGrid

Beitrag von Michl »

l0lhaxx hat geschrieben:jetzt funktioniert es wie es soll
Das ist gut, dass du eine Lösung gefunden hast. Hier ist es genau umgekehrt, schmeiße ich die Einträge raus, geht nichts mehr. Vermutlich gab es da zwischenzeitlich ein Bugfix.

Na dann noch viel Erfolg weiterhin!

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Re: DBGrid

Beitrag von l0lhaxx »

Michl hat geschrieben: Hier ist es genau umgekehrt, schmeiße ich die Einträge raus, geht nichts mehr.
Wirklich komisch...Danke für deine Hilfe!

PS: Kann man eigentlich auch ohne den Navigator neue Zeilen in eine Dbase einfügen?

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: DBGrid

Beitrag von Michl »

l0lhaxx hat geschrieben:PS: Kann man eigentlich auch ohne den Navigator neue Zeilen in eine Dbase einfügen?
Ja, aber so eine Frage kannst du dir auch mittels Suchmaschine "TDbf + Insert" viel schneller selber beantworten.

Sollte so gehen:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
begin
  Dbf1.Insert;
  Dbf1.FieldByName('PROGRAMM').AsInteger := 123;
  ...
  Dbf1.Post;
end;  

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Re: DBGrid

Beitrag von l0lhaxx »

Code: Alles auswählen

 
Form5.Dbf2.FieldByName('DATUM').AsInteger:= DateTimePicker1.Date; 
 
bekomme dann die Fehlermeldung

unit1.pas(185,61) Error: Incompatible type for arg no. 1: Got "TDateTimePicker", expected "LongInt"

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: DBGrid

Beitrag von Michl »

Du kannst auch keinen Brief in einen Pfandflaschenautomat werfen und hoffen, dass der Brief irgendwie ankommt :?

Zwei Dinge vorab:
- zum einen passt die Fehlermeldung nicht zum geposteten Code.
- die Fehlermeldung ist mMn sehr eindeutig und vermutlich eine der am häufigsten auftretenden Fehlermeldungen. Selbst wenn man kein Englisch kann, gibt es Hilfsmittel, wie den Bing Translator. Gibt man dort die Fehlermeldung

Code: Alles auswählen

Incompatible type for arg no. 1: Got "TDateTimePicker", expected "LongInt"
ein, bekommt man als Übersetzung

Code: Alles auswählen

Inkompatiblen Typ für Arg Nr. 1: bekam "TDateTimePicker", "LongInt" erwartet
Deine Aufgabe als Programmierer ist es nun zu schauen, welcher Typ erwartet wird und welchen du zuweist.

Ich weiß nicht, wie dein Feld Datum definiert ist. Normalerweise würde ich dieses als ein "ftDate" oder "ftDateTime" deklariertes vermuten. Beides benötigen TDate oder TDateTime. Schaut man mal in deren Deklaration (einfach mit <Ctrl> + <Linksklick> soweit zurückverfolgen, bis es nicht mehr geht), sieht man, dass diese von Double abgeleitet sind.

Daher ist das Feld "DATUM" ein von Double abgeleitetes Feld und sollte so zuzuweisen sein:

Code: Alles auswählen

SomeTDbf.FieldByName('DATUM').AsFloat := DateTimePicker1.Date;
besser verständlich wäre allerdings:

Code: Alles auswählen

SomeTDbf.FieldByName('DATUM').AsDateTime := DateTimePicker1.Date;

Sollte das Feld "DATUM" als ein Integer oder sonstiger ganzzahliger Datentyp deklariert sein müsste man diesen Zahlentyp entsprechend zuweisen (mittels Round oder Trunc):

Code: Alles auswählen

SomeTDbf.FieldByName('DATUM').AsInteger := Trunc(DateTimePicker1.Date);
Sollte "DATUM" ein String sein, findest du die Lösung sicherlich selbst...

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

l0lhaxx
Beiträge: 89
Registriert: Di 8. Dez 2015, 09:20

Re: DBGrid

Beitrag von l0lhaxx »

Hi,
klappt soweit jetzt alles. Hab allerdings das Problem das ich bei einem neuen Datenbankeintrag einen Crash bekomme. Wollte ich jetzt mit einer IF-Abfrage umgehen, funktioniert aber leider nicht, die Summe wird trotzdem berechnet.

Code: Alles auswählen

 
procedure TForm1.FormActivate(Sender: TObject);
begin
 //Wenn anderes Programm ausgewählt wird (Scroll)
 //wird die Summe neu berechnet
 if Form3.Visible=False then begin
  Form3.Dbf1.AfterScroll:=@Form1.BerechneSumme;
end;
end;
 
Noch eine Idee diesbezüglich?

Danke!

Antworten