4

How can I convert a fieldtype from ftFloat to ftBCD;

I tried

for i := 0 to FDataSet.FieldCount - 1 do begin
      if FDataSet.Fields.Fields[i].DataType = ftFloat then begin
           FDataSet.Fields.Fields[i].DataType := ftBCD;
      end;
end;

But I get the error

[DCC Error]  E2129 Cannot assign to a read-only property

Is there a way I can convert all dataset field that ftFloat to ftBCD ?

LU RD
  • 34,438
  • 5
  • 88
  • 296
CiucaS
  • 2,010
  • 5
  • 36
  • 63
  • 1
    The Datatype is bound to the class of your field. You will have to free the field and create a TFloatField and add this to your Dataset. The dataset has to be close while doing this. An exapmle can be seen [here](http://stackoverflow.com/a/25765707/1699210) – bummi Sep 11 '14 at 07:04
  • 1
    Are you using Firedac? If yes than set the formatoptions.maprules property of your connection. Add a rule with source ftBCD and target ftFloat. – Copilot Sep 11 '14 at 07:05
  • @Copilot no, i'm not using Firedac. – CiucaS Sep 11 '14 at 07:25
  • @bummi ty, then I creat the DataSet for all ftFloat as ftBCD and my problem is solved, ty for pointing me to a solution. Post it as an answer so I can accept it. – CiucaS Sep 11 '14 at 07:39
  • Are you aware that you are going to lose precision by doing this right? What is the class of your TDataSet? – EProgrammerNotFound Sep 11 '14 at 11:21
  • I'm aware, the precision is not so important in my current context, as this project is only for customers to view some anualy reports in a more organise enviroment, if they want specific details they have other modules to look into – CiucaS Sep 11 '14 at 11:49

3 Answers3

7

DataType is readonly Property of the Tfield created for a DataType. This is done from Fielddefs using DefaultFieldClasses: array[TFieldType] of TFieldClass from DB. If you need to change the DataType you will have to Free the Field and create anotherone fittinig your needs. Below is shown an exmaple how this could be done.

type
  TMyFieldInfo = Record
    FieldName: String;
    Size: Integer;
    DataType: TFieldType;
    FieldKind: TFieldKind;
  end;

type
  TFA= Array of TMyFieldInfo;

 Procedure GetFields(DS:Tdataset;var FA:TFA);
  var
    I: Integer;
  begin
    SetLength(FA, DS.FieldCount);
    for I := 0 to DS.FieldCount - 1 do
    begin
      FA[I].FieldName := DS.Fields[I].FieldName;
      FA[I].DataType := DS.Fields[I].DataType;
      FA[I].Size := DS.Fields[I].Size;
      FA[I].FieldKind := fkdata;
    end;
  end;

  Procedure SetFields(DS:Tdataset;var FA:TFA);
  var
    I: Integer;
    F:TField;
  begin
    DS.Fields.Clear;
    for I := Low(FA) to High(FA) do
    begin
      F := DefaultFieldClasses[FA[I].DataType].Create(DS);
      With F do
      begin
        FieldName := FA[I].FieldName;
        FieldKind := FA[I].FieldKind;
        Size := FA[I].Size;
        DataSet := DS;
      end;
    end;

  end;


procedure TForm6.Button1Click(Sender: TObject);
var
   L_FA: TFA;
   I:Integer;
begin
    MyDS.Open;  // open to get the Fielddefs.
    GetFields(MyDS,L_FA);
    MyDS.Close;  // close to be able to change the fields
    for I := Low(L_FA) to High(L_FA) do
      begin
         if L_FA[i].DataType = ftFloat then
            L_FA[i].DataType := ftBCD;
      end;
    SetFields(MyDS,L_FA);
    MyDS.Open;
end;
bummi
  • 27,123
  • 14
  • 62
  • 101
1

Here is another way:

First, you need to dump the table into a file like this

ADOQuery.SaveToFile('C:\1.xml');

then find your field description in it, let's say it will be like this:

<s:datatype dt:type='float' dt:maxLength='8' rs:fixedlength='true' rs:maybenull='true'/>

and replace it with the other type description, like this:

<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='25' rs:precision='25' rs:fixedlength='true' rs:maybenull='true'/>

now you need to load this file back, like this:

ADOQuery.LoadFromFile('C:\1.xml');
Yevgeniy Afanasyev
  • 37,872
  • 26
  • 173
  • 191
  • Nice, next time I have a problem like this I will try this solution. – CiucaS Dec 02 '14 at 08:05
  • Moreover, you may not use files, check out this question: http://stackoverflow.com/questions/7812537/adodataset-how-to-load-xml-saved-beforehand-in-db-in-ado-schema-data-without/7813249#7813249 – Yevgeniy Afanasyev Dec 02 '14 at 22:16
0

NO! Once you creates a Datafield you can not change it! It is because assigning a Filedtype is much more than just changeing an enum type property. Each field type is a specific class: TintegerField etc...

So you can not change the FieldType for the same reason the can not make an TList in to a string

Excatly what are you trying to to ?

Jens Borrisholt

Jens Borrisholt
  • 6,174
  • 1
  • 33
  • 67
  • I have a rave report, that expects ftBCD, but my decimal fileds from my dataset for that needs to be passed to the Rave returns ftFloat. So I have to somehow convert them into ftBCD. – CiucaS Sep 11 '14 at 07:24