![]() |
Datenbank: DBISAM • Version: 4.21 • Zugriff über: Native
komplexe Berechnungen von abhängigen Datenbankfeldern
Hallo Leute,
nachdem ich nun in mehreren Büchern und nach einigen DP-Sitzungen noch weniger schlau bzw. ausreichend verwirrt bin, möchte ich das Problem erstmal grob schildern: Habe eine Query aus mittlerweile 12 tables und stelle die Werte mit DBLabels dar. Diese Werte werden für weitere Berechnungen, welche zunächst nicht gespeichert werden müssen, benötigt. Und zwar in der Form, dass der User z.B. einen neuen EK-Preis in ein Editfeld einträgt (hab bisher keine schlauere Idee), mittels einer Combobox einen Handlingsaufschlag wählt und damit den EK2 erhält. Dem User soll für den VK ein Vorschlag gemacht werden, den er aber ändern kann. Wenn er dies tut, so soll der Brutto-Preis errechnet werden (in Abhähngigkeit des MwSt-Satzes) und die Felder [Marge€], [Marge%], [Provision] sollen ausgefüllt werden. Jedoch soll der User auch die Möglichleit haben, in letztere Felder Werte seiner Wahl einzutragen und die vorhergehenden sollten errechnet werden. Zu allem Überfluss sollte eine Reihe von Feldern die Veränderungen eines jedes Feldes Alt zu Neu in % ausweisen. Wichtig zu wissen ist, dass nur neue Datensätz erzeugt werden sollen, also keine Änderungen oder Löschungen. Ich bekomme das bislang nur hin, in dem ich unter viel Formatierungsaufwand mit den Feldinhalten rechne - scheitere aber an dem Punkt, die neuen Werte so aufzubereiten, dass sie in die Tabelle die es betrifft eingefügt werden können. Ein DP-Mitglied gab mir die Empfehlung den Rechenkram von der Visualisierung zu trennen - ist bestimmt gut - aber wie? Die neuen Werte müssen doch erst vom User teilweise eingegeben werden und sollen noch vor dem speichern mit allen Folgewerten vorliegen ??? memTable, ParambyName, subquery, Rembrandt? Mir drehts sich auch schon im Kreis Kann mir jemand sagen, auf welchen Weg ich mich begeben soll? Viele Grüße Emilio [edit=MrSpock]Titel geändert. Mfg, MrSpock[/edit] |
Re: Katze beißt sich in den eigenen Schwanz - komplexe Frage
Hallo Emilio,
das römische Imperium ist untergegangen und so führen heute leider nicht mehr alle Wege nach Rom. Aus dem thread, in dem ich dir den Rat gab alle Rechenvorschriften aus der Benutzerschnittstelle heraus zu halten, kenne ich zumindest eine Rechenvorschrift. Du wirst mehrere benötigen, da du ja von verschiedenen Punkten ausgehen willst. Prinzipiell musst du fixe (Konstanten) und veränderliche (Variablen) Werte in deinen Berechnungen unterscheiden. Du hattest die Buchstaben a bis m vergeben - ich halte mich hier daran, auch wenn ich eine andere Benennung besser fände. Ich notiere Konstanten mit Großbuchstaben, Variablen mit Kleinbuchstaben. Deine Rechenvorschrift hatte folgenden Aufbau:
Delphi-Quellcode:
Ich gehe davon aus, dass alle cxTextEdit Eingabefelder darstellen. Aus deinem Code leite ich folgende funktionale Abhängigkeiten ab:
procedure TForm1.cxLookupComboBox1PropertiesCloseUp(Sender: TObject);
var a, c, d , e, f , g, h, i, j, k, l, m, n : Double; b : Integer; begin a := StrToFloat(cxTextEdit1.Text); b := StrToInt(cxLookupComboBox1.Text); c := a+(a*b/100); d := (a/60*100); e := (d-a); f := (d-a)*100/d; g := (d-c)*StrToFloat(cxDBLabel13.Caption)/100; h := (d*116/100); i := StrToFloat(cxDBLabel5.Caption); j := ((c/i)-1)*100; k := StrToFloat(cxDBLabel9.Caption); l := ((d/k)-1)*100; m := StrToFloat(cxLabel28.Caption); n := ((h/m)-1)*100; cxLabel14.Caption := Format('EUR ' + '%8.2f', [a+(a*b/100)]); cxTextEdit5.Text := Format('EUR ' + '%8.2f', [d]); cxTextEdit2.Text := Format('EUR ' + '%8.2f', [e]); cxTextEdit3.Text := Format('%5.2f', [f]) + '%'; cxTextEdit6.Text := Format('EUR ' + '%8.2f', [g]); cxTextEdit4.Text := Format('EUR ' + '%8.2f', [h]); cxLabel18.Caption := Format('%4.2f', [j]) + '%'; cxLabel19.Caption := Format('%4.2f', [l]) + '%'; cxLabel24.Caption := Format('%4.2f', [n]) + '%'; end;
Code:
Die Funktionen (f_c..f_h,f_j,f_l,f_n) realisierst du im implementation Abschnitt der Unit, in der du deine Rechenvorschriften speicherst. Im interface Abschnitt dieser Unit befinden sich die Funktionen für die Rechenvorschriften. Jede Rechenvorschrift hat eine bestimmte Signatur - das sind die Eingabe- und Ausgabeparameter.
A=cxTextEdit1
b=cxLookupComboBox1 O=cxDBLabel13 I=cxDBLabel5 K=cxDBLabel9 M=cxLabel28 f_c(A,b) f_d(A) f_e(A,d) f_f(A,d) f_g(c,d,O) f_h(d) f_j(c,I) f_l(d,K) f_n(h,M)
Delphi-Quellcode:
Das Durchrechnen der Werte als Reaktion auf die Änderung in der ComboBox geschieht dann so:
unit CalcMdl;
interface procedure CalcRule01(A,I,K,M,O: Extended; b: Integer; var c,d,e,f,g,h,j,l,n: Extended); implementation function f_c(A: Extended; b: Integer): Extended; forward; function f_c(A: Extended; b: Integer): Extended; begin Result := a + (a * b / 100); end; procedure CalcRule01(A,I,K,M,O: Extended; b: Integer; var c,d,e,f,g,h,j,l,n: Extended); begin c := f_c(A, b); d := f_d(A); e := f_e(A, d); f := f_f(A, d); g := f_g(c, d, O); h := f_h(d); j := f_j(c, I); l := f_l(d, K); n := f_n(h, M); end; end.
Delphi-Quellcode:
Das verstehe ich unter Trennung. Beachte auch, dass ich Double durch Extended ersetzt habe - wegen der höheren Rechengenauigkeit. Wenn du alle Berechnungsvorschriften entworfen hast, dann wirst du eventuell feststellen, dass manche Elementarfunktion (f_c, f_d, ...) nur einmal verwendet wird. Es steht dir dann frei solche "internen" Funktionen zu integrieren. Und noch einmal mein Rat über eine Namenskonvention für dein Programm nachzudenken - du wirst es nicht bereuen.
procedure TForm1.cxLookupComboBox1PropertiesCloseUp(Sender: TObject);
var A, c, d , e, f , g, h, I, j, K, l, M, n, O: Extended; b : Integer; begin A := StrToFloat(cxTextEdit1.Text); I := StrToFloat(cxDBLabel5.Caption); K := StrToFloat(cxDBLabel9.Caption); M := StrToFloat(cxLabel28.Caption); O := StrToFloat(cxDBLabel13.Caption); b := StrToInt(cxLookupComboBox1.Text); CalcRule01(A, I, K, M, O, b, c, d, e, f, g, h, j, l, n); cxLabel14.Caption := Format('EUR ' + '%8.2f', [c]); cxTextEdit5.Text := Format('EUR ' + '%8.2f', [d]); cxTextEdit2.Text := Format('EUR ' + '%8.2f', [e]); cxTextEdit3.Text := Format('%5.2f', [f]) + '%'; cxTextEdit6.Text := Format('EUR ' + '%8.2f', [g]); cxTextEdit4.Text := Format('EUR ' + '%8.2f', [h]); cxLabel18.Caption := Format('%4.2f', [j]) + '%'; cxLabel19.Caption := Format('%4.2f', [l]) + '%'; cxLabel24.Caption := Format('%4.2f', [n]) + '%'; end; Grüße vom marabu |
Re: Katze beißt sich in den eigenen Schwanz - komplexe Frage
Hi,
ändere bitte noch den Titel so, dass dieser auch aussagekräftig ist. Danke, ...:cat:... |
Flut v. Rechenvorgängen v. Visualisierung trennen
Hi Marabu,
vielen vielen Dank! Bin dabei Deine Ausführungen umzusetzen (wobei für Dich der Code jetzt verständlicher ist, ist er für mich sehr viel aufwändiger zu lesen - ich tue mich mit der Abstraktion leichter, da ich dann die Rechenformeln leichter formulieren und lesen kann). Eine Frage zur der Funktion, die Du beispielweise anführst: muss die Deklaration der Funktion nicht im Interface-Abschnitt erfolgen? Wenn nein, warum nicht? So, jetzt bastel ich erstmal weiter an der "Übersetzung". Viele Grüße Emilio |
Re: Katze beißt sich in den eigenen Schwanz - komplexe Frage
@sakura,
:gruebel: wie geht'n das mit dem sräd-Titel ändern? |
Re: Katze beißt sich in den eigenen Schwanz - komplexe Frage
Hi Emilio,
nur die Rechenvorschriften gehören in den interface Abschnitt, weil sie von außen erreichbar sein müssen. f_c() ist eine rein interne Funktion und gehört deswegen in den implementation Abschnitt. Da ich dort nicht ausschließen kann, dass die Basis-Funktionen sich in unterschiedlicher Reihenfolge gegenseitig rufen, deklariere ich sie zuerst mit der forward Direktive. Gute Nacht marabu PS: du kannst den Titel ändern, wenn du deinen ersten Beitrag bearbeitest. |
Re: Katze beißt sich in den eigenen Schwanz - komplexe Frage
Zitat:
|
Re: Katze beißt sich in den eigenen Schwanz - komplexe Frage
Hi @all,
das mit dem Thema-Titel ändern geht nicht mehr ... vielleicht kann ja einer der Mods eingreifen? @Marabu, Zitat:
Zitat:
Emilio |
Re: Katze beißt sich in den eigenen Schwanz - komplexe Frage
Guten Morgen Emilio,
ich unterscheide Berechnungsvorschriften von mathematischen Funktionen. Die Vorschriften müssen in den interface Abschnitt der Unit CalcMdl, weil sie für die ComboBox in deiner MainForm sichtbar sein müssen. Dazu bindest du die Unit CalcMdl per USES in den implementation Abschnitt deiner MainForm ein und schon kannst du aus dem event handler der ComboBox alle Vorschriften aufrufen. Die mathematischen Funktionen (z.B. Berechnung eines Prozentsatzes) werden nur von den Vorschriften benötigt und deshalb im implementation Abschnitt der Unit CalcMdl deklariert. Du kannst alle Vorschriften und Funktionen in einer einzigen Unit (CalcMdl, dein Kalkulationsmodell) unterbringen. Dein Code wird wohl nie so umfangreich werden, als dass sich eine eigene Unit je Berechnungsvorschrift lohnen wird. Grüße vom marabu |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hi Marabu,
Die Calc-Unit habe ich eingebunden - das war kein Thema. Beim Compilieren erhalte ich nun die Fehlermeldung: "inkompatible Typen Integer und Extended", sowie die Fehlermeldung "nicht genügend wirkliche Parameter" Der Cursor steht für beide Meldungen in der Zeile (UnitMain wohlbemerkt): CalcRule01( ...);, welche ich aus Deinem script übernommen habe. Sollte ich noch ne Kleinigkeit übersehen haben? Die Variablen a (jetzt "ekneu") und b (jetzt "zuschlag") sind als Integer deklariert, in beiden Units. VG Emilio |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:03 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 by Thomas Breitkreuz