| Autor |
Beitrag |
Chaosworld
      
Beiträge: 49
|
Verfasst: Di 04.04.06 00:39
Ich habe eine Datenbankanwendung geschrieben für ein chemisches Laboratorium. Ich habe als Teil dessen ein Feld "Formel" in der Parametertabelle erstellt. Die Formeln sehen dann z.B. so aus:
("Rohproteingehalt"-"Bindegewebseiweiß")*100/"Rohproteingehalt"
ich speicher die Formel so:
(#1#-#2#)*100/#1#
wobei die # immer die Nummer des Parameters darstellt
hier ist also
Parameter 1 = Rohproteingehalt und 2 = Bindegewebseiweiß
Die komplette Berechnung klappt auch soweit ohne Probleme (auch komplexere Formeln mit Pozenzen, log,..)
Nun kann keiner wirklich die Formel (#1#-#2#)*100/#1# verstehen. Daher würde ich sie gerne anders darstellen.
Es ist kein Problem die Formel so umzuwandeln, dass z.B. in dem Fall #1# durch "Rohproteingehalt" ersetzt wird. Jedoch könnte man die so erstellte Formel kaum bearbeiten.
Meine Idee ist es nun, dass ich irgendwie ziehbare, feste Objekte erstellt
also so:
(A-B)*100/C
wobei bei A, B und C halt ein Text steht, den ich aber nicht bearbeiten kann, sondern nur komplett löschen kann, oder mit der Maus verschieben kann.
Als für den Anwender soll es zwar so aussehen
("Rohproteingehalt"-"Bindegewebseiweiß")*100/"Rohproteingehalt"
aber es ist nicht möglich aus "Rohproteingehalt" z.B. einfach das "ein" rauszulöschen.
Ich muss nur sagen, dass ich überhaubt keine Idee habe, wie man so etwas realisieren könnte. Mir würden ja schon Hinweise helfen, und welchem Stichpunkt ich vielleicht Informationen finden könnte, um so etwas zu erreichen.
Bin echt für jeden Tipp dankbar, ich selber habe keinerlei Idee und könnte es höchstens mit einer Funktion machen, die die Formel leserlicher macht, aber diese wäre dann nicht mehr bearbeitbar (auf jedenfall nicht so, dass sie eine formel in der Datenbank ergibt, die ich dann an anderer Stelle auch verwenden könnte um den Wert der sich aus der Formel ergibt zu berechnen.
Im vorraus vielen dank für jede Antwort
|
|
Simon Joker
      
Beiträge: 236
Erhaltene Danke: 1
|
Verfasst: Di 04.04.06 11:56
Hi Chaosworld
Chaosworld hat folgendes geschrieben: |
("Rohproteingehalt"-"Bindegewebseiweiß")*100/"Rohproteingehalt"
aber es ist nicht möglich aus "Rohproteingehalt" z.B. einfach das "ein" rauszulöschen. |
Reine Vorgehensweise:
beim KeyEvent
Suche ausgehend von der Cursorposition recht und links die Zeichen ".
Prüfe ob Cursor innerhalb eines Objekts ist.
wenn ja und (key = "Delete" oder "BackSpace")
Setzte die Markierung (SelStart & SelLength) auf die Grenzen und lösche alles.
wenn ja und (key = "Sichtbares Zeichen")
drop Key (Key = #0)
Das wäre die einfachste Lösung. Benutzerfreundlicher wäre sowas wie die Code-vervollständigung von Delphi.
MfG Simon
|
|
Chaosworld 
      
Beiträge: 49
|
Verfasst: Di 04.04.06 15:29
danke für deine Antwort, also dass mit dem KeyEvent würde wahrscheinlich Probleme machen, da ich dass ja irgendwie zurück zu der berechenbaren Formel zurück verwandeln müsste. Ausserdem kann man ja mit der Maus in den Text gehen. Ich denke das wäre am ende nicht wirklich sehr hilfreich.
Das mit der Idee von der art Code-Vervollständigung hört sich gut an, frage ist, weisst du wie ich das mache?
Im vorraus vielen dank
Chaosworld
|
|
Chaosworld 
      
Beiträge: 49
|
Verfasst: Di 04.04.06 18:24
Also ich habe hier
synedit.sourceforge.net
eine Komponente gefunden, die die Vervollständigung ermöglicht. Aber dennoch wäre da noch das Problem mit dem automatisch makieren und des nur komplett löschen, selbst wenn man mit der Mause manuell innerhalb ein Element rein klickt.
MFG
Chaosworld
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Di 04.04.06 23:29
Hallo,
Chaosworld hat folgendes geschrieben: | | ...Aber dennoch wäre da noch das Problem mit dem automatisch makieren und des nur komplett löschen, selbst wenn man mit der Mause manuell innerhalb ein Element rein klickt. |
hab mal etwas Code bezogen auf ein Editfeld geschrieben, ist nicht voll ausgereift, aber sollte ein guter Ansatz zum weiterentwickeln sein.
Inhalt Edit : '( Rohproteingehalt - Bindegewebseiweiß ) * 100 / Rohproteingehalt'
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58:
| function IsElement(MyE: TEdit;x: Integer): Boolean; var z,a,e : Integer; s,sEle : String; begin Result := False; a := 0; s := MyE.Text; e := Length(s)+1; for z := MyE.SelStart downto 1 do if s[z] in ['0'..'9',',','-','*','/','+','(',')',' '] then begin a := z; Break; end; for z := MyE.SelStart + x to Length(s) do if s[z] in ['0'..'9',',','-','*','/','+','(',')',' '] then begin e := z; Break; end; sEle := Copy(s,a+1,e-a-1); if Pos(sEle,'Rohproteingehalt,Bindegewebseiweiß') <> 0 then begin MyE.SelStart := a; MyE.SelLength := e-a-1; Result := True; end; end;
procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin case key of VK_Left : if Edit1.SelLength > 0 then Edit1.SelStart := Edit1.SelStart+1 else if IsElement(Edit1,0) then key := 0; VK_Right : if Edit1.SelLength > 0 then begin Edit1.SelStart := Edit1.SelStart+Edit1.SelLength; key := 0; end else if Edit1.SelStart < Length(Edit1.Text) then if not (Edit1.Text[Edit1.SelStart+1] in ['0'..'9',',','-','*','/','+','(',')',' ']) then if IsElement(Edit1,1) then key := 0; VK_Up,VK_Down : key := 0; end; end;
procedure TForm1.Edit1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Edit1.SelStart <> Length(Edit1.Text) then IsElement(Edit1,0); end; |
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
bnessler
      
Beiträge: 36
alle Win's , suse u. Ubuntu Linux
Delphi1,2,4,5,7,2005, Java (Eclipse), C++,C#, (VS2005)
|
Verfasst: Mi 05.04.06 08:26
Hallo,
ein anderer Ansatz wäre die Formeln dynamisch in mehrere Editfelder aufzuteilen,
in Parameterfelder und Operatorenfelder, dann automatisch die entsprechenden Properties für die Feldart zu vergeben.
Allerdings muss es dann zum Ergänzen/Ändern einer Formel Möglichkeiten geben, wie
z.B. Parameterfeld hinzufügen oder Operatorenfeld hinzufügen. Dort wäre dann aber wiederum eine einfache Möglichkeit gegeben die möglichen Eingaben zu kontrollieren bzw. vorzugeben.
Gruß
Bernhard
|
|
Simon Joker
      
Beiträge: 236
Erhaltene Danke: 1
|
Verfasst: Mi 05.04.06 14:48
Ok es ist nicht trivial, aber auch nicht unmöglich.
Formatierungen habe ich nicht verwendet, sind aber auch kein Problem.
Ich bin mir ziemlich sicher, das ich nicht alle Fehler getilgt habe, aber dennoch viel Spass damit.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249:
| unit UnitMain;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls;
type TFormMain = class(TForm) CodeMemo: TRichEdit; ListBoxObjects: TListBox; Label1: TLabel; Label2: TLabel; GroupBox1: TGroupBox; EditObjName: TEdit; Label3: TLabel; EditObjDesc: TEdit; Label4: TLabel; ButtonAddObj: TButton; ButtonDelObj: TButton; ListBoxAutoComplete: TListBox; function GetWordOnCursor(RichEdit: TRichEdit;AutoSelect:boolean): string; procedure CodeMemoKeyPress(Sender: TObject; var Key: Char); procedure CodeMemoMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure CodeMemoKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure CodeMemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure CodeMemoProtectChange(Sender: TObject; StartPos, EndPos: Integer; var AllowChange: Boolean); procedure FormCreate(Sender: TObject); procedure CodeMemoChange(Sender: TObject); procedure ButtonAddObjClick(Sender: TObject); procedure ButtonDelObjClick(Sender: TObject); private public ObjectWord:string; isObjectWord : boolean; DoChange : boolean; EditOK : boolean; procedure FillQuickList(FillQuickList:string); end;
var FormMain: TFormMain;
implementation
{$R *.dfm}
function TFormMain.GetWordOnCursor(RichEdit: TRichEdit;AutoSelect:boolean): string; var i, j: Integer; s: string; begin result := ''; with RichEdit do begin s := Text; i := SelStart; while (i > 0) and (s[i] <> '"') and (s[i] <> ' ') and (s[i] <> #10) and (s[i] <> #13) do Dec(i); j := SelStart + 1; while (j <= Length(s)) and (s[j] <> '"') and (s[j] <> ' ') and (s[j] <> #10) and (s[j] <> #13) do Inc(j); result := Copy(s, i+1, j - i-1); isObjectWord := false; if (s[i] = '"') and (s[j] = '"') then begin ObjectWord := result; isObjectWord := true; if AutoSelect then begin SelStart := i; SelLength := Length(result); end; end else begin result := ''; end; end; end;
procedure TFormMain.FillQuickList(FillQuickList:string); var i:integer; ObjektName:string; begin ListBoxAutoComplete.Items.Clear; if isObjectWord then begin for i:=0 to ListBoxObjects.Items.Count-1 do begin ObjektName := ListBoxObjects.Items.Values[ListBoxObjects.Items.Names[i]]; if UpperCase(copy(ObjektName,1,length(ObjectWord))) = UpperCase(ObjectWord) then ListBoxAutoComplete.Items.Add(ObjektName); end; if ListBoxAutoComplete.Items.Count > 0 then ListBoxAutoComplete.ItemIndex := 0; end; end;
procedure TFormMain.CodeMemoMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin DoChange := true; GetWordOnCursor(CodeMemo,true); FillQuickList(ObjectWord); DoChange := false; end;
procedure TFormMain.CodeMemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var EditString :string; begin DoChange := true; if (key in [38,40]) and (ObjectWord <> '') then begin if ListBoxAutoComplete.Items.Count > 1 then begin if (key = 38) and (ListBoxAutoComplete.ItemIndex > 0) then ListBoxAutoComplete.ItemIndex := ListBoxAutoComplete.ItemIndex-1; if (key = 40) and (ListBoxAutoComplete.ItemIndex < ListBoxAutoComplete.Items.Count -1) then ListBoxAutoComplete.ItemIndex := ListBoxAutoComplete.ItemIndex+1; end; key := 0; end; if key in [65..90,46,8,13] then EditOK := true; if key = 8 then begin EditString := CodeMemo.Text; if EditString[CodeMemo.SelStart] = '"' then begin CodeMemo.SelStart := CodeMemo.SelStart-1; GetWordOnCursor(CodeMemo,true); CodeMemo.SelStart := CodeMemo.SelStart-1; CodeMemo.SelLength := length(ObjectWord)+2; end; end; if key = 46 then begin end; DoChange := false; end;
procedure TFormMain.CodeMemoKeyPress(Sender: TObject; var Key: Char); var EditString :string; MemSelStart :integer; begin DoChange := true; if Key = '"' then begin MemSelStart := CodeMemo.SelStart; EditString := CodeMemo.Text; insert('"',EditString,CodeMemo.SelStart+1); CodeMemo.Text := EditString; CodeMemo.SelStart := MemSelStart; CodeMemo.SelLength := 0; end; if Key = #13 then key := #0; DoChange := false; end;
procedure TFormMain.CodeMemoKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); var EditString :string; MemSelStart :integer; begin DoChange := true; if key in [37] then begin CodeMemo.SelStart := CodeMemo.SelStart -1; GetWordOnCursor(CodeMemo,true); end; if key in [39] then begin CodeMemo.SelStart := CodeMemo.SelStart + CodeMemo.SelLength+1; GetWordOnCursor(CodeMemo,true); end; if key in [38,40] then GetWordOnCursor(CodeMemo,true); if key in [65..90,46,8] then begin MemSelStart := CodeMemo.SelStart; GetWordOnCursor(CodeMemo,false); if isObjectWord then begin FillQuickList(ObjectWord); CodeMemo.SelStart := MemSelStart; end; end; if (key in [13]) and (ObjectWord <> '') and (ListBoxAutoComplete.ItemIndex <> -1) then begin MemSelStart := CodeMemo.SelStart; GetWordOnCursor(CodeMemo,true); EditString := CodeMemo.Text; delete(EditString,CodeMemo.SelStart+1,length(ObjectWord)); insert(ListBoxAutoComplete.Items[ListBoxAutoComplete.ItemIndex],EditString,CodeMemo.SelStart+1); CodeMemo.Text := EditString; CodeMemo.SelStart := MemSelStart; GetWordOnCursor(CodeMemo,true); key := 0; end; DoChange := false; end;
procedure TFormMain.CodeMemoProtectChange(Sender: TObject; StartPos, EndPos: Integer; var AllowChange: Boolean); begin AllowChange := EditOK; if not isObjectWord then AllowChange := true; EditOK := false; end;
procedure TFormMain.FormCreate(Sender: TObject); begin CodeMemo.DefAttributes.Protected := true; ObjectWord := ''; isObjectWord := false; DoChange := false; EditOK := false; end;
procedure TFormMain.CodeMemoChange(Sender: TObject); begin if (not isObjectWord) and (GetWordOnCursor(CodeMemo,false) <> '') then CodeMemo.Undo; end;
procedure TFormMain.ButtonAddObjClick(Sender: TObject); begin ListBoxObjects.Items.Add(EditObjName.Text+'='+EditObjDesc.Text); end;
procedure TFormMain.ButtonDelObjClick(Sender: TObject); begin if ListBoxObjects.ItemIndex <> -1 then ListBoxObjects.Items.Delete(ListBoxObjects.ItemIndex); end;
end. |
Einloggen, um Attachments anzusehen!
Für diesen Beitrag haben gedankt: FURIOS
|
|
Chaosworld 
      
Beiträge: 49
|
Verfasst: Mi 05.04.06 14:54
Danke für eure antworten
@Lannes&Simon Joker
die Lösung werde ich gleich ausprobieren / durchdenken, ob dass was bringt
@bnessler
Deine lösung hört sich interessant an, nur wie meinst du dass mit dynamisch? Kann ich mir irgendwie noch nichts drunter vorstellen
Auf jeden Fall danke für eure ganzen Antworten
Habe jetzt erst einmal einiges zum testen, melde mich noch mal, sobald ich dass alles durch bin
Chaosworld
|
|
bnessler
      
Beiträge: 36
alle Win's , suse u. Ubuntu Linux
Delphi1,2,4,5,7,2005, Java (Eclipse), C++,C#, (VS2005)
|
Verfasst: Mi 05.04.06 15:05
Hallo,
dynamisch bedeutet in diesem Fall die Editfelder werden zur Laufzeit erzeugt und gegebenenfalls auch wieder gelöscht.
Da Deine Formeln nicht alle gleich lang sind und die Idee darauf beruht pro Parameter/Operator etc. ein Feld zu haben, musst Du entweder die Länge der Formeln begrenzen, oder eben abhängig von der Länge der Formel die Felder dynamisch erstellen.
Gruß
Bernhard
|
|
Chaosworld 
      
Beiträge: 49
|
Verfasst: Mi 05.04.06 15:07
@Simon Joker
Habe mir gerade deine Lösung angesehen, die idee mit dem Protected-Text finde ich klasse, kannte ich noch garnicht. Ich glaube dass ist echt eine super Lösung.
Danke an euch alle für eure Hilfen
Chaosworld
|
|
|