Link to home
Start Free TrialLog in
Avatar of ISIGest
ISIGestFlag for Italy

asked on

Mask Edit delphi for discount

Hi,
I want to have a TEditMask to insert this values:
10+5+3
10+5
10%
-10

how I can do this?
Avatar of Emmanuel PASQUIER
Emmanuel PASQUIER
Flag of France image

With a TEditMask ???

Not possible. Obviously the many formats that you want to be able to edit are not compatible

But with a normal TEdit, you could well analyse the text and detect operators '+' /  '-'  and do operations, and pretty much the same for %
Avatar of jimyX
jimyX

You can use the following but each line is separately set you can't have one mask for all of them at once:

!90+9+9;1;_           //_ the gap sign

!90%;1;_

-!90;1;_
That should do the trick :

ShowMessageFmt('Formula [%s] = %f', [ edtFormula.Text , GetSimpleFormulaValue( edtFormula.Text ) ] );

of course, that will not validate fully the mathematical syntax of the formula, it is well possible to accept formulas that are not valid, or return results not exactly correct. For example :
' 200 + 10%' will return 210% = 2,10 , so neither 200,1 which would be the correct mathematical result not 220% which would be what most regular guy wait ( 200 + 10% of 200 )

Function GetSimpleFormulaValue(F:String):Double;
 function FindOper(Ops:String):Integer;
 begin
  for Result:=1 to Length(F) do if Pos(F[Result],Ops)>0 Then Exit;
  Result:=0;
 end; 
   
 procedure DoOper(ValStr:String);
 begin
  ValStr:=Trim(ValStr);
  if ValStr='' Then Exit;
  Val:=StrToFloat(ValStr);
  Case Op of
   '+':Result:=Result+Val;
   '-':Result:=Result-Val;
   '%':Result:=Result/100;
  end;
 end; 
Var 
 P:Integer;
 Val:Double;
 Op:Char;
begin
 Result:=0;
 Op:='+';
 try
  Repeat
   P:=FindOper('+-%');
   if P>0 Then
    begin
     DoOper(LeftStr(F,P-1));
     Op:=F[P];
     F:=Copy(F,P+1,Length(F)); 
    end;
  Until P=0;
  DoOper(F);
 except
  Raise Exception.Create('Invalid Formula :'+F);
 end;  
end;

Open in new window

Avatar of ISIGest

ASKER

When an user insert text like:  
------
10+5+3 is not a mathematical formula but a custom differten value.
10+5+3 is a cascade discount then like: 10% + 5% + 3% that in my TDataSet is stored in 3 separated fields Discount1, Discount2 and Discount3.
------
10% is like 10+5+3 but only the first discount that stored only in field "Discount1"
------
-10 is a value discount that stored in other field named "DiscountValue"

the mask edit is a SemiCalculated field the display and edit this possible values.

I hope I was clear.
what about that then :
!90%+9%+9%;1;_

that way, only the first value HAVE to be set. But you can't manage easily the -10 (fixed value) AND those % edit with a same maskedit, or you would end up with such a mask that it would be of no use, and simpler for users to have a plain TEdit that YOU control the syntax upon validation


What do you mean ? I did not get your point clearly.

If you mean -10%+-5%+-3% then here it is:
#99%+#9%+#9%;1;_

If you want it all positive 10%+5%+3%, then:
99%+9%+9%;1;_
JimyX : the point is that the discount can be set in 2 ways :
- by percentage, where 1 to 3 %age values can be added.
Atomic syntax : all positive values with "%" suffix, separated by "+"

- by fixed value, where only ONE NEGATIVE value is entered
I don't think using masked edit with such an input is a good idea.

Let the user input what he can and validate, TMaskEdit is not pretty with complex input
Function ValidateEntry(S:String):Boolean;
Var
 V:Double;
 i:integer;
 DiscA:Array[0..2] of Double; 
 L:TStringList;
begin
 if TryStrToFloat(S,V) Then
  begin
   DiscountValue:=V;
   Result:=True;
   Exit;
  end;
 L:=TStringList.Create;
 try
  L.Delimiter:='+';
  L.DelimitedText:=S;
  for i:=0 to 2 do
   begin
    if i<L.Count 
     Then DiscA[i]:=StrToFloat(Trim(StringReplace(L[i],'%','',[rfReplaceAll])))
     Else DiscA[i]:=0;
   end;  
  Discount1:=DiscA[0];
  Discount2:=DiscA[1];
  Discount3:=DiscA[2];
 except
  Result:=False;
 end;
 L.Free;
end;

Open in new window

in the first case (string is simple numeric value), you can check if V<0, and if it is not , 2 choices :
- you consider it is always a fixed value, but should be considered negative
- if the value is <100, consider it is a percentage value

so , entering "10" could be interpreted either as "-10" or "10% discount" , as you see fit
if the input is limited to a specific set :

just use a combobox with the possible entries

a lot easier ...
You might present them with a combobox control that states what kind of data they want to enter and then set the mask based on their selection.

You could let them enter the text without a mask and then apply different RegEx masks to see which one is most applicable/valid.

This UI problem stems from the multiple possible uses of a single control.  
> combo + dynamic mask edit
In that direction, one would even not present a single field for the 3 %age values, but 3 fields.
that would be what a "normal" programmer would do, because it fills the functionality needs and simplify the input validation.
but it is also not very clear for the user to have 2 or 4 fields.

> This UI problem stems from the multiple possible uses of a single control.

I perfectly understand where ISIGest needs come from...

I have some Retail users that WANT that kind of entry because that simplify the interface in a crowded screen (invoice input). That is just a major pain in the @$$ from a developer point of view, and the usability is relative, but for an unknown reason that is what cashiers are used to...

The only way to do it properly is then to custom-validate the entry
ASKER CERTIFIED SOLUTION
Avatar of Ephraim Wangoya
Ephraim Wangoya
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial