Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

incompatible data types and data conversions 1

Status
Not open for further replies.

Mezzzo

Technical User
May 30, 2003
56
0
0
US
Hi

I really lost on a few issues. I have a application I`m attempting that uses bound controls.
Also, I have a unit that converts all control data from decimal to fractional to millimeters.
I need to write quite a few functions based on the field values of various editboxes. I`m uncertain of the syntax and how to set it up to work with the numerical conversion. I did a bit of code using this code:
procedure TfrmDrw.dbedtTopClearBoxChange(Sender: TObject);
begin
if not (TableControls.State in [dsInsert, dsEdit]) then
TableControls.Edit;
TableControls.fieldbyname('TotalHtClear').asfloat :=
Add2InputNumbers(dbedtTopClearBox, dbedtBotClearBox);
end;

I get errors regarding incompatible data types. I`m certain it relates to the numerical conversions.
This newbie is lost.....I appreciate some guidance from the experts in this forum


numerical conversion unit

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SUIImagePanel, SUIGroupBox, SUIRadioGroup, ExtCtrls, SUIForm,
SUIButton, AdvGrid, BaseGrid, suidbctrls, StdCtrls;
// defines the measure unit codes
const
Imperial = 0;
Fractional = 1;
Metric = 2;
type
TConversionForm = class(TForm)
suiForm1: TsuiForm;
suiRadioGroup1: TsuiRadioGroup;
suiButton1: TsuiButton;
procedure suiButton1Click(Sender: TObject);
procedure Check_fields(To_Notation: integer);
procedure suiRadioGroup1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
ConversionForm: TConversionForm;
ParentForm: TForm;
Current_notation: integer;
implementation

{$R *.dfm}

function metric_to_float(e: string): extended;
var
rc: integer;
r: extended;
begin
{$R-}
val(e, r, rc);
if rc = 0 then
Result := r
else
Result := 0;
{$R+}
end;
// this function convert the string e representing a fractional number eg 1/2 or 1 33/98 to it's real value eg 0.1

function fractional_to_float(e: string): extended;
var
s1, s2, e1: string;
rc, ip: integer;
r, r1: extended;
i: integer;
f: boolean;
begin
{$R-}
e1 := e;
ip := 0;
if (pos(' ', e1) > 1) and (pos(' ', e1) <= Length(e1)) and (e1[(pos(' ', e1))
- 1] in ['0'..'9']) then
begin
s1 := '';
i := 1;
while i < pos(' ', e1) do
begin
s1 := s1 + e1;
i := i + 1;
end;
val(s1, ip, rc);

i := i + 1;
e1 := '';
while (i <= Length(e)) do
begin
e1 := e1 + e;
i := i + 1;
end;

end;

if pos('/', e1) <> 0 then
begin
i := 1;
f := false;
s1 := '';
s2 := '';

while (i <= Length(e1)) and (not f) do
begin
if (e1 <> '/') and (e1 in ['0'..'9']) then
s1 := s1 + e1
else
f := true;
i := i + 1;

end;

while (i <= Length(e1)) do
begin
s2 := s2 + e1;
i := i + 1;
end;

if (s2 <> '') and (s1 <> '') and (f) then
begin
val(s1, r, rc);
if (rc = 0) and (r <> 0) then
begin

val(s2, r1, rc);
if (rc = 0) and (r1 <> 0) then
begin
if ip < 0 then
Result := ip - (r / r1)
else
Result := ip + (r / r1)
end
else
Result := ip;
end
else
Result := ip

end
else
Result := ip
end
else
begin
if pos(' ', e) = 0 then
Result := strtoint(e)
else
Result := ip
end;

{$R+}
end;
// this function converts real number eg 1.5 to it's fractional representation 1 1/2

function fractional_to_str(r: extended): string;
var
v1, v2, c, ip: int64;
v3: extended;
i: integer;
s1, s2: string;
function cmmdc(a, b: int64): longint;
var
r, a1, b1: longint;
begin
if a > b then
begin
a1 := b;
b1 := a;
end
else
begin
a1 := a;
b1 := b;
end;
repeat
r := a1 mod b1;
a1 := b1;
b1 := r;
until r = 0;
cmmdc := a1;
end;
function RoundN(x: extended;d: integer): extended;
const
t: array[0..12] of int64 = (1, 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000, 1000000000, 10000000000,
100000000000, 1000000000000);
begin
if Abs(d) < 12 then
begin
if d = 0 then
Result := Int(x) + Int(Frac(x) * 2)
else if d > 0 then
begin
x := x * t[d];
Result := (Int(x) + Int(Frac(x) * 2)) / t[d];
end
else
begin
x := x / t[-d];
Result := (Int(x) + Int(Frac(x) * 2)) * t[-d];
end;
end
else
Result := x;

end;

begin
s1 := '';
s2 := '';
if r = 0 then
Result := '0'
else
begin
i := 0;
v2 := 1;
v3 := RoundN(r, 5);
while (i <= 5) and (trunc(v3) <> v3) do
begin
v2 := v2 * 10;
v3 := v3 * 10;
i := i + 1;
end;
v1 := trunc(v3);
c := cmmdc(v1, v2);
v1 := v1 div c;
v2 := v2 div c;
ip := v1 div v2;
v1 := v1 mod v2;
if ip = 0 then
begin
if v1 <> 0 then
Result := inttostr(v1) + '/' + inttostr(v2)
else
Result := '0';
end
else
begin
if v1 <> 0 then
Result := inttostr(ip) + ' ' + inttostr(Abs(v1)) + '/' +
inttostr(Abs(v2))
else
Result := inttostr(ip);
end;

end;
end;

//////////////////////////////////////
// this function loops every fiel in the pafent form and makes the conversion
//

procedure TConversionForm.Check_fields(To_Notation: integer);
var
col_, row_: integer;
index_: integer;
change: tsuidbedit;
sg: TAdvStringGrid;
// this function changes the notation suitem af a field
function change_notation(s: string;from_, to_: integer): string;
var
e: extended;
begin

e := 0;
Result := '0';
case from_ of
Imperial:
begin
try
e := StrToFloat(s);
except e := 0;
end;
end;
Metric:
begin
try
e := StrToFloat(s) / 25.4;
except e := 0;
end;
end;
Fractional: e := fractional_to_float(s);
end;
// e := (round(e * 1000)) / 1000;
case to_ of
Imperial: Result := Floattostr(e);
Metric: Result := Floattostr(e * 25.4);
Fractional: Result := fractional_to_str(e);
end;

end;
begin
// each component on the parent form it's looped
for index_ := 0 to ParentForm.ComponentCount - 1 do
begin
// if the component it's a tsuidbedit then
if ParentForm.Components[index_] is tsuidbedit then
begin
// assign that component
change := ParentForm.Components[index_] as tsuidbedit;
// check for tag 3=must be changed
if (change.Tag = 3) and (change.text <> '') then
begin
// do the change
change.text := change_notation(change.text,
Current_notation, To_Notation);
end;
end;
// if the component it's a TAdvStringGridthen
if ParentForm.Components[index_] is TAdvStringGrid then
begin
// assign that component
sg := ParentForm.Components[index_] as TAdvStringGrid;
// check if tag=3 then must be changed
if sg.Tag = 3 then
begin
// loops every cell
for row_ := 1 to sg.RowCount - 1 do
for col_ := 0 to sg.ColCount - 1 do
// if cell not empty and coll number is in [5..8] interval then do the change
// * note the decision can be changed to a &quot;if (sg.Cells[col_, 1]='Width') or (sg.Cells[col_, 1]='Length') ..etc then&quot;
// * this way if the header of the column is &quot;Width&quot; all collumns from a stringgrids with tag=3 will be converted
// * replacing &quot;for col_ := 0 to sg.ColCount - 1 do&quot; with &quot;for col_ := 5 to 8 do&quot;
// * it's not corect! It mai generate errors if the number of columns <8

if (sg.Cells[col_, row_] <> '') and (col_ in [5..8])
then
// do the change
sg.Cells[col_, row_] :=
change_notation(sg.Cells[col_, row_],
Current_notation, To_Notation);
end;
end;

end;
// set's the curent notation sistem
Current_notation := To_Notation;
end;

procedure TConversionForm.suiButton1Click(Sender: TObject);
begin
ConversionForm.Hide;
end;

procedure TConversionForm.suiRadioGroup1Click(Sender: TObject);
begin
Check_fields(suiRadioGroup1.ItemIndex);
end;

procedure TConversionForm.FormCreate(Sender: TObject);
begin

Left := (Screen.Width - Width) div 2;
Top := (Screen.Height - Height) div 2;
end;
begin
Current_notation := Imperial;

end.
 
Hi
Thanks for taking a interest in my problem. Here are
the functions. I hope this info is helpful.

Thanks


function Add2InputNumbers(EditA, EditB: TsuiDBEdit): Double;
begin
try
if EditA.text = '' then
EditA.text := '0';
//this eliminates errors if the user clears the edtbox
if EditB.text = '' then
EditB.text := '0';
Result := StrToFloat(EditA.Text) + StrToFloat(EditB.Text);
except
result := 0
end;
end; // function to add two numbers

function DoubleTheNumber(EditA: TsuiDBEdit): Double;
var
Two: Double;
begin
if EditA.text = '' then
EditA.text := '0';
Two := 2;
Result := StrToFloat(EditA.Text) * Two;
end;

procedure TfrmDrw.dbedtTopClearBoxChange(Sender: TObject);
begin
if not (ADOTableControls.State in [dsInsert, dsEdit]) then
ADOTableControls.Edit;
ADOTableControls.fieldbyname('TotalHtClear').asfloat :=
Add2InputNumbers(dbedtTopClearBox, dbedtBotClearBox);
end;

procedure TfrmDrw.dbedtBotClearBoxChange(Sender: TObject);
begin
if not (ADOTableControls.State in [dsInsert, dsEdit]) then
ADOTableControls.Edit;
ADOTableControls.fieldbyname('TotalHtClear').asfloat :=
Add2InputNumbers(dbedtTopClearBox, dbedtBotClearBox);
end;
 
ok, I've not looked through all of your code as there is so much of it and I'm a little lazy today.

Where is the exception getting raised from? i.e. what peice of code causes it? I assume you know how to use the CallStack to see where the exception was generated from?

Lastly, why not make the 'TotalHtClear' field a calculated field, that way you don't need to have code in the dbedtTopClearBoxChange and dbedtBotClearBoxChange to recalculate it every time - rather, just have it in the OnCalcFields event of your Table/Query object.
 
No, I`m no expert with Call Stack. When I convert to fractional notation this line is highlighted in blue.It mentioned that TotalHtClear is not a floating point number. I would assume when the notation changes to fractions it is considered a string. How do I deal with the changing data types. I guess I have floating point
and string types that the controls have to deal with.


