Formatting a Column as Currency - FireMonkey Guide

Back to FireMonkey Topics

In Custom Grid Columns we saw how to create a column for a control class. Here I’m going to build on that to demonstrate a column with both a custom cell control class and custom column class. This shows how to create columns of custom components.

In this example I’ll take a standard TTextCell (which you’ll remember is descended from TEdit) and format it’s contents as currency. For this I shall: right align the text; display it’s contents as a monetary value; show negative values in red.

The Class Declarations

We need two classes, one for the cells and another for the column. Here are the class declarations,

type TMoneyCell = class(TTextCell)
  private
    
FFloatValueSingle;
  protected
    
procedure SetData(const ValueTValue);override;
  public
    
constructor Create(OwnerTComponent);override;
  
end;

type TMoneyColumn = class(TColumn)
  protected
    function 
CreateCellControlTStyledControl;override;
  
end

TMoneyCell

In the cell’s constructor I firstly remove ssFontColor from StyledSettings so I can override the font color from the style. Next I set the TextAlign to taTrailing, which right-aligns the contents.

constructor TMoneyCell.Create(OwnerTComponent);
begin
  inherited
;
  
StyledSettings := StyledSettings-[TStyledSetting.ssFontColor];
  
TextAlign := TTextAlign.taTrailing;
end

A grid sets each cell’s contents by setting the Data property of the cell, which uses the SetData setter method, so I override that to handle setting the value.

procedure TMoneyCell.SetData(const ValueTValue);
begin
  FFloatValue 
:= Value.AsType<Single>;
  
inherited SetData(Format('%m'[FFloatValue]));

  if 
FFloatValue 0 then
    FontColor 
:= claRed
  
else
    
FontColor := claBlack;
end

This method starts by extracting the data from the TValue, which is stored as a single. I then format it appropriately and pass it on to the inherited SetData method from the TEdit to be displayed as usual.

Finally I set the FontColor to reflect whether the value is positive or negative.

Note here that I haven’t implemented GetData which will be called to read changed cell values. This is left as an exercise for the reader, if you want editable cells.

TMoneyColumn

For the column I only need to override CreateCellControl so I can create my cell and set a few event handlers which pass events back to the application via the grid.

function TMoneyColumn.CreateCellControlTStyledControl;
begin
  Result 
:= TMoneyCell.Create(Self);
  
TMoneyCell(Result).OnTyping := DoTextChanged;
  
TMoneyCell(Result).OnChange := DoTextChanged;
  
TMoneyCell(Result).OnExit := DoTextExit;
end

On the Form

Now we need to use our new column. You’ll recall that there’s no way to register custom column types with the IDE for use at design time so you’ll need to add the column in code,

procedure TForm1.FormCreate(SenderTObject);
begin
  Grid1
.AddObject(TMoneyColumn.Create(Grid1));
end

And I test it with some random sample data,

procedure TForm1.Grid1GetValue(SenderTObject; const ColRowInteger;
  var 
ValueTValue);
begin
  
if Col 0 then
    Value 
:= TValue.From<Single>(Random(10000)/100-50);
end

Source

Here’s the full source of the MoneyColumn unit:

unit MoneyColumn;

interface
uses FMX.GridSystem.RTTIFMX.ControlsClasses;

type TMoneyCell = class(TTextCell)
  private
    
FFloatValueSingle;
  protected
    
procedure SetData(const ValueTValue);override;
  public
    
constructor Create(OwnerTComponent);override;
  
end;

type TMoneyColumn = class(TColumn)
  protected
    function 
CreateCellControlTStyledControl;override;
  
end;

implementation
uses FMX
.TypesSysUtilsFMX.ObjectsSystem.UIConsts;

{ TMoneyColumn }

function TMoneyColumn.CreateCellControlTStyledControl;
begin
  Result 
:= TMoneyCell.Create(Self);
  
TMoneyCell(Result).OnTyping := DoTextChanged;
  
TMoneyCell(Result).OnChange := DoTextChanged;
  
TMoneyCell(Result).OnExit := DoTextExit;
end;

{ TMoneyCell }

constructor TMoneyCell
.Create(OwnerTComponent);
begin
  inherited
;
  
StyledSettings := StyledSettings-[TStyledSetting.ssFontColor];
  
TextAlign := TTextAlign.taTrailing;
end;

procedure TMoneyCell.SetData(const ValueTValue);
begin
  FFloatValue 
:= Value.AsType<Single>;
  
inherited SetData(Format('%m'[FFloatValue]));

  if 
FFloatValue 0 then
    FontColor 
:= claRed
  
else
    
FontColor := claBlack;
end;

end

See Also

TGrid
Custom Grid Columns

Categories:

div title=