Recent

Author Topic: Strings to numbers and whatnot  (Read 2178 times)

heebiejeebies

  • Full Member
  • ***
  • Posts: 127
Strings to numbers and whatnot
« on: March 16, 2021, 01:16:53 am »
Hi friends,

So I have a TEdit which feeds into another section of my programme and I need to make sure it can only accept numbers 1 - 12, otherwise I'm going to look mighty stupid if some mischievous user puts the number 99 in and it appears elsewhere.

This is what I've got so far, in the Change handler.  The max length of the field is 2, and the first line successfully stops them entering '0', but obviously I don't want to do every other number from 13 - 99.

Code: Pascal  [Select][+][-]
  1. If TVertNumber.Text = '0' then TVertNumber.Text := '';
  2. if (StrToInt(TVertNumber.Text) >12) then TVertNumber.Text :='';  

It compiles, but when you actually enter a number above 12 Lazarus throws his toys out of his cot and says "" is an invalid integer.

And question 2 - what about preventing them from entering letters and other funny characters?  Unfortunately the NumbersOnly property does not work on Ubuntu (bug already reported by others).

Thank you for your kind help!  :)
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

Josh

  • Hero Member
  • *****
  • Posts: 1271
Re: Strings to numbers and whatnot
« Reply #1 on: March 16, 2021, 01:48:05 am »
Hi

If your using the onchange event.
Quick and dirty

Code: Pascal  [Select][+][-]
  1. function IsInRange(const AValue,ALow, AHigh: Integer): Boolean;
  2. begin
  3.   Result := (AValue >= ALow) and (AValue <= AHigh);
  4. end;
  5.  
  6. procedure TForm1.Edit1Change(Sender: TObject);
  7. Var MyValue:LongInt;
  8.     Ok:Boolean;
  9. begin
  10.   If Sender is TEdit then
  11.   Begin
  12.     Ok:=TryStrToInt(TEdit(Sender).Text,MyValue);
  13.     If Ok then
  14.     Begin
  15.       If IsInRange(MyValue,1,12) then Label1.caption:=IntToStr(MyValue)
  16.       else ok:=false;
  17.     end;
  18.     If Ok=false then Label1.caption:='Out of Range';
  19.   end;
  20. end;        
  21.  
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Strings to numbers and whatnot
« Reply #2 on: March 16, 2021, 08:07:18 am »
In the OI set "NumbersOnly" to true, and then as Jamie said, the OnKeyDown-Event with Josh's InRange
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

circular

  • Hero Member
  • *****
  • Posts: 4196
    • Personal webpage
Re: Strings to numbers and whatnot
« Reply #3 on: March 16, 2021, 08:18:15 am »
Good ideas around. It depends if you want an instant update or not.

If you don't need instant update then I suggest to check the value of the TEdit in its OnLeave event:
- at this moment, if the value is not correct, then replace it with its previous value (you need to store it, for example in the OnEnter event).
- after that, you're sure you have an acceptable value to use somewhere else

If you need an instant update, josh's solution is probably the simplest. You can add to it the OnLeave event to restore to the previous value if it wasn't correct.
Conscience is the debugger of the mind

Ally

  • Jr. Member
  • **
  • Posts: 52
Re: Strings to numbers and whatnot
« Reply #4 on: March 16, 2021, 10:12:21 am »
Hi heebiejeebies,

that could be what you are looking for:

https://forum.lazarus.freepascal.org/index.php/topic,53352.msg394615.html#msg394615

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Strings to numbers and whatnot
« Reply #5 on: March 16, 2021, 12:05:45 pm »
Good ideas around. It depends if you want an instant update or not.

If you don't need instant update then I suggest to check the value of the TEdit in its OnLeave event:
- at this moment, if the value is not correct, then replace it with its previous value (you need to store it, for example in the OnEnter event).
- after that, you're sure you have an acceptable value to use somewhere else

If you need an instant update, josh's solution is probably the simplest. You can add to it the OnLeave event to restore to the previous value if it wasn't correct.

Wouldn't do that.
In  the company i work for we had something similiar in the ERP, and it was driving the people mad.
In case of no instant update, i'd rather color the background of the TEdit green/red with of course if red not being able to save
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

circular

  • Hero Member
  • *****
  • Posts: 4196
    • Personal webpage
Re: Strings to numbers and whatnot
« Reply #6 on: March 16, 2021, 01:14:13 pm »
It depends on the context. Sometimes you don't need instant update.
Conscience is the debugger of the mind

heebiejeebies

  • Full Member
  • ***
  • Posts: 127
Re: Strings to numbers and whatnot
« Reply #7 on: March 16, 2021, 01:20:26 pm »
Thanks everyone! Appreciate all the ideas.  Not being a natural programmer, I really struggled to understand some of these ideas but I think Josh's script will do the trick.  :D  The only way I learn anything is by taking things apart and figuring them out - and it's taxing my puny brain to make sense of it but after reading it about 25 times I think I juuuuuuuuuust understand how it works.  :D  Although I don't quite understand why people are concerned about whether I need instant update or not - isn't it pretty much the same method either way, just a question of which event I put the code in?  %)

Anyway, I'll try it tomorrow (in the Change event seems the most logical) and report back if Lazarus throws any more toys out of his cot.  :D

Grazie mille!  As they say in Lichtenstein  :)
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

Josh

  • Hero Member
  • *****
  • Posts: 1271
Re: Strings to numbers and whatnot
« Reply #8 on: March 16, 2021, 02:23:00 pm »
Hi

Attached project, that you may find useful.

You can use the tag property to select the range you wish to use, the ranges are set in in an array; so you can modify/add at will.

you can set the normal and error colors globally; these used when error detected.

