Search code examples
listviewdelphifiremonkey

Error on FormatFloat(#,##0.00, var_number) and Format('%n', var_number) Rounding-off to Thousands


The FormatFloat(#,##0.00, var_number) and Format('%n', var_number) is giving me a rounded-off to thousands result. Why is this happening? Is there something wrong with my code?

I did some Minimum Reproducible Example below for your reference. The result I am getting here is 12 instead of 12,345.00. Please let me know where and what exactly I missed here.

FMX Procedure:

unit Unit9;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base,
  FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf,
  FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async,
  FireDAC.Phys, FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef,
  FireDAC.Stan.ExprFuncs, FireDAC.FMXUI.Wait, FireDAC.Stan.Param, FireDAC.DatS,
  FireDAC.DApt.Intf, FireDAC.DApt, Data.Bind.EngExt, Fmx.Bind.DBEngExt,
  System.Rtti, System.Bindings.Outputs, Fmx.Bind.Editors, Data.Bind.Components,
  Data.Bind.DBScope, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client,
  FMX.ListView, FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm9 = class(TForm)
    lbl1: TLabel;
    lsv1: TListView;
    con1: TFDConnection;
    qryLists: TFDQuery;
    bdr1: TBindSourceDB;
    bdl1: TBindingsList;
    tcf1: TLinkFillControlToField;
    lpfText: TLinkPropertyToField;
    qryInsert: TFDQuery;
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form9: TForm9;

implementation

{$R *.fmx}

procedure TForm9.btn1Click(Sender: TObject);
begin
  qryInsert.ParamByName('id').AsInteger := 1;
  qryInsert.ParamByName('cur_datetime').AsDateTime := now;
  qryInsert.ParamByName('name').AsString := 'sample';
  qryInsert.ParamByName('size_cont').AsString := 'size_cont';
  qryInsert.ParamByName('qty').AsFloat := 10;
  qryInsert.ParamByName('est_price').AsFloat := 1234.5;
  qryInsert.ParamByName('qty_price').AsString := '10 x 1234.5';
  qryInsert.ParamByName('estimate').AsString := FormatFloat('#,##0.00', 10 * 1234.5); //the result is giving me 12 (the correct one is 12,345.00)
  qryInsert.ExecSQL;
  qryLists.Close;
  qryLists.Open();
end;

end.

FMX File:

object Form9: TForm9
  Left = 0
  Top = 0
  Caption = 'Form9'
  ClientHeight = 480
  ClientWidth = 308
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object lbl1: TLabel
    Align = Top
    StyledSettings = [Family, Style, FontColor]
    Size.Width = 308.000000000000000000
    Size.Height = 33.000000000000000000
    Size.PlatformDefault = False
    TextSettings.Font.Size = 14.000000000000000000
    TextSettings.HorzAlign = Center
    Text = '5'
    TabOrder = 0
  end
  object lsv1: TListView
    ItemAppearanceClassName = 'TImageListItemBottomDetailAppearance'
    ItemEditAppearanceClassName = 'TImageListItemBottomDetailShowCheckAppearance'
    HeaderAppearanceClassName = 'TListHeaderObjects'
    FooterAppearanceClassName = 'TListHeaderObjects'
    Align = Client
    Size.Width = 308.000000000000000000
    Size.Height = 407.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 1
  end
  object btn1: TButton
    Align = Bottom
    Position.Y = 440.000000000000000000
    Size.Width = 308.000000000000000000
    Size.Height = 40.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 7
    Text = 'btn1'
    OnClick = btn1Click
  end
  object con1: TFDConnection
    Params.Strings = (
      
        'Database=D:\My Project Files\5. my_projects_aws-rest\project_x_v' +
        '0\application\client\database\smartcart.s3db'
      'LockingMode=Normal'
      'DriverID=SQLite')
    Connected = True
    LoginPrompt = False
    Left = 72
    Top = 24
  end
  object qryLists: TFDQuery
    Active = True
    Connection = con1
    SQL.Strings = (
      'SELECT id, date_created, name, size_cont, qty_price, estimate'
      'FROM lists ORDER BY date_created DESC')
    Left = 112
    Top = 24
  end
  object bdr1: TBindSourceDB
    DataSet = qryLists
    ScopeMappings = <>
    Left = 152
    Top = 24
  end
  object bdl1: TBindingsList
    Methods = <>
    OutputConverters = <>
    Left = 20
    Top = 5
    object tcf1: TLinkFillControlToField
      Category = 'Quick Bindings'
      Control = lsv1
      Track = True
      FillDataSource = bdr1
      AutoFill = True
      FillExpressions = <
        item
          SourceMemberName = 'estimate'
          ControlMemberName = 'Detail'
        end>
      FillHeaderExpressions = <>
      FillBreakGroups = <>
    end
    object lpfText: TLinkPropertyToField
      Category = 'Quick Bindings'
      DataSource = bdr1
      FieldName = 'estimate'
      Component = lbl1
      ComponentProperty = 'Text'
    end
  end
  object qryInsert: TFDQuery
    Connection = con1
    SQL.Strings = (
      'INSERT INTO lists (id, date_created, name, size_cont, '
      '                   qty, est_price, qty_price, estimate) '
      'VALUES (:id, :cur_datetime, :name, :size_cont, '
      '        :qty, :est_price, :qty_price, :estimate);')
    Left = 192
    Top = 24
    ParamData = <
      item
        Name = 'ID'
        DataType = ftInteger
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'CUR_DATETIME'
        DataType = ftDateTime
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'NAME'
        DataType = ftString
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'SIZE_CONT'
        DataType = ftString
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'QTY'
        DataType = ftFloat
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'EST_PRICE'
        DataType = ftFloat
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'QTY_PRICE'
        DataType = ftString
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'ESTIMATE'
        DataType = ftFloat
        ParamType = ptInput
        Value = Null
      end>
  end
end

UPDATE: TListView Properties Screenshot

TListView Properties Screenshot


Solution

  • Your parameter is defined as Datatype = ftFloat, according to your form definition file.

    item
      Name = 'ESTIMATE'
      DataType = ftFloat
      ParamType = ptInput
      Value = Null
    end>
    

    That means that you have no need to assign the value using the parameter's AsString or converting it using FormatFloat at all, as you can just assign the value directly as a floating point value.

    qryInsert.ParamByName('estimate').AsFloat := 10 * 1234.5;
    

    Doing so cannot cause any rounding errors, as the data is stored with the proper value. No rounding is done at all.