YOUSEFUL / DELPHI / SAMPLE PROJECTS

Linked dashboard

VCL application Product: Atlas Analytics · Components: TAtlasDashboard, TAtlasWidgetDefinition, TAtlasDashboardWidget, TAtlasFilter

A VCL program, with the form created in code, that binds a TAtlasDashboard to one TAtlasTable and shows six widgets from the same snapshot: three KPI cards (revenue, average sale, order count), two bar charts (revenue by region, units by product) and a detail grid. A region combo box filters every widget at once, a button appends a row to the table so the widgets refresh through the table's change notification, and two buttons save and reload the layout as JSON.

What it demonstrates

Build and run

Open LinkedDashboard.dpr in Delphi 13; the IDE creates the project file. Add the Atlas Analytics src folder, the Atlas VCL src folder and the shared folder to the project's search path, then build and run for Win32 or Win64. No packages need to be installed. The shared folder is part of the sample download. It holds Atlas.TestVcl.pas, which the optional snapshot mode uses to save a picture of the window.

Expected output

A 1200 by 860 window with a dark header and a two-column card layout. The status line reads 6 source rows, 6 widgets, Revenue 73300, Average sale 12216.6666666667, Orders 6. Choosing West changes the revenue KPI to 32,100, leaves one bar in the region chart and two rows in the grid. Add a sale appends a West/Service row and every widget updates. Save layout writes dashboard-layout.json next to the executable; Load layout rebuilds the widgets from it.

Adapting it

Replace SalesTable with your own table and change the widget definitions: the Field of a KPI or chart must be an ackNumber column unless the measure is amCount, and a chart needs a Dimension. The dashboard has no property that reads back its filters, so keep the current selection in your own code (this sample keeps it in the combo box) if you need it after LoadJSON.

Project files

Download all 34 projects

The ZIP contains every sample project with its README. See getting started for the search path to add.

Source

LinkedDashboard.dpr

pascal
program LinkedDashboard;

// Atlas Analytics: KPI, chart and grid widgets linked to one table.
// Run without arguments for the window. "LinkedDashboard --image out.png"
// renders the form off screen into a PNG and exits, for automated review.

uses
  Vcl.Forms,
  Atlas.TestVcl,
  LinkedDashboardForm in 'LinkedDashboardForm.pas';

var
  Form: TLinkedDashboardForm;

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TLinkedDashboardForm, Form);
  if (ParamCount = 2) and (ParamStr(1) = '--image') then
    SaveFormImage(Form, ParamStr(2))
  else
    Application.Run;
end.

LinkedDashboardForm.pas

pascal
unit LinkedDashboardForm;

// A form created in code that links KPI, chart and grid widgets of a
// TAtlasDashboard to one TAtlasTable. A region filter, a new row and a saved
// layout each refresh every widget from the same snapshot.

interface

uses
  System.Classes, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls, Vcl.ExtCtrls,
  Atlas.Data, Atlas.Dashboard;

type
  TLinkedDashboardForm = class(TForm)
  private
    FSource: TAtlasTable;
    FDashboard: TAtlasDashboard;
    FRegion: TComboBox;
    FStatus: TLabel;
    FLayoutFile: string;
    procedure RegionChanged(Sender: TObject);
    procedure AddSaleClick(Sender: TObject);
    procedure SaveLayoutClick(Sender: TObject);
    procedure LoadLayoutClick(Sender: TObject);
    procedure ShowStatus(const Note: string = '');
  public
    constructor Create(AOwner: TComponent); override;
    property Dashboard: TAtlasDashboard read FDashboard;
  end;

function SalesTable(Owner: TComponent): TAtlasTable;

implementation

uses
  System.SysUtils, System.IOUtils, Vcl.Graphics, Atlas.Analytics;

function SalesTable(Owner: TComponent): TAtlasTable;
begin
  Result := TAtlasTable.Create(Owner);
  Result.AddColumn('Region');
  Result.AddColumn('Product');
  Result.AddColumn('Revenue', ackNumber);
  Result.AddColumn('Units', ackNumber);
  Result.AddColumn('Booked', ackDate);
  Result.ImportCSV(
    'Region,Product,Revenue,Units,Booked' + sLineBreak +
    'East,Desktop,18000,12,2026-09-01' + sLineBreak +
    'West,Desktop,22500,15,2026-09-02' + sLineBreak +
    'East,Service,6400,8,2026-09-03' + sLineBreak +
    'North,Desktop,12000,8,2026-09-04' + sLineBreak +
    'West,Service,9600,12,2026-09-05' + sLineBreak +
    'North,Service,4800,6,2026-09-06');
end;

constructor TLinkedDashboardForm.Create(AOwner: TComponent);
var
  Header: TPanel;

  function AddButton(Left: Integer; const Caption: string; OnClick: TNotifyEvent): TButton;
  begin
    Result := TButton.Create(Self);
    Result.Parent := Header;
    Result.SetBounds(Left, 13, 110, 30);
    Result.Caption := Caption;
    Result.OnClick := OnClick;
  end;