It is just a follow on from previous post, but you now have a project to play with. You will notice the same onchange routine is called for each tedit control (using the Tedit(Sender)). The code If Sender is TEdit then is a failsafe, it makes sure that the sending component is actually a tedit; just incase for some reason the event gets called from some other component by mistake.  "catch possible errors and handle them before they happen"

As you pogress; you will learn that you can ceate your own components ( derived from another); this allows you to use a standard component (tedit) but add your extra properties like; min, max, error color; normal color etc as properties for the 'NEW' control, or use 3rd party components

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Edit2: TEdit;
  16.     Edit3: TEdit;
  17.     Edit4: TEdit;
  18.     Edit1: TEdit;
  19.     Label1: TLabel;
  20.     Label2: TLabel;
  21.     Label3: TLabel;
  22.     Label4: TLabel;
  23.     procedure Edit1Change(Sender: TObject);
  24.     procedure FormCreate(Sender: TObject);
  25.   private
  26.  
  27.   public
  28.  
  29.   end;
  30.  
  31.   // a record structure to hold the min and max values
  32.   TMyRange=Record
  33.              Min,Max:LongInt;
  34.            End;
  35.  
  36.  
  37.  
  38. var
  39.   Form1: TForm1;
  40.   // colors for normal and error value
  41.   okcolor:tcolor=clSkyBlue;
  42.   errcolor:tcolor=clred;
  43.   // create array of 3 possible ranges
  44.   MyRanges:Array[1..3] of TMyRange;
  45.  
  46. implementation
  47.  
  48. {$R *.lfm}
  49.  
  50. { TForm1 }
  51.  
  52.  
  53. function IsInRange(const AValue,ALow, AHigh: Integer): Boolean;
  54. begin
  55.   Result := (AValue >= ALow) and (AValue <= AHigh);
  56. end;
  57.  
  58.  
  59. procedure TForm1.Edit1Change(Sender: TObject);
  60. Var MyValue:LongInt;
  61.     Ok:Boolean;
  62. begin
  63.   If Sender is TEdit then
  64.   Begin
  65.     Ok:=TryStrToInt(TEdit(Sender).Text,MyValue);
  66.     If Ok then
  67.     Begin
  68.       // check if tag is used that it is range of available ranges
  69.       if IsInRange(TEdit(Sender).tag,Low(MyRanges),High(MyRanges)) Then
  70.       Begin
  71.         // now check if value is within the ranges of the tag
  72.         If IsInRange(MyValue,MyRanges[TEdit(Sender).tag].Min,MyRanges[TEdit(Sender).tag].max) then tedit(sender).color:=okcolor
  73.         else ok:=false;
  74.       end;
  75.     end;
  76.     If Ok=false then tedit(sender).color:=errcolor;
  77.   end;
  78. end;
  79.  
  80. procedure TForm1.FormCreate(Sender: TObject);
  81. begin
  82.   // Set the Ranges options
  83.   MyRanges[1].Min:=1;
  84.   MyRanges[1].Max:=12;
  85.  
  86.   MyRanges[2].Min:=3;
  87.   MyRanges[2].Max:=100;
  88.  
  89.   MyRanges[3].Min:=101;
  90.   MyRanges[3].Max:=1000;
  91.  
  92.   // setting label text
  93.   label1.Caption:='Tag 0 No Range';
  94.   label2.Caption:='Tag 1 Range '+inttostr(MyRanges[1].Min)+' to '+inttostr(MyRanges[1].Max);
  95.   label3.Caption:='Tag 2 Range '+inttostr(MyRanges[2].Min)+' to '+inttostr(MyRanges[2].Max);
  96.   label4.Caption:='Tag 3 Range '+inttostr(MyRanges[3].Min)+' to '+inttostr(MyRanges[3].Max);
  97.  
  98.  
  99. end;
  100.  
  101. end.
  102.  
« Last Edit: March 16, 2021, 03:07:18 pm by josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Strings to numbers and whatnot
« Reply #9 on: March 16, 2021, 02:42:50 pm »
Use a TSpinEdit and set MinValue to 1, MaxValue to 12.
The property Value is guaranteed to be always in the range MinValue..MaxValue (so 1..12 in your case).
IIRC then you can hide the spinners if so desired.
(If this is not the case for TSpinEdit, then it might be the case for TSpinEditEx, too lazy to look it up right now.)

Bart

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Strings to numbers and whatnot
« Reply #10 on: March 16, 2021, 03:12:33 pm »
*snip* Although I don't quite understand why people are concerned about whether I need instant update or not - isn't it pretty much the same method either way, just a question of which event I put the code in?  *snip*
No, it's not the same.
It has to do with the concept of how to control user-input.
And that is a topic, philosophical wars have been fought over.
It's validating user-input during input vs. validating user-input when user is done and wants to save his/her data.

FWIW, i'm a member of "control the user-input DURING input"
If you have, e.g. 4 mandatory TEdit's, then you'll not get the save-button enabled until you've filled out all mandatory data (in the correct form --> numeric, string, whatever). Period!
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

heebiejeebies

  • Full Member
  • ***
  • Posts: 127
Re: Strings to numbers and whatnot
« Reply #11 on: April 09, 2021, 12:07:39 pm »
Thanks everyone for the additional replies - have been torn away from all programming the last few weeks due to a couple of urgent things but appreciate the effort a lot, thank you.  Will take a proper look at everyone's suggestions very soon.  Thanks again everyone for being so helpful!  This forum is great !!  :D
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Strings to numbers and whatnot
« Reply #12 on: April 09, 2021, 12:42:01 pm »
I am missing InRange and EnsureRange (from the math unit)?
Both have a considerable set of overloads.
Specialize a type, not a var.

 

TinyPortal © 2005-2018