![]() |
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 |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Emilio, du wirst doch die Signatur von CalcRule01() an deine geänderten Bedürfnisse angepasst haben? A war bei meinem Beispiel ja noch Extended...
marabu |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Ups, hab ich mich doch verschrieben, ich meinte
die Variablen a = zuschlag und b = ProvSatz sind als Integer deklariert, da sie solche sind. Ich stell mal den neuen Code rein: Unit Main:
Delphi-Quellcode:
und die zweite unit:
procedure TForm1.cxLookupComboBox1PropertiesCloseUp(Sender: TObject);
var ekneu, bpneu, lvpneu , margeEneu, margeprozneu , provlvpneu, bruttolvpneu, bpaender, lvpaender, bruttolvpaender, BPALT, LVPAlt, BruttoLVPAlt : Extended; zuschlag, ProvSatz : Integer; begin ekneu := StrToFloat(cxTextEdit1.Text); BPAlt := StrToFloat(cxDBLabel5.Caption); LVPAlt := StrToFloat(cxDBLabel9.Caption); BruttoLVPAlt := StrToFloat(cxLabel17.Caption); ProvSatz := StrToInt(cxDBLabel13.Caption); zuschlag := StrToInt(cxLookupComboBox1.Text); CalcRule01(ekneu, bpneu, lvpneu, margeEneu, margeprozneu, provlvpneu, bruttolvpneu, bpaender, lvpaender, bruttolvpaender, BPALT, LVPAlt, BruttoLVPAlt, ProvSatz, zuschlag); cxLabel14.Caption := Format('EUR ' + '%8.2f', [bpneu]); cxTextEdit5.Text := Format('EUR ' + '%8.2f', [lvpneu]); cxTextEdit2.Text := Format('EUR ' + '%8.2f', [margeEneu]); cxTextEdit3.Text := Format('%5.2f', [margeprozneu]) + '%'; cxTextEdit6.Text := Format('EUR ' + '%8.2f', [provlvpneu]); cxTextEdit4.Text := Format('EUR ' + '%8.2f', [bruttolvpneu]); cxLabel18.Caption := Format('%4.2f', [bpaender]) + '%'; cxLabel19.Caption := Format('%4.2f', [lvpaender]) + '%'; cxLabel24.Caption := Format('%4.2f', [bruttolvpaender]) + '%'; end;
Delphi-Quellcode:
Ich kann leider nicht erkennen, wo ich noch was anpassen müsste.unit Kalk; interface procedure CalcRule01(EKAlt,BPAlt,LVPAlt,BruttoLVPAlt,MargeEAlt, MargeProzAlt, ProvLVPAlt, MwSt: Extended; zuschlag,ProvSatz: Integer; var ekneu, bpneu,lvpneu,margeEneu,margeprozneu,provlvpneu,bruttolvpneu,bpaender,lvpaender,bruttolvpaender, ekaender, margeEaender, margeprozaender, provlvpaender: Extended); implementation function f_bpneu(ekneu: Extended; zuschlag: Integer): Extended; forward; function f_lvpneu(ekneu: Extended): Extended; forward; function f_margeEneu(ekneu: Extended; lvpneu: Extended):Extended; forward; function f_margeprozneu(ekneu: Extended; lvpneu: Extended):Extended; forward; function f_provlvpneu(bpneu: Extended; lvpneu: Extended; ProvSatz: Integer):Extended; forward; function f_bruttolvpneu(lvpneu: Extended; MwSt: Extended): Extended; forward; function f_ekaender(ekneu: Extended; EKAlt: Extended): Extended; forward; function f_bpaender(bpneu: Extended; BPAlt: Extended): Extended; forward; function f_lvpaender(lvpneu: Extended; LVPAlt: Extended): Extended; forward; function f_bruttolvpaender(bruttolvpneu: Extended; BruttoLVPAlt: Extended): Extended; forward; function f_margeEaender(margeEneu: Extended; MargeEAlt: Extended): Extended; forward; function f_margeprozaender(margeEneu: Extended; MargeEAlt: Extended): Extended; forward; function f_provlvpaender(provlvpneu: Extended; ProvLVPAlt: Extended): Extended; forward; function f_bpneu(ekneu: Extended; zuschlag: Integer): Extended; begin Result := ekneu + (ekneu * zuschlag / 100); end; function f_lvpneu(ekneu: Extended): Extended; begin Result := ekneu/55*100; end; function f_margeEneu(ekneu: Extended; lvpneu: Extended): Extended; begin Result := lvpneu-ekneu; end; function f_margeprozneu(ekneu: Extended; lvpneu: Extended): Extended; begin Result := (1-(ekneu/lvpneu)*100); end; function f_provlvpneu(bpneu: Extended; lvpneu: Extended; ProvSatz: Integer): Extended; begin Result := (lvpneu-bpneu)*ProvSatz/100; end; function f_bruttolvpneu(lvpneu: Extended; MwSt: Extended): Extended; begin Result := lvpneu+(lvpneu*MwSt/100); end; function f_ekaender(ekneu: Extended; EKAlt: Extended): Extended; begin Result := (ekneu/EKAlt-1)*100; end; function f_bpaender(bpneu: Extended; BPAlt: Extended): Extended; begin Result := (bpneu/BPAlt-1)*100; end; function f_lvpaender(lvpneu: Extended; LVPAlt: Extended): Extended; begin Result := (lvpneu/LVPAlt-1)*100; end; function f_bruttolvpaender(bruttolvpneu: Extended; BruttoLVPAlt: Extended): Extended; begin Result := (bruttolvpneu/BruttoLVPAlt-1)*100; end; function f_margeEaender(margeEneu: Extended; MargeEAlt: Extended): Extended; begin Result := (margeEneu-MargeEAlt); end; function f_margeprozaender(margeEneu: Extended; MargeEAlt: Extended): Extended; begin Result := (margeEneu/MargeEAlt-1)*100; end; function f_provlvpaender(provlvpneu: Extended; ProvLVPAlt: Extended): Extended; begin Result := (provlvpneu/ProvLVPAlt-1)*100; end; procedure CalcRule01(EKAlt,BPAlt,LVPAlt,BruttoLVPAlt,MargeEAlt, MargeProzAlt, ProvLVPAlt,MwSt: Extended; zuschlag, ProvSatz: Integer; var ekneu, bpneu,lvpneu,margeEneu,margeprozneu,provlvpneu,bruttolvpneu,bpaender,lvpaender,bruttolvpaender, ekaender, margeEaender, margeprozaender, provlvpaender: Extended); begin bpneu := f_bpneu(ekneu, zuschlag); lvpneu := f_lvpneu(ekneu); margeEneu := f_margeEneu(ekneu, lvpneu); margeprozneu := f_margeprozneu(ekneu, lvpneu); provlvpneu := f_provlvpneu(bpneu, lvpneu, ProvSatz); bruttolvpneu := f_bruttolvpneu(lvpneu, MwSt); bpaender := f_bpaender(bpneu, BPAlt); lvpaender := f_lvpaender(lvpneu, LVPAlt); bruttolvpaender := f_bruttolvpaender(bruttolvpneu, BruttoLVPAlt); ekaender := f_ekaender(ekneu, EKAlt); margeEaender := f_margeEaender(margeEneu, MargeEAlt); margeprozaender := f_margeProzaender(margeEneu, MargeEAlt); provlvpaender := f_provlvpaender(provlvpneu, ProvLVPNeu); end; end. //Konstanten: // EKAlt = cxDBLabel8 // BPAlt = cxDBLabel5 // LVPAlt = cxDBLabel9 // BruttoLVPAlt = cxDBLabel17 // MargeEAlt = cxDBLabel11 // MargeProzAlt = cxDBLabel12 // ProvLVPAlt = cxDBLabel14 // MwSt = cxDBLabel16 // ProvSatz = cxDBLabel13 // Variablen // ekneu = cxTextEdit1 // zuschlag = cxLookupCombobox1 // bpneu = cxLabel14 // lvpneu = cxTextEdit5 // bruttolvpneu = cxTextEdit4 // margeEneu = cxTextEdit2 // margeprozneu = cxTExtEdit3 // provlvpneu = cxTextEdit6 // + die Variablen, welche die Veränderungen neu gegen alt "anzeigen" sollen // ekaender = cxLabel15 // bpaender = cxLabel18 // lvpaender = cxLabel19 // bruttolvpaender = cxLabel24 +++ eingentlich obsolet, aberwassolls +++ // margeEaender = cxLabel25 // margeprozaender = cxLabel26 // provlvpaender = cxLabel27 VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Emilio,
der Compiler meckert wohl zu Recht: Zitat:
marabu |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hi Marabu,
so, habs vervollständigt. Die Fehlermeldung mit den ungenügenden Parametern ist weg. Die Meldung "inkompatible Typen Integer und Extended" ist jetzt 2mal da und dazu die Meldung "Die Typen der tatsächlichen und formalen Var-Parameter müssen übereinstimmen." Die einzigen beiden Integer-Werte sind [zuschlag] und [provSatz]; ändere ich diese auf Extended (in beiden Units an jeder Stelle) , so compiliert das Programm zwar, allerdings mit den Warnhinweisen, dass die (in Summe 9) Variablen möglicherweise nicht initialisiert worden sind. Ist es notwendig alle Werte auf Extended einzustellen, selbst wenn sie es originär nicht sind? Wie initialisiere ich die 9 Variablen? Wie Du an meinen Fragen erkennen kannst, bewege ich mich auf Neuland. VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Bei so vielen Parametern in einem Aufruf kann man schonmal die Übersicht verlieren. Es bleibt dir wohl nichts anderes übrig, als jeden Aufruf akribisch unter die Lupe zu nehmen. Jeder Parameter muss mit einem passenden Wert belegt werden, wobei du manchmal auf automatische Typanpassung durch den Compiler hoffen darfst. Einem Extended-Parameter kannst du so ungestraft einen Integer-Wert zuweisen - andersrum geht es nicht.
marabu |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hi Marabu,
ich werd noch zum Elch: sofern ich einen der originären Werte auf Integer stelle, scheitert die Kompilierung mit der Meldung: "inkompatible blabla ; die Typen der tatsächlichen und formalen Var-Parameter müssen übereinstimmen." Stelle ich alle Wert auf Extended ein, so kompiliert das Programm mit der bekannten Warnung das 9 Variablen (bpneu, lvpneu, margeEneu, margeprozneu, provlvpneu, bruttolvpneu, bpaender, lvpaender, ekaender) möglicherweise nicht initialisiert worden sind. Ich kann nicht erkennen, dass ich bei diesen Variablen irgendwie anders vorgegangen bin als bei den anderen. Das Programm stoppt dann in dem Moment wo das ComboboxOnCloseUp-Ereignis ausgelöst werden soll mit einer Meldung "EInvalidOp" ... 'ungültige Gleitkommaoperation! ..." Wo schuht der Drück? VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Die Fehlermeldung mit den möglicherweise nicht initalisierten Variablen, verschwand, nachdem ich die Reihenfolge der Funktionszuweisungen in der Unit Calc geändert habe ... freu!
Die ungültige Gleitmittel-OP bleibt leider. VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Ändere ich die Funktion, auf die die Gleitkomma-Fehlermeldung verweist in eine blödsinnige (bei der keine Division erfolgt), dann passiert bei den nachfolgenden Funktionen, die eine Division enthalten dasselbe. Ändere ich all diese Funktionen in einfache, dann läuft das Programm ohne Fehler, zeigt aber in den Ergebnisfelder nur Nullen an.
Hm, da kanns doch nicht nur an den Formeln liegen, oder? |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
:wall: Emilio is'n Dummi! - ekneu ist ja gar keine Variable, sondern in dieser CalcRule eine Konstante ...
dafür sind jetzt möglicherweise wieder 10 Variablen nicht initialisiert und die ERgebnisfelder sind alle "0" - aaaargh! |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
@ Marabu,
würde mich mächtig freuen, wenn Du Deinen geschulten Blick noch einmal auf den Code werfen könntest; Wie durch Geisterhand sind Warnungen mit möglicherweise nichtinitialisierten Variablen verschwunden (vielleicht hat DELPHI erkannt, dass ich veredlungsresistent bin und aufgegeben ...) Das Programm läuft sauber aber bewirkt nicht das was es sollte. Die Felder die berechneten Werte anzeigen sollen, weisen nach einigem rumprobieren und überlegen immer nur den Wert "0" aus; zwar schön formatiert, aber wertlos. Eigentlich kann es doch nur so sein, dass zum Zeitpunkt der Berechnungen, das Feld [ekneu] oder cxTextEdit1 leer ist - isses aber (zumindest optisch) nicht. Ich komme nicht dahinter!
Delphi-Quellcode:
und die Kalk-Unit:
procedure TForm1.cxLookupComboBox1PropertiesCloseUp(Sender: TObject);
var ekneu, bpneu, lvpneu , margeEneu, margeprozneu , provlvpneu, bruttolvpneu, ekaender, bpaender, lvpaender, bruttolvpaender, margeEaender, margeprozaender, provlvpaender, EKAlt,BPAlt, LVPAlt, BruttoLVPAlt, MargeEAlt, MargeProzAlt, ProvLVPAlt, MwSt, Provsatz, zuschlag : Extended; begin ekneu := StrToFloat(cxTextEdit1.Text); EKAlt := StrToFloat(cxDBLabel8.Caption); BPAlt := StrToFloat(cxDBLabel5.Caption); LVPAlt := StrToFloat(cxDBLabel9.Caption); BruttoLVPAlt := StrToFloat(cxDBLabel17.Caption); MargeEAlt := StrToFloat(cxDBLabel11.Caption); MargeProzAlt := StrToFloat(cxDBLabel12.Caption); ProvLVPAlt := StrToFloat(cxDBlabel14.Caption); MwSt := StrToFloat(cxDBLabel16.Caption); ProvSatz := StrToFloat(cxDBLabel13.Caption); zuschlag := StrToFloat(cxLookupComboBox1.Text); CalcRule01(ekneu, bpneu, lvpneu, margeEneu, margeprozneu, provlvpneu, bruttolvpneu, ekaender, bpaender, lvpaender, bruttolvpaender, margeEaender, margeprozaender, provlvpaender, EKAlt, BPALT, LVPAlt, BruttoLVPAlt, MargeEAlt, MargeProzAlt,ProvLVPAlt,MwSt, ProvSatz, zuschlag); cxTextEdit1.Text := Format('%m', [ekneu]); cxLabel14.Caption := Format('EUR ' + '%8.2f', [bpneu]); cxTextEdit5.Text := Format('EUR ' + '%8.2f', [lvpneu]); cxTextEdit4.Text := Format('EUR ' + '%8.2f', [bruttolvpneu]); cxTextEdit2.Text := Format('EUR ' + '%8.2f', [margeEneu]); cxTextEdit3.Text := Format('%5.2f', [margeprozneu]) + '%'; cxTextEdit6.Text := Format('EUR ' + '%8.2f', [provlvpneu]); cxLabel18.Caption := Format('%4.2f', [bpaender]) + '%'; cxLabel19.Caption := Format('%4.2f', [lvpaender]) + '%'; cxLabel24.Caption := Format('%4.2f', [bruttolvpaender]) + '%'; cxLabel25.Caption := Format('%8.2f', [margeEaender]); cxLabel26.Caption := Format('%4.2f', [margeprozaender]) + '%'; cxLabel27.Caption := Format('%4.2f', [provlvpaender]) + '%'; end;
Delphi-Quellcode:
interface
procedure CalcRule01(EKAlt, ekneu, BPAlt,LVPAlt,BruttoLVPAlt,MargeEAlt, MargeProzAlt, ProvLVPAlt, MwSt, ProvSatz, zuschlag: Extended; var bpneu,lvpneu, bruttolvpneu, margeEneu, margeprozneu, provlvpneu, ekaender, bpaender, lvpaender, bruttolvpaender, margeEaender, margeprozaender, provlvpaender: Extended); implementation function f_bpneu(ekneu: Extended; zuschlag: Extended): Extended; forward; function f_lvpneu(ekneu: Extended): Extended; forward; function f_margeEneu(ekneu: Extended; lvpneu: Extended):Extended; forward; function f_margeprozneu(ekneu: Extended; lvpneu: Extended):Extended; forward; function f_provlvpneu(bpneu: Extended; lvpneu: Extended; ProvSatz: Extended):Extended; forward; function f_bruttolvpneu(lvpneu: Extended; MwSt: Extended): Extended; forward; function f_ekaender(ekneu: Extended; EKAlt: Extended): Extended; forward; function f_bpaender(bpneu: Extended; BPAlt: Extended): Extended; forward; function f_lvpaender(lvpneu: Extended; LVPAlt: Extended): Extended; forward; function f_bruttolvpaender(bruttolvpneu: Extended; BruttoLVPAlt: Extended): Extended; forward; function f_margeEaender(margeEneu: Extended; MargeEAlt: Extended): Extended; forward; function f_margeprozaender(margeEneu: Extended; MargeEAlt: Extended): Extended; forward; function f_provlvpaender(provlvpneu: Extended; ProvLVPAlt: Extended): Extended; forward; function f_bpneu(ekneu: Extended; zuschlag: Extended): Extended; begin Result := ekneu + (ekneu * zuschlag / 100); end; function f_lvpneu(ekneu: Extended): Extended; begin Result := ekneu/55*100; end; function f_margeEneu(ekneu: Extended; lvpneu: Extended): Extended; begin Result := lvpneu-ekneu; end; function f_margeprozneu(ekneu: Extended; lvpneu: Extended): Extended; begin Result := (1-(ekneu/lvpneu))*100; end; function f_provlvpneu(bpneu: Extended; lvpneu: Extended; ProvSatz: Extended): Extended; begin Result := (lvpneu-bpneu)*ProvSatz/100; end; function f_bruttolvpneu(lvpneu: Extended; MwSt: Extended): Extended; begin Result := lvpneu+(lvpneu*MwSt/100); end; function f_ekaender(ekneu: Extended; EKAlt: Extended): Extended; begin Result := (ekneu/EKAlt-1)*100; end; function f_bpaender(bpneu: Extended; BPAlt: Extended): Extended; begin Result := ((bpneu+BPAlt)-1)*100; end; function f_lvpaender(lvpneu: Extended; LVPAlt: Extended): Extended; begin Result := (lvpneu+LVPAlt-1)*100; end; function f_bruttolvpaender(bruttolvpneu: Extended; BruttoLVPAlt: Extended): Extended; begin Result := (bruttolvpneu+BruttoLVPAlt-1)*100; end; function f_margeEaender(margeEneu: Extended; MargeEAlt: Extended): Extended; begin Result := (margeEneu-MargeEAlt); end; function f_margeprozaender(margeEneu: Extended; MargeEAlt: Extended): Extended; begin Result := (margeEneu+MargeEAlt-1)*100; end; function f_provlvpaender(provlvpneu: Extended; ProvLVPAlt: Extended): Extended; begin Result := (provlvpneu+ProvLVPAlt-1)*100; end; procedure CalcRule01(EKAlt, ekneu, BPAlt,LVPAlt,BruttoLVPAlt,MargeEAlt, MargeProzAlt, ProvLVPAlt,MwSt, ProvSatz, zuschlag: Extended; var bpneu, lvpneu, bruttolvpneu, margeEneu, margeprozneu, provlvpneu, ekaender, bpaender, lvpaender, bruttolvpaender, margeEaender, margeprozaender, provlvpaender: Extended); begin bpneu := f_bpneu(ekneu, zuschlag); lvpneu := f_lvpneu(ekneu); bruttolvpneu := f_bruttolvpneu(lvpneu, MwSt); margeEneu := f_margeEneu(ekneu, lvpneu); margeprozneu := f_margeprozneu(ekneu, lvpneu); provlvpneu := f_provlvpneu(bpneu, lvpneu, ProvSatz); ekaender := f_ekaender(ekneu, EKAlt); bpaender := f_bpaender(bpneu, BPAlt); lvpaender := f_lvpaender(lvpneu, LVPAlt); bruttolvpaender := f_bruttolvpaender(bruttolvpneu, BruttoLVPAlt); margeEaender := f_margeEaender(margeEneu, MargeEAlt); margeprozaender := f_margeProzaender(margeEneu, MargeEAlt); provlvpaender := f_provlvpaender(provlvpneu, ProvLVPNeu); end; end. :gruebel: |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hallo Emilio,
ich habe die ersten vier Parameter der Berechnungsvorschrift mit den Aufrufwerten verglichen und dann mein Code-Studium wieder eingestellt, weil die für mich schon nicht zusammen passen. Bitte überprüfe deinen Prozeduraufruf gewissenhaft. Bei der Bereitstellung der Eingabe-Parameter-Werte fällt mir auf, dass du die Rechenwerte aus den Anzeigetexten konvertierst - das ist nicht nötig, da die Datenbank-Feldkomponenten Methoden besitzen, mit denen du direkt den Rechenwert erhältst (AsInteger, AsFloat). Wenn du deinen Code in Ordnung gebracht hast, dann gib einen Satz Eingabe-Werte und die erwarteten Ergebnisse an - so ist es leichter den Code zu testen. Ich kann leider nicht erkennen, welche Komponenten sich hinter bestimmten Namen verbergen (cxLookupCombo1). Gute Nacht marabu |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hi Marabu,
sorry - ich check's wirklich nicht - kannst Du mir schreiben, was aus Deiner Sicht nicht zusammenpasst? Vielleicht entdecke ich dann des Pudels Kern. Möglicherweise hilft diese Beschreibung: Der User gibt einen Wert in cxTextEdit1 (DEVExpress-Kompo) ein = ekneu; wählt dann einen Zuschlagsatz aus der cxLookupCombobox1 aus = zuschlag; Daraus errechnet sich über die Funktion/Vorschrift f_bpneu der Wert bpneu. Alle folgenden Werte bauen auf dem ekneu und den "alten" Werten aus der Datenbank auf. Nachdem ich jetzt bei der Fehlersuche alle anderen Funktionen auskommentiert habe, stelle ich fest, dass auch dieser erste Schritt schon nicht funktioniert (Ergebnis = 0). Möglicherweise ist der Aufruf falsch, wenngleich er mit Deinem Beispiel übereinstimmt. Da mir die von Dir freundlicherweise angebotene Lösug vom Verfahren her (noch) fremd ist, tue ich mich verdammt schwer den Fehler zu finden. VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hi Emilio !
Zitat:
Auch dort musst Du den Datentyp auf Extended ändern. Bei grösseren Anwendungen hat es sich sehr bewährt eine eigene Unit für alle Typdeklarationen, GlobalVariable und Konstanten zu erstellen. Dort könntest Du zB. definieren
Delphi-Quellcode:
und dann weiter
type
TMyFloat:Extended;
Delphi-Quellcode:
soll der Datentyp später geändert werden, muss dies nur an einer Stelle geschehen.
...
var BruttoLVPAlt, MargeEAlt:TMyFloat; ... Zu deinem Berechnungsproblem: Ziemlich komplexe Sache, schlage eine objektorientiertere Lösung vor. Kapsle die ganze Berechnung in ein Objekt und statte es mit properties aus. Dadurch vermeidest du auch die enorme Anzahl an Parametern. Überlege auch, ob es nicht sinnvoll wäre, die Daten in einem Record zusammenzufassen. Ich denke dass Du auf dem derzeitigen Weg nur schwer weiterkommst. :gruebel: Edit: Codebeispiel
Delphi-Quellcode:
Du könntest auf diese Art sogar eine Berechnungskomponente erstellen.
interface
type TMyFloat = Double; TBerechnung = class private FAltEK, FAltBP, FAltVP:TMyFloat; FNeuEK, FNeuBP, FNeuVP:TMyFloat; //... procedure SetNeuBP(const Value: TMyFloat); procedure SetNeuEK(const Value: TMyFloat); procedure SetNeuVP(const Value: TMyFloat); //... protected procedure Recalculate; public property AltEK:TMyFloat read FAltEK write FAltEK; property AltBP:TMyFloat read FAltBP write FAltBP; property AltVP:TMyFloat read FAltVP write FAltVP; property NeuEK:TMyFloat read FNeuEK write SetNeuEK; property NeuBP:TMyFloat read FNeuBP write SetNeuBP; property NeuVP:TMyFloat read FNeuVP write SetNeuVP; //... end; implementation { TBerechnung } procedure TBerechnung.Recalculate; begin // hier die Berechnungen durchführen // nur die privaten (F...) variablen setzen - nicht die Properties // würde sonst unerwünschte Rekursion ergeben, die mit einer // Variablen wie zB: Updating abgefangen werden müsste end; procedure TBerechnung.SetNeuBP(const Value: TMyFloat); begin if FNeuBP = Value then exit; FNeuBP := Value; Recalculate; end; procedure TBerechnung.SetNeuEK(const Value: TMyFloat); begin if FNeuEK = Value then exit; FNeuEK := Value; Recalculate; end; procedure TBerechnung.SetNeuVP(const Value: TMyFloat); begin if FNeuVP = Value then exit; FNeuVP := Value; Recalculate; end; |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hi Ferber,
wow, das hört sich massiv an. Beim ersten Aufruf Deines Beitrags hab ich Dein Code-Beispiel nicht gesehen und dachte gleich, dass das ne Nummer zu hoch für mich ist; so siehts aber schon etwas machbarer für mich aus - Danke! Hm, Wien soll ja ne schöne Stadt sein; hättest Du im Prinzip mal Interesse und Zeit an Nachhilfe-Unterricht? VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
@Ferber,
welch unglückliche Formulierung! - Ich meinte selbstverständlich Nachhilfe zu geben ! VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hi Emilio !
Hab das Codebeispiel auch erst im Edit angehängt. Ganz verstehe ich das, was Du mit der Nachhilfe meinst, nicht. :stupid: Hier im Forum bekommen wir doch alle 'Nachhilfe', wenn's mal nicht weitergeht. VG Ferber :) PS: Um meine Zeit ist's leider schlecht bestellt, muss mich um meine Firma kümmern. |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
@Ferber,
Betr.: Nachhilfe: habe nebenbei auch eine Compnay zu managen und ebenso ein permanentes Zeitproblem. Tatsächlich aber wäre ich bereit Zeit und Geld in gezielte Hilfestellung für mein Projekt zu investieren, da es mich schlussendlich entlasten soll. Zurück zum Thema: habe aus meinem Code alles rausgeworfen, bis auf den ersten Rechenschritt - und siehe da, das Ergebnis von BP ist "0" und der Compiler meldet, dass der Wert der Funktion f_bpneu nie verwendet wird ??? Teufel und die Axt! Ich bin drauf und dran nachma ganz von vorne zu beginnen. Hast Du ne Idee? VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hallo Emilio, nur zur Erinnerung:
Zitat:
|
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hi Marabu,
eigentlich ist es egal, welchen Eingabewert für diese Procedure nimmt. Aber trotzdem ekneu = StroFloat(cxTextEdit1.Text) = 1000,00 dann sollte [ekaender] errechnet werden, als OnEditChange in cxTextEdit1 (da das Ergebnis von [ekaender] auf der Form1 in der Zeile von EKAlt und ekneu steht. EKalt = 1200,00 Also [ekaender] = ((ekneu/EKAlt)-1)*100 = -16,67 dann wählt man aus der cxCombobox1 einen zuschlagsatz [zuschlag] aus z.B.: 10 Also [bpneu] = ekneu+(ekneu*zuschlag/100) = 1100,00 [bpaender] ist dann wie bei [ekaender] ((bpneu/BPAlt)-1)*100. Als Vorschlag für den Wert [lvpneu] ist die Formel ekneu/55*100 hinterlegt [lvpaender] ist dann wiederum lvpneu/LVPAlt usw. Solange ich alles in einer Unit behalte und nicht in eine "CalcRule" packe (d.h. Funktionen im interface-Abschnitt deklariert, alle Werte mit denen gerechnet wird als Variablen im Implementation-Abschnitt ganz oben, funktioniert alles prima. Also habe ich vermutlich bei der Umsetzung Deines Vorschlags einen Aufruffehler verbaut (der u.a. bewirkt, dass die Variablen nicht initialisiert werden), den ich nicht finde. Dennoch würde ich gerne die Trennung in 2 Units bevorzugen, da es übersichtlicher und sicher nützlicher ist, da ja der User auch einen lvpneu( neuer Verkaufspreis) und eine margeprozneu (Marge in % vom neuen Verkaufspreis) als Basisdaten eingeben möchte und alle anderen Felder errechnet werden sollen. Ich werde jetzt den Code in der UnitMain so fertigmachen und dann den Versuch mit der Trennung neu starten. Falls Du den Fehler finden solltest - ich freu mich riesig auf Deine Antwort! VG Emilio by the wy: deutsch ist eine furchtbar umständliche Sprache! |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Emilio, es ist eigentlich nicht egal - aber da du beim Aufruf der Berechnungsvorschrift ganz fundamentale Fehler machst, ist es auch wieder egal.
Eine gewissenhafte Überprüfung deines Codes hat folgendes zu Tage gefördert:
Delphi-Quellcode:
Wie du unschwer erkennen kannst, übergibst du die falschen Argumente für die festgelegten Parameter. Wenn du das in Ordnung gebracht hast, dann schreibe in der dritten Spalte unter Beispiel noch die Eingabewerte, mit denen ich testen kann. Ohne konkrete Testdaten mag ich nicht.
CalcRule01(
// argument parameter beispiel // --------------- ---------------- ------------- ekneu, // EKalt bpneu, // EKneu 1000,00 lvpneu, // BPalt margeEneu, // LVPalt margeprozneu, // BruttoLVPalt provlvpneu, // MargeEAlt bruttolvpneu, // MargeProzAlt ekaender, // ProvLVPAlt bpaender, // MwSt lvpaender, // ProvSatz bruttolvpaender, // zuschlag // var margeEaender, // bpneu margeprozaender, // lvpneu provlvpaender, // bruttolvpneu EKAlt, // margeEneu BPALT, // margeprozneu LVPAlt, // provlvpneu BruttoLVPAlt, // ekaender MargeEAlt, // bpaender MargeProzAlt, // lvpaender ProvLVPAlt, // bruttolvpaender MwSt, // margeEaender ProvSatz, // margeprozaender zuschlag // provlvpaender ); Freundliche Grüße vom marabu |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hi Marabu und Emilio !
Das Problem interessiert mich deshalb, weil ich ähnlichen Themenkreis programmiere. Habe untersucht was rein und was rausgehen soll, und das tabellarisch dargestellt.
Delphi-Quellcode:
Die Neu...-Varaiblen sollen ja Ein/Ausgabe-Felder werden, was sie ja bisher noch nicht sind,
Nur als Quellcode weils da so schön untereinander steht
Rein : AltEK, AltBP, AltLVP, AltLVPBrutto, AltMarge, AltMargeProz, AltLVPProv, MwSt, ProvSatz, Zuschlag Raus : AendEK, AendBP, AendLVP, AendLVPBrutto, AendMarge, AendMargeProz, AendLVPProv Raus/Rein: NeuEK, NeuBP, NeuLVP, NeuLVPBrutto, NeuMarge, NeuMargeProz, NeuLVPProv und dann wird das eigentliche Dilemma erst beginnen, da ja die übrigen Felder aktualisiert werden müssen. @Emilio: Du wirst um das Objektorientierte und Properties IMHO nicht herumkommen. Beispielsweise sollten ja alle Neu...-Variablen auf den Wert der Alt-Variablen initialisiert werden. Beim Verändern einzelner Neu...-Werte mussen unterschiedlichste Berechnungen durchgeführt werden. Schlimm wirds besonders dann, wenn noch die Änderungsfelder Ein/Ausgabefelder werden sollen. Na viel Spass :mrgreen: |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hallo Otto,
warum willst du ein rein funktionales Problem unbedingt objekt-orientiert angehen? Hast du dir schon überlegt, wie du deinen Beispiel-Code so erweiterst, dass er benutzerdefinierte Zielgrößen berücksichtigt? Freundliche Grüße vom marabu |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hi @all,
so funzt es, wenn alles in der UnitMain untergebracht ist:
Delphi-Quellcode:
unschön ist noch : interface ... procedure DBLookupComboBox1CloseUp(Sender: TObject); procedure cxTextEdit1KeyPress(Sender: TObject; var Key: Char); procedure cxLookupComboBox1PropertiesCloseUp(Sender: TObject); function f_bpneu(ekneu: Extended; zuschlag: Extended): Extended; function f_ekaender(ekneu: Extended; EKAlt: Extended): Extended; function f_bpaender(bpneu: Extended; BPAlt: Extended): Extended; function f_lvpneu(ekneu: Extended): Extended; function f_lvpaender(lvpneu: Extended; LVPAlt: Extended): Extended; function f_bruttolvpneu(lvpneu: Extended; MwSt: Extended): Extended; function f_bruttolvpaender(bruttolvpneu: Extended; BruttoLVPAlt: Extended): Extended; function f_margeEneu(ekneu: Extended; lvpneu: Extended): Extended; function f_margeEaender(margeEneu: Extended; MargeEAlt: Extended): Extended; function f_margeprozneu(ekneu: Extended; lvpneu: Extended): Extended; function f_margeprozaender(margeEneu: Extended; MargeEAlt: Extended): Extended; function f_provlvpneu(bpneu: Extended; lvpneu: Extended; ProvSatz: Extended): Extended; function f_provlvpaender(provlvpneu: Extended; ProvLVPAlt: Extended): Extended; ... implementation var ekneu, zuschlag, bpneu, EKAlt, ekaender, BPAlt, bpaender, lvpneu, LVPAlt, lvpaender, bruttolvpneu, MwSt, BruttoLVPAlt, bruttolvpaender, margeEneu, MargeEAlt, margeEaender, margeprozneu, margeprozaender, provlvpneu, ProvSatz, provlvpaender, ProvLVPAlt : Extended; ... function TForm1.f_bpneu(ekneu: Extended; zuschlag: Extended): Extended; begin Result := ekneu + (ekneu * zuschlag / 100); end; function TForm1.f_ekaender(ekneu: Extended; EKAlt: Extended):Extended; begin Result := ((ekneu/EKAlt)-1)*100; end; function TForm1.f_bpaender(bpneu:Extended; BPAlt: Extended):Extended; begin Result := ((bpneu/BPAlt)-1)*100; end; function TForm1.f_lvpneu(ekneu: Extended):Extended; begin Result := ekneu/55*100; end; function TForm1.f_lvpaender(lvpneu: Extended; LVPAlt: Extended): Extended; begin Result := lvpneu-LVPAlt; end; function TForm1.f_bruttolvpneu(lvpneu: Extended; MwSt: Extended): Extended; begin Result := lvpneu + (lvpneu*MwSt/100); end; function TForm1.f_bruttolvpaender(bruttolvpneu: Extended; BruttoLVPAlt: Extended):Extended; begin Result := ((bruttolvpneu/BruttoLVPAlt)-1)*100; end; function TForm1.f_margeEneu(ekneu: Extended; lvpneu: Extended): Extended; begin Result := lvpneu-ekneu; end; Function TForm1.f_margeEaender(margeEneu: Extended; MargeEAlt: Extended): Extended; begin Result := margeEneu-MArgeEAlt; end; Function TForm1.f_margeprozneu(ekneu: Extended; lvpneu: Extended): Extended; begin Result := (1-(ekneu/lvpneu))*100; end; function TForm1.f_margeprozaender(margeEneu: Extended; MargeEAlt: Extended): Extended; begin Result :=((margeEneu/MargeEAlt)-1)*100; end; function TForm1.f_provlvpneu(bpneu: Extended; lvpneu: Extended; ProvSatz: Extended): Extended; begin Result := (lvpneu-bpneu)*ProvSatz/100; end; function TForm1.f_provlvpaender(provlvpneu: Extended; ProvLVPAlt: Extended): Extended; begin Result := ((provlvpneu/ProvLVPAlt)-1)*100; end; procedure TForm1.cxLookupComboBox1PropertiesCloseUp(Sender: TObject); begin Beispielwerte ekneu := StrToFloat(cxTextEdit1.Text); 1000,00 zuschlag := StrToFloat(cxLookupComboBox1.Text); 10,00 bpneu := f_bpneu(ekneu, zuschlag); 1100,00 EKAlt := qrypli.Fieldbyname('EK').AsFloat; 900,00 ekaender := f_ekaender(ekneu, EKalt); 11,11 (%) BPAlt := qrypli.Fieldbyname('BP').AsFloat; 980,00 bpaender := f_bpaender(bpneu, BPAlt); 12,24 (%) lvpneu := f_lvpneu(ekneu); 1818,18 LVPAlt := qrypli.Fieldbyname('LVP').AsFloat; 1600,00 lvpaender := f_lvpaender(lvpneu, LVPAlt); 218,18 MwSt := qrypli.Fieldbyname('MwStSatz').AsFloat; 16,00 bruttolvpneu := f_bruttolvpneu(lvpneu, MwSt); 2109,09 BruttoLVPAlt := qrypli.Fieldbyname('BruttoLVP').AsFloat; 1856,00 bruttolvpaender := f_bruttolvpaender(bruttolvpneu, BruttoLVPAlt); 13,64 (%) margeEneu := f_margeEneu(ekneu, lvpneu); 818,18 MargeEAlt := qrypli.Fieldbyname('MARGE').AsFloat; 700,00 margeEaender := f_margeEaender(margeEneu, MargeEAlt); 118,18 margeprozneu := f_margeprozneu(ekneu, lvpneu); 45,00 (%) margeprozaender := f_margeprozaender(margeEneu, MargeEAlt); 16,88 (%) ProvSatz := qrypli.Fieldbyname('PSatz').AsFloat; 5,00 provlvpneu := f_provlvpneu(bpneu, lvpneu, ProvSatz); 35,91 ProvLVPAlt := qrypli.Fieldbyname('ProvLVP').AsFloat; 31,00 provlvpaender := f_provlvpaender(provlvpneu, ProvLVPAlt); 15,84 (%) cxTextEdit1.Text := Format('%8.2f', [ekneu]); cxLabel14.Caption := Format('EUR ' + '%8.2f', [bpneu]); cxLabel15.Caption := Format('%4.2f', [ekaender]) + '%'; cxLabel18.Caption := Format('%4.2f', [bpaender]) + '%'; cxTextEdit5.Text := Format('EUR ' + '%8.2f', [lvpneu]); cxLabel19.Caption := Format('%m', [lvpaender]); cxTextEdit4.Text := Format('EUR ' + '%8.2f', [bruttolvpneu]); cxLabel24.Caption := Format('%4.2f', [bruttolvpaender]) + '%'; cxTextEdit2.Text := Format('EUR ' + '%8.2f', [margeEneu]); cxLabel25.Caption := Format('%m', [margeEaender]); cxTextEdit3.Text := Format('%5.2f', [margeprozneu]) + '%'; cxLabel26.Caption := Format('%4.2f', [margeprozaender]) + '%'; cxTextEdit6.Text := Format('EUR ' + '%8.2f', [provlvpneu]); cxLabel27.Caption := Format('%4.2f', [provlvpaender]) + '%'; - das Feld cxTextEdit1, in welches der ekneu vom user eingetragen wird, sollte nach dem Eintragen formatiert werden ('EUR' + '%8.2f'); krieg ich aber(noch) nicht hin, da ich diesen Wert ja roh brauche. - der Wert [ekaender] sollte besser als OnChange- oder OnEditValueChanged-Event(in cxTextEdit1) erscheinen - also aus der Combobox-procedure raus - krieg ich auch noch hin ... jetzt kommt's: Wie bereits erwähnt, kann es sein, dass der User mit dem lvpneu nicht einverstanden ist und diesen überschreibt. Dann sollten sich 10 Werte ändern (alle außer (ekneu), (bpneu), (ekaender), [bpaender]). Womöglich will er aber auch eine "fixe" Marge vorgeben und nur einen lvpneu ... Also ich erkenne die Anforderungen, den Kram aufzusplitten als notwendig an. Als erstes versuche ich jetzt den Code so umzustricken, dass er dem Beispiel von Marabu folgt und ich erkenne was ich im ersten Anlauf versaubeutelt habe. Der Saft sei mit mir! VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
:party: :dancer: :cheers: Es funzt!!!
Hi Marabu, hi Ferber, mit ordentlich Konzentration und reichlich Kaffee habe ich es geschafft, das Beispiel von Marabu richtig zu übersetzen - keine Warnhinweise, keine Fehlermeldungen und alle Eregebnisse da und richtig - freu! @Marabu, gehe ich richtig in der Annahme, dass ich für die anderen bereits erwähnten Möglichkeiten (also User hat andere Ausgangswerte als den neuen EK oder will Anpassungen überdie EditFelder vornehmen) weitere CalcRules erstelle oder wäre das zu einfach ...? @Ferber, wenngleich Marabu Deinen Vorschlag für 'unangemessen' hält, könntest Du Deinen Weg etwas weiter ausführen? Schönes Wochenende und vielen herzlichen Dank für Eure Hilfe VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
sorry, bitte löschen...
|
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Zitat:
Sorry - was löschen ? |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Hallo Emilio,
Zitat:
Zur Verdeutlichung ein einfaches Beispiel: Ein Quader hat drei Seiten (a,b, und c) und ein Volumen V. Aus jeweils drei Eingabewerten lässt sich der vierte berechnen. Es ergeben sich vier triviale Rechenvorschriften. Trivial, weil alle Vorschriften nur von Konstanten abhängig sind:
Freundliche Grüße vom marabu |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Liste der Anhänge anzeigen (Anzahl: 2)
Ja, manchmal kann das ziemlich komplex werden.
Nachdem ich das Ganze überschlafen hab dachte ich mir schon, dass der OO-Ansatz doch ein 'mit Kanonen auf Spatzen schiessen' ist. :? Eine grosse Mühsal ist halt die ganze Herumformatiererei. Ich hab deshalb in meinem Komponentenfundus gekramt, was gefunden, und Überarbeitet. Dabei hab ich natürlich ersteinmal alles Kaputtgemacht :stupid: bevor's wieder gelaufen ist, aber jetzt haben die Edits auch Label (von BDS abgespranzt). Natürlich bin ich nachher draufgekommen dass ich den falschen Vorfahren erwischt habe, sollte vielleicht endlich mal zumindest auf D7 umsteigen, aber so funzts wenigstens auch in D5. Es ist ein Set von EditKomponenten, die weit mehr können als TEdit. Vor allem gibt's die Eigenschaft 'Value', die direkt zugewiesen werden kann, der Text wird Formatiert. Ich stell das hier als Open-Source herein, bitte ausprobieren und testen. Ein Testbeispiel ist auch dabei. Liebe Grüsse vom 'Ferber' :coder: |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
@Marabu,
Zitat:
Es gibt ingesamt 5 Edit-Felder in die der User Werte eingeben könnte (ekneu, lvpneu, bruttolvpneu, MargeE und Marge%). Der ekneu kann z.B. über 3 Wege zustande kommen: - User-Eintrag im ekneu Edit-Feld - User-Eintrag im lvpneu-Feld und MargeE- oder Marge%-Feld (Berechnung) - User-Eintrag im bruttolvpneu-Feld und MargeE- oder Marge%-Feld (Berechnung) der lvp kann z.B. über 5 Wege zustande kommen: - User-Eintrag im lvpneu Edit-Feld - User-Eintrag im ekneu-Feld + Auswahl des zuschlag aus der Combobox (Auto-Vorschlag wie in CalcRule01) - User-Eintrag im bruttolvp-Feld (Berechnung) - User-Eintrag im ekneu-Feld und MargeE- oder Marge%-Feld (Berechnung) - User-Eintrag im bruttolvpneu-Feld und MargeE- oder Marge%-Feld (Berechnung) Die 7 Werte, welche die Änderungen neu gegen Alt ausdrücken (ekaender, xyaender, etc.) werden eigentlich immer dann benötigt, wenn zum passenden Alt-Wert ein neu-Wert eingegeben oder errechnet und angezeigt wird. Mit den genannten Wegen decke ich jedoch nur die "primär"-Eingabe ab; Nicht erfasst sind Änderungen, die der User nach der Primär-Eingabe vornehmen möchte (z.B. den bruttolvpneu runden/glätten, die Marge prozentual anpassen, etc.). Das hieße, nach der Ergänzung des Codes für die primär-Eingaben noch 7 onChange-Events mit unterschiedlichen "Calcrules" bauen - oder nicht? Irgendwie werde ich das Gefühl nicht los, dass ich das bisherige Konstrukt zerfleddern muß, um den User-Wünschen gerecht zu werden. Ich grübel weiter. Falls jemand noch 'n Tipp hat - ich freue mich! VG Emilio |
Re: komplexe Berechnungen von abhängigen Datenbankfeldern
Das Thema ist ja ein richtiger Dauerbrenner - :coder:
Zitat:
@Emilio: Stell Dir nun vor, Du müsstest das Ganze nur in 7 Formeln kleiden, die alle anderen Variablen berechnen. Falls Du auch der Meinung bist, dass das simpel ist, dann schau doch endlich meine Komponenten an ! Das sind quasi Variablen, die Dir den ganzen restlichen Schnickschnack abnehmen. Nenne diese zB. EKNeu und verwende sie als EKNeu.Value. Kurzbeschreibung aus den Units herauskopiert:
Delphi-Quellcode:
Edit: Die Komponenten gibts hier:
{ Unit MyEditPrim erweitert das etwas dümmliche TLabeledEdit um Eigenschaften und Ereignisse,
die in der Praxis des Programmierens IMHO notwendig sind. TEditPrim ist Vorfahre für weitere, spezialisiertere EditKomponenten (siehe Unit MyEdit) Erweiterungen: property Alignment Ausrichtung des Textes taLeftJustify, taCenter, taRightJustify property RedValues Negative Werte werden rot dargestellt property ReturnIsTab Eingabetaste ist wie Tab property OnChange Änderung des Verhaltens. Wird nur durch Enter, Tab oder Verlassen des Edits ausgelöst, nicht mehr bei jeder Zeichneingabe, und auch dann nur, falls der Wert geändert wurde. Validierung der Eingabe möglich. property OnIniData Wird Aufgerufen um Variablen mit Value belegen zu können. property OnDrwData Wird vor dem Zeichnen aufgerufen und erlaubt Änderungen von Farbe und Font Taste ESC stellt den ursprünglichen Wert des Feldes wieder her. } { unit MyEdit leitet vom erweiterten TEditPrim, die spezialisierten Editfelder TEditString, TEditInteger, TEditFloat, TEditCurr, TEditProz und TEditDate ab. Basisverhalten siehe: Unit MyEditPrim. Jedes diese Editfelder hat die zusätzliche Eigenschaft 'Value', die dem DatenTyp entspricht. Nachkommastellen bei den entsprechend Datentypen sind einstellbar. Vorgabe bei Float und Currency: 2, bei Prozent: 0 Zuweisungen zur Eigenschaft Value lösen das Ereignis OnChange NICHT aus. Zuweisungen zur Eigenschaft Text lösen das Ereignis OnChange nach wie vor aus. Zusätzliche Eigenschaft NullValues - wie Excel Nullwerte anzeigen, Vorgabe false. Zusätzliches Ereignis OnInitData ermöglicht das initialisieren von Variablen. Validierung kann im Ereignis OnChange durchgeführt werden. TEditPrim wurde in separate Unit extrahiert, um die Übersichtlichkeit zu erhöhen. Die Erweiterung um weitere Datentypen ist in Unit MyEdit sehr einfach. } ![]() Mit freundlichen Grüssen, Otto. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:27 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