Since adding EurekaLog to APK I’ve been able to track down the causes of some perplexing errors.
“X is not a valid floating point value”, this error has puzzled me for years. I have actually never seen it myself in 15+ years of using the program. I am only aware of it because of scattered reports from users.
As usual, it is the user causing the error. Instead of entering a valid decimal value, ie, [1.02], they accidentally add a decimal point or two: [1.02.] or [1..02], etc. This error has cropped up twice in only 30 reports. I never would have imagined that someone would do something so fundamentally wrong. I also believe that it is impossible to imagine every possible scenario of software usage. I think it would take a troop of monkeys randomly pounding on multiple keyboards to approximate the myriad of potential mistakes.
Regardless, any software program must be able to prevent a user’s dumb mistake from causing a fatal error. All of the input boxes for numeric values in APK are coupled to procedures to prevent non-numeric input:
procedure TfrmMain.EditRecentSCrKeyPress(Sender: TObject; var Key: Char);
if not (Key in ['0'..'9', DecimalSep, #8]) then
Key := #0;
However, that’s not enough. I was under the impression that the StrToFloat function was fault tolerant, i.e., if the input was wrong, it would output a zero.
if EditRecentSCr.Text <> '' then
RecentSCr := StrToFloat(EditRecentSCr.Text);
Unfortunately that’s not true. Instead, execution is halted with a fatal error and the program crashes.
The little known expression SysUtils.TryStrToFloat does have fault tolerance.
if EditRecentSCr.Text <> '' then
if RecentSCr <= 0 then begin ValidPatData := False; MessageDlg('Data entry error', 'Serum creatinine is a required field.', mtError, [mbOK], 100, dckActiveForm); EditRecentSCr.SetFocus; Exit; end;
Alternatively one can test the boolean result of TryStrToFloat within an if..then block to flag an error:
if TryStrToFloat(EditKel.Text, KelSD) = False then
IsOkay := False;
ErrMsg := 'Kel SD';
So, I've spent the better part of 3 days re-coding all the StrToFloat calls to TryStrToFloat (also StrToInt -> TryStrToInt). And I've been able to prevent fatal errors.
I feel that the EurekaLog dialog doesn't really fit this situation. I'd rather catch the error, display a dialog, and rollback the edit which produced the error. But I've hit a brick wall, unable to get to the event triggering the error. I've tried BeforePost, PostError, BeforeEdit, and EditError, none of these events are trapped when a db field is edited. In the case of database fields it appears that no event is triggered. WTF!?
Another error that EurekaLog discovered is "unable to save settings". The most fundamental requirement for use of this program is to have full read and write privileges to the APK folder. Without that, you can't really use the software. Again, regardless, any software program should not allow a user's dumb mistake to cause a fatal error. So, I combed through all code, and surrounded all ini writes in try..try..finally..except blocks:
UserIni := TIniFile.Create(AppDataPath + 'screen.ini');
UserIni.WriteInteger('Window Placement', 'Main.Top', frmMain.Top);
UserIni.WriteInteger('Window Placement', 'Main.Left', frmMain.Left);
on E:Exception do
MessageDlg('Error saving window placement',
mtError, [mbOK], 690, dckActiveForm);
Action := caFree;
The other common error that I've addressed in this update is "range check error". Unfortunately there are not enough reports to establish a pattern, so I simply switched off range error checking. Within the compiler settings, range error checking is turned off by default. I only switched it on because some Delphi guru advised it. Well, sorry guru, in the end your advice caused more problems than it solved.
Today I figured out how to bypass the EurekaLog dialog for the EDatabaseError 'not a valid floating point value':
- Activated Exception Filters in the EurekaLog options
- Added EDatabaseError
- Changed handler to RLT