Solved

Mask Edit delphi for discount

Posted on 2010-11-24
13
971 Views
Last Modified: 2012-05-10
Hi,
I want to have a TEditMask to insert this values:
10+5+3
10+5
10%
-10

how I can do this?
0
Comment
Question by:ISIGest
13 Comments
 
LVL 25

Expert Comment

by:epasquier
ID: 34204735
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 %
0
 
LVL 24

Expert Comment

by:jimyX
ID: 34204819
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;_
0
 
LVL 25

Expert Comment

by:epasquier
ID: 34204909
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

0
 

Author Comment

by:ISIGest
ID: 34205361
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.
0
 
LVL 25

Expert Comment

by:epasquier
ID: 34205461
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


0
 
LVL 24

Expert Comment

by:jimyX
ID: 34205600
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;_
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 25

Expert Comment

by:epasquier
ID: 34205648
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
0
 
LVL 25

Expert Comment

by:epasquier
ID: 34205761
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

0
 
LVL 25

Expert Comment

by:epasquier
ID: 34205787
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
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 34206134
if the input is limited to a specific set :

just use a combobox with the possible entries

a lot easier ...
0
 
LVL 45

Expert Comment

by:aikimark
ID: 34206785
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.  
0
 
LVL 25

Expert Comment

by:epasquier
ID: 34206974
> 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
0
 
LVL 32

Accepted Solution

by:
ewangoya earned 250 total points
ID: 34210871

Have you considered using three edit boxes, not the most ideal but might solve your problem.
Put them next to each other and remove the borders, or leave the borders

Here is a simple example
unit Unit3;



interface



uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, ComCtrls, StdCtrls, ExtCtrls;



type

  TForm3 = class(TForm)

    Panel1: TPanel;

    edtDiscount1: TEdit;

    edtDiscount2: TEdit;

    edtDiscount3: TEdit;

    procedure edtDiscount1KeyPress(Sender: TObject; var Key: Char);

    procedure edtDiscount2KeyPress(Sender: TObject; var Key: Char);

    procedure edtDiscount3KeyPress(Sender: TObject; var Key: Char);

  private

    function CountOf(AChar: Char; const AValue: string): Integer;

    procedure DisableEdits(AEdits: array of TEdit; AClear: Boolean = True);

    procedure EnableEdits(AEdits: array of TEdit);

  end;



var

  Form3: TForm3;



implementation



{$R *.dfm}



function TForm3.CountOf(AChar: Char; const AValue: string): Integer;

var

  I: Integer;

begin

  Result := 0;

  for I := 1 to Length(AValue) do

    if AChar = AValue[I] then

      Inc(Result);

end;



procedure TForm3.DisableEdits(AEdits: array of TEdit; AClear: Boolean);

var

  I: Integer;

begin

  for I := 0 to Length(AEdits) -1 do

  begin

    AEdits[I].Enabled := False;

    if AClear then

      AEdits[I].Text := '';

  end;

end;



procedure TForm3.edtDiscount1KeyPress(Sender: TObject; var Key: Char);

var

  S: string;

begin

  S := (Sender as TEdit).Text;

  if (Pos('-', S) > 0) or (Pos('%', S) > 0) then

    EnableEdits([edtDiscount2, edtDiscount3]);



  case Key of

    '0'..'9':

    begin

      if (Length(S) > 1) and (S[1] <> '-') then

        Key := #0

    end;

    '-':

    begin

      if Length(S) > 0 then

        Key := #0

      else

        DisableEdits([edtDiscount2, edtDiscount3]);

    end;

    '%':

    begin

      if (CountOf(Key, S) > 1) or (Pos('%', S) > 1) then

        Key := #0

      else

        DisableEdits([edtDiscount2, edtDiscount3]);

    end;

    '+':

    begin

      if (CountOf(Key, S) > 1) or (Pos('+', S) = 1) then

        Key := #0

      else

      begin

        edtDiscount2.SetFocus;

        edtDiscount2.SelectAll;

      end;

    end;

    #8, #27: ;

    else

      Key := #0

  end;

end;



procedure TForm3.edtDiscount2KeyPress(Sender: TObject; var Key: Char);

var

  S: string;

begin

  EnableEdits([edtDiscount3]);

  S := (Sender as TEdit).Text;

  case Key of

    '0'..'9':

    begin

      if Length(S) > 1 then

        Key := #0

    end;

    '+':

    begin

      if (CountOf(Key, S) > 1) or (Pos('+', S) = 1) then

        Key := #0

      else

      begin

        edtDiscount3.SetFocus;

        edtDiscount3.SelectAll;

      end;

    end;

    #8:

    begin

      if Length(S) <= 1 then

      begin

        edtDiscount1.SetFocus;

        edtDiscount1.SelectAll;

      end;

    end;

    #27, #127: ;

    else

      Key := #0

  end;

end;



procedure TForm3.edtDiscount3KeyPress(Sender: TObject; var Key: Char);

var

  S: string;

begin

  S := (Sender as TEdit).Text;

  case Key of

    '0'..'9':

    begin

      if Length(S) > 1 then

        Key := #0

    end;

    #8:

    begin

      if Length(S) <= 1 then

      begin

        edtDiscount2.SetFocus;

        edtDiscount2.SelectAll;

      end;

    end;

    #27, #127: ;

    else

      Key := #0

  end;

end;



procedure TForm3.EnableEdits(AEdits: array of TEdit);

var

  I: Integer;

begin

  for I := 0 to Length(AEdits) -1 do

    AEdits[I].Enabled := True;

end;



end.



//

object Form3: TForm3

  Left = 0

  Top = 0

  Caption = 'Form3'

  ClientHeight = 73

  ClientWidth = 245

  Color = clBtnFace

  Font.Charset = DEFAULT_CHARSET

  Font.Color = clWindowText

  Font.Height = -11

  Font.Name = 'Tahoma'

  Font.Style = []

  OldCreateOrder = False

  PixelsPerInch = 96

  TextHeight = 13

  object Panel1: TPanel

    Left = 24

    Top = 24

    Width = 185

    Height = 28

    BevelInner = bvLowered

    Color = clWhite

    ParentBackground = False

    TabOrder = 0

    object edtDiscount1: TEdit

      Left = 4

      Top = 3

      Width = 22

      Height = 21

      BevelInner = bvNone

      BevelOuter = bvNone

      BorderStyle = bsNone

      TabOrder = 0

      OnKeyPress = edtDiscount1KeyPress

    end

    object edtDiscount2: TEdit

      Left = 29

      Top = 3

      Width = 22

      Height = 21

      BevelInner = bvNone

      BevelOuter = bvNone

      BorderStyle = bsNone

      TabOrder = 1

      OnKeyPress = edtDiscount2KeyPress

    end

    object edtDiscount3: TEdit

      Left = 55

      Top = 3

      Width = 25

      Height = 21

      BevelInner = bvNone

      BevelOuter = bvNone

      BorderStyle = bsNone

      TabOrder = 2

      OnKeyPress = edtDiscount3KeyPress

    end

  end

end

Open in new window

0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video discusses moving either the default database or any database to a new volume.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now