Recent

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

heebiejeebies

  • New Member
  • *
  • Posts: 27
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!  :)
Ubuntu 18.04/Lazarus 2.0.10 FPC 3.2.0

jamie

  • Hero Member
  • *****
  • Posts: 4439
Re: Strings to numbers and whatnot
« Reply #1 on: March 16, 2021, 01:36:22 am »
You can implement the OnKeyDown where you could just reject a unwanted key.


BUt I think you are looking for something you better understand...

using the VAL function/Procedure, what ever it is you perform the conversion and determine if there is an error..

VaL(Edit.Text, TheOUtputInteger, CodeError);;


CodeError will point to where in the string the error was...

if there is no error then CodeError will be 0 in which case the value that was returned in the "TheOutputInteger" is valid...

From that, you can test the scale of it...


----

 You could also use the TRY ….. Except … END operation to capture the error but it will only work at without debugging because the error dialog will still popup...

That should give you some insight.
The only true wisdom is knowing you know nothing

josh

  • Hero Member
  • *****
  • Posts: 827
Re: Strings to numbers and whatnot
« Reply #2 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.  
Development Installation Lazarus 1.3, FPC 2.7.1,Windows 7/8 32/64, OSX, *nix

Test Environment Lazarus & FPC Trunk on Windows and OSX (Cocoa Mainly on OSX). Testing also Crosscompile windows to OSX.. 
Any posts made from 2015 will be based on Lazarus Trunk.

Zvoni

  • Hero Member
  • *****
  • Posts: 544
Re: Strings to numbers and whatnot
« Reply #3 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 IDE to find them,
One Code to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
People call me crazy, because i'm jumping out of perfectly fine aircraft

circular

  • Hero Member
  • *****
  • Posts: 3703
    • Personal webpage
Re: Strings to numbers and whatnot
« Reply #4 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

  • New Member
  • *
  • Posts: 18
Re: Strings to numbers and whatnot
« Reply #5 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: 544
Re: Strings to numbers and whatnot
« Reply #6 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 IDE to find them,
One Code to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
People call me crazy, because i'm jumping out of perfectly fine aircraft

circular

  • Hero Member
  • *****
  • Posts: 3703
    • Personal webpage
Re: Strings to numbers and whatnot
« Reply #7 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

  • New Member
  • *
  • Posts: 27
Re: Strings to numbers and whatnot
« Reply #8 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  :)
Ubuntu 18.04/Lazarus 2.0.10 FPC 3.2.0

josh

  • Hero Member
  • *****
  • Posts: 827
Re: Strings to numbers and whatnot
« Reply #9 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 »
Development Installation Lazarus 1.3, FPC 2.7.1,Windows 7/8 32/64, OSX, *nix

Test Environment Lazarus & FPC Trunk on Windows and OSX (Cocoa Mainly on OSX). Testing also Crosscompile windows to OSX.. 
Any posts made from 2015 will be based on Lazarus Trunk.

Bart

  • Hero Member
  • *****
  • Posts: 4238
    • Bart en Mariska's Webstek
Re: Strings to numbers and whatnot
« Reply #10 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: 544
Re: Strings to numbers and whatnot
« Reply #11 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 IDE to find them,
One Code to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
People call me crazy, because i'm jumping out of perfectly fine aircraft

heebiejeebies

  • New Member
  • *
  • Posts: 27
Re: Strings to numbers and whatnot
« Reply #12 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
Ubuntu 18.04/Lazarus 2.0.10 FPC 3.2.0

Thaddy

  • Hero Member
  • *****
  • Posts: 10778
Re: Strings to numbers and whatnot
« Reply #13 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.

 

TinyPortal © 2005-2018