delphi cxgrid restrict characters - delphi

We are working in Delphi 2006 with devexpress.
We have a cxGrid.
We want to restrict the entry of values for a number column, integers between 0 and 999.
If I set the property type to a SpinEdit the initial value is always 0 which is unwanted.
So I left the property value on the column null and set the datatype on the databinding of the column to Smallint. That works for the most part but an 'e' and '.' and '+' and '-' can still be entered into the column which causes exceptions.
Is some simple way to exclude the 'e' and '.' and '+' and '-' from being entered into the column?

The initial 0 Value can be prevented by setting UseNullString to true.
The input of unwanted characters can handled by
procedure TForm1.ViewEditKeyPress(Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem;
AEdit: TcxCustomEdit; var Key: Char);
begin
if AItem = TheColumnWithSpinEdit then
if (not (Key in ['0'..'9',#8])) then Key := #0;
end;

Related

Paradox BCD field - Number is out of Range error

I'm attempting to update an old Paradox (BDE) table using an older Delphi XE6 application. One particular table has two fields; a Date field, and a BCD field. I'm unable to post a new record to the (FuelSurch) table due to the BCD (FuelSur) field which is throwing a "Number is out of range" error.
So I wrote a quick test, but still the same issue. Here are the FuelSurch table field specifications.
I just added a button to a form and this procedure fires when clicked.
procedure TTestForm.BCDTestBtnClick(Sender: TObject);
var
Bcd: TBcd;
begin
POE_Data.FuelSurch.Open;
POE_Data.FuelSurch.Insert;
Bcd:= StrToBcd('2.01');
showMessage('Bcd = ' + BcdToStr(Bcd)); // This works and shows 'Bcd = 2.01'
POE_Data.FuelSurchFuelSur.AsBCD := Bcd; // Line produces "Number is out of range." error
POE_Data.FuelSurch.Post;
POE_Data.FuelSurch.Close;
end;
The database connection is confirmed as good as I'm able to post to other tables. It just seems like this BCD field type is giving me issues.
Do I need to format the string differently before assigning it to the Bcd variable?
Internally the precision of a BCD is the total number of digits, not the number of digits after the decimal separator.
It's always an even number (when odd, 1 is added to it). The reason is that a byte stores 2 digits.
So if you try this:
procedure TForm1.Button1Click(Sender: TObject);
var
Bcd: TBCD;
begin
Bcd := StrToBcd('2.01', TFormatSettings.Invariant);
ShowMessage(IntToStr(Bcd.Precision));
end;
you will see 4, because 3 digits are used, plus 1 to make it even.
Your field precision is only 2. If it represents the same as TBCD.Precision, it's not enough.
Note that BcdPrecision() returns the number of digits before the decimal separator, which is a bit confusing.

how to avoid spaces in tmaskedit?

Im having an issue with edit box. i need to be able to write positive and negative numbers ( 0.22 included)
i tried tedit numbers only feature but obviously i cant write negative sign. then i found tmaskedit that lets me write possitive and negative numbers but there are spaces and instead of for example 123 i can write 12 3 and get an error.
is there any quick way to solve this problem with spaces in tmaskedit or should i just try to write something with ifs and key presses?
What worked for me was this function right here. and i went back to tedit box because i cant really get rid of spaces in tmaskedit
procedure KeyPressWithDouble(Sender: TObject; var Key: Char);
begin
if not(Key in [#8, '0' .. '9', '-', FormatSettings.DecimalSeparator]) and
not(ord(Key) = VK_RETURN) then
begin
showmessage('Invalid key');
// Discard the key
Key := #0;
end;
end;

OnCalculate field in a table produces too long number

I have such a table in SQLite :
CREATE TABLE [TABLE1] (
[T_ID] INTEGER PRIMARY KEY ON CONFLICT IGNORE AUTOINCREMENT,
[DATE] DATE UNIQUE ON CONFLICT IGNORE,
[FIELD1] INTEGER,
[FIELD2] INTEGER,
[FIELD3] INTEGER,
[FIELD4] REAL);
I added a 2 new calculated fields to the TABLE1
called SUM1 (integer) and SUM2 (float).
procedure TForm3.UniTable1CalcFields(DataSet: TDataSet);
begin
UNITable1.Fields.FieldByName('SUM1').asInteger := (UNITable1.Fields.FieldByName('FIELD1').AsInteger) + (UNITable1.Fields.FieldByName('FIELD2').AsInteger) + (UNITable1.Fields.FieldByName('FIELD3').AsInteger);
UNITable1.Fields.FieldByName('SUM2').asFloat := (UNITable1.Fields.FieldByName('SUM1').AsInteger) / (UNITable1.Fields.FieldByName('FIELD4').AsInteger) ;
end;
This kind of works but I am having trouble vwith SUM2 displaying a 15 digit number.
I would like to display a number with only two decimals like 5,81.
I could do it in the cxGrid by setting the properties of the field to CalcEdit and set Precision to 3.
But I am wondering can this be done in code.
Is there a way I can accomplish this ?
Well 314 / 54 is 5.814814814814... . If you are using persistent fields you can set the DisplayFormat to ',0.00;; '
or in code:
TNumericField(UNITable1.Fields.FieldByName('SUM2')).DisplayFormat := ',0.00;; ';
Another option is to use the FormatFloat('0.00',myvariable) function.
'0.00' defines the format (2 decimal places), and myvariable is an aptly named variable.
The only drawbacks are that it requires an extra few lines of code to declare and assign a value to the variable, and if you wish to use this value for further calculations, the accuracy will be lower than the original floating point number you had.
procedure TForm3.UniTable1CalcFields(DataSet: TDataSet);
var
var1: real;
begin
//Assign the floating point value to the variable
var1 := (UNITable1.Fields.FieldByName('SUM1').AsInteger) / (UNITable1.Fields.FieldByName('FIELD4').AsInteger);
UNITable1.Fields.FieldByName('SUM1').asInteger := UNITable1.Fields.FieldByName('FIELD1').AsInteger) + (UNITable1.Fields.FieldByName('FIELD2').AsInteger) + (UNITable1.Fields.FieldByName('FIELD3').AsInteger);
UNITable1.Fields.FieldByName('SUM2').AsFloat := FormatFloat('0.00',var1);
end;
i haven't had a chance to test this, but the basic idea would be something along these lines.

Delphi Edit Text Integer: Minus Sign Error

Hi I am very beginner for Delphi.
But what confuses me is that I have Edit1.Text
and variable "i" which uses StrToInt(Edit1.Text);
Everything is Ok until I type minus sign
If I copy/paste minus with number (eg -2) it works
Can Anyone help me!
Regards, Umar
The StrToInt conversion function is unsafe to use when you're not 100% sure the input string can be converted to an integer value. And the edit box is such an unsafe case. Your conversion failed because you've entered as a first char the - sign that cannot be converted to integer. The same would happen to you also when you clear the edit box. To make this conversion safe, you can use the TryStrToInt function, which handles the conversion exceptions for you. You can use it this way:
procedure TForm1.Edit1Change(Sender: TObject);
var
I: Integer;
begin
// if this function call returns True, the conversion succeeded;
// when False, the input string couldn't be converted to integer
if TryStrToInt(Edit1.Text, I) then
begin
// the conversion succeeded, so you can work
// with the I variable here as you need
I := I + 1;
ShowMessage('Entered value incremented by 1 equals to: ' + IntToStr(I));
end;
end;
You get an error, obviously, because - is not an integer. You can use TryStrToInt instead.

How to change decimal separator for numeric key in my Delphi application?

In my country the decimal separator is ",". One of my clients would like to have it as a "." character. What should I do to change decimal separator to "."?
I've tried this:
procedure TfrmMain.FormCreate(Sender: TObject);
begin
DecimalSeparator := '.';
Application.UpdateFormatSettings := True;
end;
But this code helps only partialy. I see the "." in gird in float fields. However, when user press on numeric keybord a "." key, the comma is send despite the settings.
This is problem not related to the grid, I've checked this on KeyPress event on the form.
I am using Delphi 2007, thanks for your help.
First of all, you should set UpdateFormatSettings to false! If this property is true, the DecimalSeparator will be reset to the Windows default one every now and then (for instance, every time you lock the workstation (using Win+L) and then unlock it again). The default value is true, so you need to set it to false when you want to override DecimalSeparator.
Secondly, the DecimalSeparator is used by Delphi routines when formatting floating-point numbers as strings (e.g. when using FloatToStr or FormatFloat). To make the decimal separator key on the numeric keypad result in a point (.) and not the OS default character (which is probably either . or ,), you can handle the OnKeyPress event:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if Key = ',' then
Key := '.'
end;
But be cautious - this will replace all , with ., even those inserted by the comma key on the alphabetical part of the keyboard.
A more advanced (and safer) method is to handle the OnKeyDown event like this:
procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
msg: TMsg;
begin
if Key = VK_DECIMAL then
begin
PeekMessage(msg, Edit1.Handle, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE);
SendMessage(Edit1.Handle, WM_CHAR, ord('.'), 0);
end;
end;
What char this key maps to isn't determined by Delphi, but by the keyboard layout set in windows.
One hack would be simply replacing , by . in the OnKeyPress handler.
Else you need to somehow modify the Translation of the KeyDown/Up messages to the key press messages, but I don't know how to do that.
The Translation from virtual keys to chars happens in TranslateMessage http://msdn.microsoft.com/en-us/library/ms644955(VS.85).aspx
So you could check the message passed in to TranslateMessage beforehand, check if it is the virtual decimal key on the numpad and then pass in a different virtual key. But everything you can do is pretty hackish.

Resources