Headless data layer
Use the data layer independently — sort, filter, group, and export without any visual component on screen. Useful for background processing, batch exports, and unit-testable data pipelines.
Overview
TTMSFNCDataGridData is the layer that stores cell values and
owns all data operations: sorting, filtering, grouping, and CSV export. Because
it has no dependency on drawing or controls, you can instantiate it anywhere —
including a background thread, a service, or a console application — and run
full data operations without displaying anything.
The same API works on both the headless layer and on a live grid: Filter.Add,
ApplyFilter, Sort, Group, Strings[], Floats[], Ints[], SaveToCSVData
are all on TTMSFNCDataGridData and therefore available on TTMSFNCDataGrid too.
Quick example
Load 500 JSON records, filter by category, sort by price, and log the top five:
procedure TFormDataLayerDemo.BtnLoadClick(Sender: TObject);
begin
FData.ClearData;
FData.FixedRowCount := 1;
FData.Options.IO.StartRow := 1; // row 0 receives JSON key names as headers
FData.LoadFromJSONData(
JSONPath,
'', '',
['id', 'name', 'category', 'price', 'stock', 'is_organic', 'is_vegan']);
Log(Format('Loaded %d records', [FData.RowCount - FData.FixedRowCount]));
end;
Step by step
1. Create and destroy
type
TMyForm = class(TForm)
private
FData: TTMSFNCDataGridData;
end;
procedure TMyForm.FormCreate(Sender: TObject);
begin
FData := TTMSFNCDataGridData.Create;
end;
procedure TMyForm.FormDestroy(Sender: TObject);
begin
FData.Free;
end;
TTMSFNCDataGridData is an ordinary object — it allocates on the heap and must
be freed explicitly.
2. Load data
The data layer supports the same load methods as the grid:
// From JSON (most common for REST payloads)
FData.LoadFromJSONData(FileName, '', '',
['id', 'name', 'category', 'price', 'stock']);
// From CSV
FData.Options.IO.Delimiter := ',';
FData.LoadFromCSVData('products.csv');
// Manually
FData.ColumnCount := 3;
FData.FixedRowCount := 1;
FData.RowCount := 4;
FData.Cells[0, 0] := 'ID';
FData.Cells[1, 0] := 'Name';
FData.Cells[2, 0] := 'Price';
FData.Cells[0, 1] := 1; FData.Cells[1, 1] := 'Widget A'; FData.Cells[2, 1] := 9.99;
FData.Cells[0, 2] := 2; FData.Cells[1, 2] := 'Widget B'; FData.Cells[2, 2] := 14.50;
FData.Cells[0, 3] := 3; FData.Cells[1, 3] := 'Widget C'; FData.Cells[2, 3] := 4.25;
Set
FData.Options.IO.StartRow := 1before loading JSON so that row 0 receives the JSON key names as column headers automatically.
3. Filter
FData.Filter.Clear;
FData.Filter.Add(COL_CATEGORY, gftEqual, 'Meat');
FData.ApplyFilter;
After ApplyFilter, iterate visible rows with IsRowDisplayed:
var Count := 0;
for var R := FData.FixedRowCount to FData.RowCount - 1 do
if FData.IsRowDisplayed(R) then
Inc(Count);
Log(Format('%d matching rows', [Count]));
To remove all filters and show every row again, call RemoveFilter:
FData.RemoveFilter;
4. Sort
FData.Sort(COL_PRICE, gsdDescending);
Sort and filter interact: sorting re-orders only the displayed rows; hidden rows stay hidden.
5. Group with aggregations
FData.Group(COL_CATEGORY);
FData.GroupCount(COL_CATEGORY); // count column
FData.GroupSum(COL_PRICE); // sum column
Walk the result to inspect group rows and their summaries:
for var R := FData.FixedRowCount to FData.RowCount - 1 do
begin
if FData.IsRowNode(R) then
Log(FData.Strings[FData.FixedColumnCount, R]) // group header text
else if FData.IsRowSummary(R) then
Log(Format(' count=%.0f sum=$%.2f',
[FData.Floats[COL_CATEGORY, R], FData.Floats[COL_PRICE, R]]));
end;
FData.Ungroup;
6. Export
FData.Options.IO.Delimiter := ',';
FData.SaveToCSVData('output.csv');
7. Read typed values
Use typed accessors for performance in tight loops:
var Name := FData.Strings[COL_NAME, Row];
var Price := FData.Floats [COL_PRICE, Row];
var Stock := FData.Ints [COL_STOCK, Row];
Connecting the headless layer to a visual grid
If you later want to display the processed data in a TTMSFNCDataGrid, you
can copy it row by row or simply re-load the same source into the grid:
// Simplest: let the grid load its own copy
Grid.LoadFromJSONData(FileName, '', '', ['id', 'name', 'price']);
For a shared-source pattern, use TTMSFNCDataGridDatabaseAdapter against a
common TDataSet. The data layer is best used for scenarios where you need
data operations without any UI — for example, generating a filtered CSV in a
background thread or computing statistics at startup.
Related API
TTMSFNCDataGridDataFData.LoadFromJSONData/LoadFromCSVDataFData.Filter.Add(AColumn, AFilterType, ACondition)— typed filter overloadFData.ApplyFilter/RemoveFilterFData.IsRowDisplayed(ARow)— True if the row is visible after filterFData.IsRowNode(ARow)— True if the row is a group headerFData.IsRowSummary(ARow)— True if the row is a group summaryFData.Sort(AColumn, ADirection)FData.Group(AColumn)/UngroupFData.GroupSum/GroupCount/GroupAverage/GroupMin/GroupMaxFData.SaveToCSVData(AFileName)— delimiter set viaOptions.IO.DelimiterFData.Strings[col, row]/Floats/Ints/Booleans— typed accessorsFData.FixedRowCount/ColumnCount/RowCountFData.Options.IO.StartRow— set to 1 so JSON keys land in row 0 as headers
See also
- Architecture — where the data layer fits in the three-layer design.
- Data, formatting & conversion — how values are stored.
- Filtering — full filtering reference.
- Grouping — grouping and aggregation reference.
- Import (JSON) — JSON structure mapping options.