begin
  inherited CreateNew(AOwner);
  Caption := 'Atlas Analytics: linked dashboard';
  Width := 1200;
  Height := 860;
  Position := poScreenCenter;
  Font.Name := 'Segoe UI';
  Font.Size := 10;
  FLayoutFile := TPath.Combine(TPath.GetDirectoryName(ParamStr(0)), 'dashboard-layout.json');

  Header := TPanel.Create(Self);
  Header.Parent := Self;
  Header.Align := alTop;
  Header.Height := 56;
  Header.BevelOuter := bvNone;
  Header.Color := $003D2C1E;
  Header.ParentBackground := False;

  FRegion := TComboBox.Create(Self);
  FRegion.Parent := Header;
  FRegion.SetBounds(16, 14, 150, 28);
  FRegion.Style := csDropDownList;
  FRegion.Items.Add('All regions');
  FRegion.Items.Add('East');
  FRegion.Items.Add('West');
  FRegion.Items.Add('North');
  FRegion.ItemIndex := 0;
  FRegion.OnChange := RegionChanged;
  AddButton(182, 'Add a sale', AddSaleClick);
  AddButton(300, 'Save layout', SaveLayoutClick);
  AddButton(418, 'Load layout', LoadLayoutClick);

  FStatus := TLabel.Create(Self);
  FStatus.Parent := Header;
  FStatus.SetBounds(548, 18, 630, 22);
  FStatus.AutoSize := False;
  FStatus.Font.Color := clWhite;

  // The table is owned by the form; the dashboard only listens to it.
  FSource := SalesTable(Self);
  FDashboard := TAtlasDashboard.Create(Self);
  FDashboard.Parent := Self;
  FDashboard.Align := alClient;
  FDashboard.Source := FSource;
  FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awKPI, 'Revenue', 'Revenue'));
  FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awKPI, 'Average sale', 'Revenue', amAverage));
  FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awKPI, 'Orders', '', amCount));
  FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awChart, 'Revenue by region', 'Revenue', amSum, 'Region'));
  FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awChart, 'Units by product', 'Units', amSum, 'Product'));
  FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awGrid, 'Sales detail', ''));
  ShowStatus;
end;

procedure TLinkedDashboardForm.RegionChanged(Sender: TObject);
begin
  // SetFilters rebuilds every widget from one filtered snapshot. The source
  // table keeps its own filter and sort; a bad filter raises and leaves the
  // previous filters in place.
  if FRegion.ItemIndex > 0 then
    FDashboard.SetFilters([TAtlasFilter.Create('Region', FRegion.Text)])
  else
    FDashboard.SetFilters([]);
  ShowStatus;
end;

procedure TLinkedDashboardForm.AddSaleClick(Sender: TObject);
begin
  // The dashboard listens to the table, so every widget updates by itself.
  FSource.AddRow(['West', 'Service', '1500', '2', '2026-09-07']);
  ShowStatus('Added a West/Service sale of 1500');
end;

procedure TLinkedDashboardForm.SaveLayoutClick(Sender: TObject);
begin
  // ToJSON persists widget definitions and dashboard filters, not the data.
  TFile.WriteAllText(FLayoutFile, FDashboard.ToJSON, TEncoding.UTF8);
  ShowStatus('Layout saved to ' + FLayoutFile);
end;

procedure TLinkedDashboardForm.LoadLayoutClick(Sender: TObject);
begin
  if not FileExists(FLayoutFile) then
  begin
    ShowStatus('Save a layout first');
    Exit;
  end;
  // LoadJSON validates every widget against the current source before it
  // replaces anything; an invalid file leaves the current widgets in place.
  FDashboard.LoadJSON(TFile.ReadAllText(FLayoutFile, TEncoding.UTF8));
  ShowStatus('Layout loaded from ' + FLayoutFile);
end;

procedure TLinkedDashboardForm.ShowStatus(const Note: string);
var
  Text: string;
  Widget: TAtlasDashboardWidget;
  I: Integer;
begin
  Text := Format('%d source rows, %d widgets', [FSource.RowCount, FDashboard.WidgetCount]);
  for I := 0 to FDashboard.WidgetCount - 1 do
  begin
    Widget := FDashboard.Widgets[I];
    if (Widget.Definition.Kind = awKPI) and Assigned(Widget.Data) then
      Text := Text + Format(', %s %s', [Widget.Definition.Title, Widget.Data.Cell(0, 0)]);
  end;
  if FDashboard.LastError <> '' then
    Text := 'Last error: ' + FDashboard.LastError
  else if Note <> '' then
    Text := Note + ' (' + Text + ')';
  FStatus.Caption := Text;
end;

end.