highlighted line.......
ADOTableControls.fieldbyname('TotalHtClear').asfloat :=
<Lastly, why not make the 'TotalHtClear' field a calculated field,>
I need the addition to recalculate without the use of a
button click
 
ok...as you mention, 'TotalHtClear' has been defined as a string, your using .AsFloat to convert it to a float. The problem with this, is that it may not contain a valid float.

I would suggest you change the line to:

ADOTableControls.fieldbyname('TotalHtClear').AsString := FloatToStr(Add2InputNumbers(dbedtTopClearBox, dbedtBotClearBox));

you could also use FloatToStrF for more control over the precision etc.
 
I made the changes you suggested but I still get the same error. If I convert all the control
data to and from decimal to millimeter no error occur. When the data is changed to fractional
notation the error occurs. I might not be clear in explaining the notation code. This code
allows the user at any time to convert any displayed data to various notations. 1/8 or .125 or 7 mm

Thanks

procedure TfrmDrw.dbedtTopClearBoxChange(Sender: TObject);
begin
if not (TableControls.State in [dsInsert, dsEdit]) then
TableControls.Edit;
TableControls.fieldbyname('TotalHtClear').AsString := SHOWS ERROR
FloatToStr(Add2InputNumbers(dbedtTopClearBox, dbedtBotClearBox));
end;

procedure TfrmDrw.dbedtBotClearBoxChange(Sender: TObject);
begin
if not (TableControls.State in [dsInsert, dsEdit]) then
TableControls.Edit;
TableControls.fieldbyname('TotalHtClear').AsString :=
FloatToStr(Add2InputNumbers(dbedtTopClearBox, dbedtBotClearBox));
end;

procedure TfrmDrw.dbedtSideClearDoubleChange(Sender: TObject);
begin

if not (TableControls.State in [dsInsert, dsEdit]) then
TableControls.Edit;
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top