Continuation of the article “Let’s be friends with tables”
The three most popular buttons in applications built with the My Visual Dtabase development environment are tabular data editing buttons: add, modify, and delete a record. They are usually found next to each table that the user intends to edit. Their functionality is determined by visual settings, and the creation takes a few seconds. But in our application there are only three editing buttons, so they will not be ordinary, but “heroic”. Such buttons will easily cope with all
These buttons are located on the main form (1) and have traditional names and pictures (2). But that’s where their similarity to standard buttons ends, as all their power lies in the scripts. And the power of scripts is in the conventions that must be observed when naming application forms.
Conventions
Conventions are rules that a developer sets for himself. This is a very useful practice that allows you to write efficient code. Details about this technique and various examples of its use are written in my book “Visual Programming”, Chapter 12. Good Deal .
The following are conventions that have helped in writing efficient code for edit buttons.
Names for table view forms
The name of the form must consist of the three-character prefix frm followed by the name of the table that the form is displaying. The table name may be followed by a suffix. The suffix is separated from the table name by an underscore and consists of an arbitrary number of characters. Thanks to the suffix, you can create several forms of a tabular
frm<table name>[_<suffix>]
For example, in our application, the classType table stores various information displayed by various forms: data about types (frmClassType_TypeList) and classes, and classes are represented as a list ( frmClassType_List) and as a tree (frmClassType_Tree).
Names for editing forms
The name of the editing form consists of the prefix efm and the name of the table that this form is intended to edit.
efm<table name>
Scripts
Adding a new record uses the form method NewRecord(). The name of the table is passed to it as the first parameter.
Note. The second parameter is used when creating child records in a tree structure, but it requires a component with certain settings on the editing form. Our application will use a different technology for adding to the tree.
procedure frmMain_btnNew_OnClick (Sender: TObject; var Cancel: boolean);
// addition
var
tmpID: integer;
tmpTableName: string;
tmpEditForm:TAForm;
tmpForm:TAForm;
begin
// if the tab with an example is open, then create an example
if frmMain.pgcMain.ActivePage = frmMain.tshExample then
begin
efmExample.NewRecord('example');
end
else // if the navigator tab is open and the user has selected a table, then we create an entry in the table
if (frmMain.pgcMain.ActivePage = frmMain.tshNavigation) and (ActiveGrid <> nil) then
begin
// define the name of the edited table using the form naming convention
// <frm><table name>[_<suffix>]
tmpTableName := Grid_GetTableName(ActiveGrid);
// use the convention for the edit form:
// the edit form is called by the template:
// <efm><table name>
tmpEditForm := App_GetFormByName('efm'+tmpTableName);
CForm(ActiveGrid,tmpForm);
// some tables depend on the main ones, so a check is needed
if not Form_CheckMasterForm(tmpForm.Name) then
ShowHint(ActiveGrid,'Select a record in the main table')
else
// open edit form
tmpEditForm.NewRecord(tmpTableName);
end;
end;
Code language: Delphi (delphi)
The editing procedure is also very elegant, and is based on the ShowRecord() form method, in which the table name and the number of the record being edited are passed as parameters.
procedure frmMain_btnEdit_OnClick (Sender: TObject; var Cancel: boolean);
// редактирование
var
tmpID: integer;
tmpTableName: string;
tmpEditForm:TAForm;
begin
if frmMain.pgcMain.ActivePage = frmMain.tshExample then
begin
if IDExample <> -1 then
begin
efmExample.ShowRecord('example',IDExample);
LoadExample;
end;
end
else
if frmMain.pgcMain.ActivePage = frmMain.tshNavigation then
begin
tmpID := ActiveGrid.dbItemID;
tmpTableName := Grid_GetTableName(ActiveGrid);
if tmpID = -1 then
ShowHint(ActiveGrid,'Select record')
else
begin
// we use the convention:
// the edit form is called by the template:
// <efm><table name>
tmpEditForm := App_GetFormByName('efm'+tmpTableName);
if tmpEditForm<>nil then
tmpEditForm.ShowRecord(tmpTableName, tmpID );
end;
end;
end;
Code language: Delphi (delphi)
Deletion looks similar to editing, but uses the SQL DELETE command in its work:
procedure frmMain_btnDelete_OnClick (Sender: TObject; var Cancel: boolean);
var
tmpID: string;
tmpTableName: string;
begin
if frmMain.pgcMain.ActivePage = frmMain.tshExample then
begin
if IDExample <> -1 then
if MessageBox( 'Delete example?', 'Delete', MB_YESNO + MB_ICONWARNING ) = mrYes then
begin
SQLExecute('delete from example where id = '+IntToStr(IDExample) );
UpdateDatabase('example');
end;
end
else
if (frmMain.pgcMain.ActivePage = frmMain.tshNavigation) and (ActiveGrid<>nil) then
begin
tmpID := IntToStr(ActiveGrid.dbItemID);
tmpTableName := Grid_GetTableName(ActiveGrid);
if tmpID = '-1' then
ShowHint(ActiveGrid,'Select record')
else
if MessageBox( 'Delete record?', 'Delete', MB_YESNO + MB_ICONWARNING ) = mrYes then
begin
SQLExecute('delete from '+tmpTableName+' where id = '+tmpID );
UpdateDatabase(tmpTableName);
end;
end;
end;
Code language: Delphi (delphi)
The above procedures use the key function Grid_GetTableName(). Its implementation looks very concise.
function Grid_GetTableName( AGrid: TdbStringGridEx ):string;
// возвращает имя таблицы
var
tmpForm:TAForm;
begin
// We use the naming convention of the form:
// <frm><table name>[_<suffix>]
// i.e. there can be multiple table view forms for one table,
// they must be distinguished by the suffix
CForm(AGrid,tmpForm);
Result := DeleteSuffix(DeleteClassName(tmpForm.Name));
end;
Code language: Delphi (delphi)
Note. When trying to create a similar function without using naming conventions, I found a bug in MVDB, namely: the TdbTreeView component in the dbGeneralTable property does not have the name of the table that it displays. This error prevented us from creating a universal function that would work both for tables and for a tree.
And here is another useful function used in the “heroic” buttons procedures, which returns the application form by name:
function App_GetFormByName(AName: string): TAForm;
// get form by name
var
tmpForm: TAForm;
i: integer;
begin
AName := UpperCase(AName);
for i := 0 to Screen.FormCount - 1 do
begin
Result := TAForm(Screen.Forms[i]);
if UpperCase(Result.Name) = AName then
exit;
end;
Result := nil;
end;
Code language: PHP (php)
To be continued…