Title: How to create Tabs with Names from an Table-Field
Question: Your application has a Category-Field (or any other..). You will present this locates in a better style than `prompt a string and do a locate`.
Answer:
You need this Objects:
TForm Form1
TTabControl Tabcontrol1 (Align to alBottom, Height 20)
TTable Table1 (connected to Borlands Biolife.db or ...)
TDataSource DataSource1 (connectet to Table1)
TDBGrid DBGrid1 (connected to DataSource1)
TEdit Edit1 (with onChange Edit1Change)
TButton Button1 (with onClick Button1Click)
The Tabs are automaticly titled with the values from the Table-Field.
If you click on a Tab the Table is positioned to this Record.
uses CommCtrl;
private
IXField: string;
// Here the FormCreate Procedure
procedure TForm1.FormCreate(Sender: TObject);
begin
// set here the correct pathname for the Biolife-Table
Table1.DatabaseName := 'C:\Programme\Gemeinsame Dateien\Borland Shared\Data';
// set here the TableName
Table1.TableName := 'Biolife.db';
// Set here the Fieldname for the Secondary Index and TabControl
IXField := 'Category';
// create and set the Secondary Index for Category
CreateSX(Table1, IXField);
Table1.open;
Table1.IndexFieldNames := IXField;
// and now Create the Tabs
TabCreate(Table1);
end;
// Here set Focus and activate the Secondary Index
procedure TForm1.FormShow(Sender: TObject);
begin
DBGrid1.setfocus;
DBGrid1.SelectedField := Table1.FieldByName(IXField);
end;
// close the Table and delete the Secondary Index
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
Table1.close;
DeleteSX(Table1);
end;
// This procedure creates all TabControl-Tabs
procedure TForm1.TabCreate(TableX: TTable);
var
OldName: string;
begin
with TableX do begin
DisableControls;
first;
OldName := '';
// Scan the Table for all Category-Names
while not eof do begin
// look if an new Category-Name
if (OldName TableX.FieldByName(IXField).AsString) then begin
// save the new name
OldName := TableX.FieldByName(IXField).AsString;
// and add an new Tab
TabControl1.Tabs.add(OldName);
end;
next;
end;
first;
EnableControls;
end;
end;
{ If the Category has become new Names then normally this new Tabs are created
at next Program-Start only. You can place an Button on your Form with the following
code. This removes the old Tabs and add all Tabs new.}
procedure TForm1.Button1Click(Sender: TObject);
// needs: Uses CommCtrl
begin
Edit1.Text := '';
// delete all old Tabs
SendMessage(TabControl1.Handle, TCM_DELETEALLITEMS, 0, 0);
// and create all new Tabs
TabCreate(Table1);
end;
// handle the Tab-changes
procedure TForm1.TabControl1Change(Sender: TObject);
begin
// get the new Tab-name into Edit-Field and start the Edit1Change-Handler
Edit1.Text := TabControl1.Tabs[TabControl1.TabIndex];
// set the focus back to the Secondary-IndexField
DBGrid1.setfocus;
DBGrid1.SelectedField := Table1.FieldByName(IXField);
end;
// manual locate is done at every input of a char
procedure TForm1.Edit1Change(Sender: TObject);
begin
Table1.Locate(IXField, Edit1.text, [loCaseInsensitive, loPartialKey]);
end;
{ The following Procedures CreateSX and DeleteSX are also used in Article
'How to sort DBGrid-Columns, create/delete secondary Indizes'}
// Here is the secondary-index create Procedure:
procedure TForm1.CreateSX(TableX: TTable; cFieldname: string);
begin
with TableX do begin
// table must be open with exclusive
Active := False;
Exclusive := True;
IndexDefs.Update;
Active := True;
// if Fieldname not exists create this secondary index new
if indexdefs.indexof(cFieldName) = -1 then begin
addindex(cFieldname, cFieldname, []);
end;
// close the table and reset exclusive
Active := false;
exclusive := False;
end;
end;
// Here is the secondary-index delete Procedure:
procedure TForm1.DeleteSX(TableX: TTable);
var
I: Integer;
begin
TableX.active := False;
TableX.IndexDefs.update;
// Look for all Indizes
for I := TableX.IndexDefs.Count - 1 downto 0 do begin
// ignore primary Index
if (TableX.IndexDefs.Items[I].options * [ixPrimary]) ([ixPrimary]) then
// This is an secondary index. Delete it.
TableX.DeleteIndex(TableX.IndexDefs.Items[I].fields);
end;
end;