BufDataset Demonstration with Sorting and Filtering

This demonstration requires the same kind of set-up as the simpler example on the previous page, so we provide here the code of the unit and of the form rather than stepwise instructions. Whereas the first example used trivial data, this one is useful for comparing areas of European countries. We copied the areas from this Wikipedia page. The code follows a screenshot of sorting and filtering in action.

Sorting and Filtering

Sorting and Filtering

Code of Unit

unit uBufDatasetDemo2;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, db, BufDataset, FileUtil, Forms, Controls, Graphics,
  Dialogs, DBGrids, DbCtrls, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    BufDataset1: TBufDataset;
    Button1: TButton;
    ComboBox1: TComboBox;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    Label1: TLabel;
    leMinArea, leMaxArea: TLabeledEdit;
    procedure BufDataset1FilterRecord(DataSet: TDataSet; var Accept: Boolean);
    procedure Button1Click(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
  private
    const
      CountriesAndCapitals: array[1..78] of string =
       ('England', 'London', 'Scotland', 'Edinburgh', 'Northern Ireland', 'Belfast',
        'Wales', 'Cardiff', 'Ireland', 'Dublin', 'Germany', 'Berlin',
        'France', 'Paris', 'Greece', 'Athens', 'Finland', 'Helsinki',
        'Hungary', 'Budapest', 'Italy', 'Rome', 'Liechtenstein', 'Vaduz',
        'Lithuania', 'Vilnius', 'Luxembourg', 'Luxembourg', 'Poland', 'Warsaw',
        'Portugal', 'Lisbon', 'Romania', 'Bucharest', 'Russia', 'Moscow',
        'Serbia', 'Belgrade', 'Slovakia', 'Bratislava', 'Slovenia', 'Ljubljana',
        'Spain', 'Madrid', 'Sweden', 'Stockholm', 'Switzerland', 'Bern',
        'Norway', 'Oslo', 'Austria', 'Vienna', 'Belgium', 'Brussels',
        'Bosnia and Herzegovina', 'Sarajevo', 'Bulgaria', 'Sofia', 'Netherlands', 'Amsterdam',
        'Czech Republic', 'Prague', 'Moldova', 'Chisinau', 'Latvia', 'Riga',
        'Iceland', 'Reykjavik', 'Malta', 'Valletta', 'Macedonia', 'Skopje',
        'Montenegro', 'Podgorica', 'Turkey', 'Ankara', 'Estonia', 'Tallinn');

      Areas: array[1..39] of integer = (130395, 78387, 14148, 20732, 70280, 357021,
                                        547030, 131940, 338424, 93030, 301230, 160,
                                        65200, 2586, 312685, 92391, 23839, 17075400,
                                        88361, 48845, 20273, 505782, 449964, 41290,
                                        385252, 83858, 30510, 51129, 110910, 41526,
                                        78866, 33843, 64589, 103001, 316, 25713,
                                        13812, 783562, 45226);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

procedure TForm1.BufDataset1FilterRecord(DataSet: TDataSet; var Accept: Boolean);
begin
  Accept := (BufDataset1.Fields[1].AsInteger >= StrToInt(leMinArea.Text)) and
            (BufDataset1.Fields[1].AsInteger <= StrToInt(leMaxArea.Text));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Bufdataset1.Filtered := False;
  Bufdataset1.Filtered := True;
  Bufdataset1.First;
end;

procedure TForm1.ComboBox1Change(Sender: TObject);
begin
  BufDataset1.IndexFieldNames := Combobox1.Text;
  BufDataset1.First;
end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  BufDataSet1.Filtered := False;
  BufDataSet1.SaveToFile('Demo2.bds');
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i : integer;
begin
   with  BufDataSet1 do
    begin
      if fileExists('demo2.bds') then
        begin
          LoadFromFile('demo2.bds') ;
        end
      else
        begin
          CreateDataset;
          for i := 1 to 39 do
            begin
              Append;
              Fields[0].Value := CountriesAndCapitals[i * 2 - 1];
              Fields[1].Value := Areas[i];
              Fields[2].Value := CountriesAndCapitals[i * 2];
            end;
          Post;
          Filtered := False;
          SaveToFile('demo2.bds');
          First;
        end;
     end;
end;

end.

Code of Form

object Form1: TForm1
  Left = 452
  Height = 253
  Top = 230
  Width = 370
  Caption = 'Capitals and Areas (Europe)'
  ClientHeight = 253
  ClientWidth = 370
  OnClose = FormClose
  OnCreate = FormCreate
  LCLVersion = '1.2.4.0'
  object DBGrid1: TDBGrid
    Left = 9
    Height = 164
    Top = 8
    Width = 359
    Color = clWindow
    Columns = <    
      item
        Title.Caption = 'Country'
        Width = 150
        FieldName = 'Country'
      end    
      item
        Title.Caption = 'Area (sq km)'
        Width = 75
        FieldName = 'Area (sq km)'
      end    
      item
        Title.Caption = 'Capital'
        Width = 100
        FieldName = 'Capital'
      end>
    DataSource = DataSource1
    TabOrder = 0
  end
  object DBNavigator1: TDBNavigator
    Left = 57
    Height = 25
    Top = 176
    Width = 241
    BevelOuter = bvNone
    ChildSizing.EnlargeHorizontal = crsScaleChilds
    ChildSizing.EnlargeVertical = crsScaleChilds
    ChildSizing.ShrinkHorizontal = crsScaleChilds
    ChildSizing.ShrinkVertical = crsScaleChilds
    ChildSizing.Layout = cclLeftToRightThenTopToBottom
    ChildSizing.ControlsPerLine = 100
    ClientHeight = 25
    ClientWidth = 241
    DataSource = DataSource1
    Options = []
    TabOrder = 1
  end
  object leMinArea: TLabeledEdit
    Left = 116
    Height = 23
    Top = 225
    Width = 80
    EditLabel.AnchorSideLeft.Control = leMinArea
    EditLabel.AnchorSideRight.Control = leMinArea
    EditLabel.AnchorSideRight.Side = asrBottom
    EditLabel.AnchorSideBottom.Control = leMinArea
    EditLabel.Left = 116
    EditLabel.Height = 15
    EditLabel.Top = 207
    EditLabel.Width = 80
    EditLabel.Caption = 'Minimum Area'
    EditLabel.ParentColor = False
    TabOrder = 2
    Text = '0'
  end
  object leMaxArea: TLabeledEdit
    Left = 203
    Height = 23
    Top = 224
    Width = 80
    EditLabel.AnchorSideLeft.Control = leMaxArea
    EditLabel.AnchorSideRight.Control = leMaxArea
    EditLabel.AnchorSideRight.Side = asrBottom
    EditLabel.AnchorSideBottom.Control = leMaxArea
    EditLabel.Left = 203
    EditLabel.Height = 15
    EditLabel.Top = 206
    EditLabel.Width = 80
    EditLabel.Caption = 'Maximum Area'
    EditLabel.ParentColor = False
    TabOrder = 3
    Text = '100000'
  end
  object ComboBox1: TComboBox
    Left = 6
    Height = 23
    Top = 224
    Width = 100
    ItemHeight = 15
    ItemIndex = 0
    Items.Strings = (
      'Country'
      'Area (sq km)'
      'Capital'
    )
    OnChange = ComboBox1Change
    TabOrder = 4
    Text = 'Country'
  end
  object Button1: TButton
    Left = 290
    Height = 25
    Top = 222
    Width = 75
    Caption = 'Filter'
    OnClick = Button1Click
    TabOrder = 5
  end
  object Label1: TLabel
    Left = 9
    Height = 15
    Top = 206
    Width = 49
    Caption = 'Sort Field'
    ParentColor = False
  end
  object DataSource1: TDataSource
    DataSet = BufDataset1
    left = 24
    top = 72
  end
  object BufDataset1: TBufDataset
    IndexFieldNames = 'Country'
    FieldDefs = <    
      item
        Name = 'Country'
        DataType = ftString
        Precision = 0
        Size = 25
      end    
      item
        Name = 'Area (sq km)'
        DataType = ftInteger
        Precision = 8
        Size = 4
      end    
      item
        Name = 'Capital'
        DataType = ftString
        Precision = 0
        Size = 25
      end>
    OnFilterRecord = BufDataset1FilterRecord
    left = 112
    top = 72
  end
end    
Programming - a skill for life!

How to set-up and use the TBufDataset component in Lazarus