Построение приложений локальных баз данных средствами delphi

Цель работы: научиться разрабатывать клиентские приложения в среде Delphi для управления базами данных.

Порядок выполнения работы

1. Постановка задачи. В среде Delphi разработать проект клиентского приложения для управления базой данных «Поваренная книга» (см. задания к лабораторной работе № 15).

2. Создать следующие формы:

MainForm (модуль MainUnit),

RecipeForm (модуль RecipeUnit),

FoodForm (модуль FoodUnit),

ComponentForm (модуль ComponentUnit),

ListCalcForm (модуль ListCalcUnit).

3. Расположить и настроить компоненты на формах.

3.1. На форме MainForm:

FoodGrid: TDBGrid

Align = alBottom

DataSouce = FoodDataSource

Splitter1: TSplitter

Align = alBottom

RecipesGrid: TDBGrid

Align = alLeft

DataSouce = RecipesDataSource

Splitter2: TSplitter

Align = alLeft

ComponentsGrid: TDBGrid

Align = alClient

DataSouce = ComponentsDataSource

CookBookConnection: TADOConnection

LoginPrompt = False

FoodTable: TADOTable

Connection = CookBookConnection

TableName = Food

RFLinksTable: TADOTable

Connection = CookBookConnection

TableName = RF_Links

CategoryTable: TADOTable

Connection = CookBookConnection

TableName = Categories

RecipesTable: TADOTable

Connection = CookBookConnection

TableName = Recipes

ComponentsQuery: TADOQuery

Connection = CookBookConnection

RecipesQuery: TADOQuery

Connection = CookBookConnection

SQL =

select Recipes.ID, R_Name, Persons, C_Name, Category_ID

from Recipes, Categories

where Category_ID=Categories.ID

order by R_Name

OpenDBDialog: TOpenDialog

Filter = Файлы Access|*.mdb

FoodDataSource: TDataSource

DataSet = FoodTable

RecipesDataSource: TDataSource

DataSet = RecipesQuery

ComponentsDataSource: TDataSource

DataSet = ComponentsQuery

CookBookMenu: TMainMenu

Создание элементов меню:

Группа Пункт (Name) Подпись (Caption)
Файл OpenDBItem Открыть БД
CloseDBItem Закрыть БД
ExitItem Выход
Таблицы NewRecipeItem Новый рецепт
EditRecipeItem Изменить рецепт
AddFoodItem Добавить продукт к рецепту
RemoveFoodItem Убрать продукт из рецепта
EditQuantityItem Изменить количество продукта
DeleteRecipeItem Удалить рецепт
NewFoodItem Новый продукт
EditFoodItem Изменить продукт
DeleteFoodItem Удалить продукт
Сервис ListCalcItem Расчет сметы

3.2. На форме RecipeForm:

Label1: TLabel

Caption = Название:

Label2: TLabel

Caption = Персон:

Label3: TLabel

Caption = Категория:

NameEdit: TEdit

PersonsEdit: TEdit

CategoryCombo: TComboBox

OKButton: TButton

Caption = ОК

CancelButton: TButton

Caption = Отмена

3.3. На форме FoodForm:

Label1: TLabel

Caption = Название:

Label2: TLabel

Caption = Калорийность:

Label3: TLabel

Caption = Цена

NameEdit: TEdit

EnergyEdit: TEdit

PriceEdit: TEdit

OKButton: TButton

Caption = ОК

CancelButton: TButton

Caption = Отмена

3.4. На форме ComponentForm:

Label1: TLabel

Caption = Количество продукта:

QuantityEdit: TEdit

OKButton: TButton

Caption = ОК

CancelButton: TButton

Caption = Отмена

3.5. На форме ListCalcForm

Label1: TLabel

Caption = Количество персон:

PersonsEdit: TEdit

LCGrid: TStringGrid

ColCount = 2

FixedCols = 0

UpdateButton: TButton

Caption = Обновить

OKButton: TButton

Caption = Закрыть

4. Создать обработчики событий для компонентов формы, определить глобальные переменные, подключить необходимые библиотеки. Тексты модулей для форм приводятся в нижеследующих листингах.

4.1. Листинг модуля MainUnit:

unit MainUnit;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, ExtCtrls, Grids, DBGrids, Menus, DB, ADODB, FoodUnit, RecipeUnit,

ComponentUnit, ListCalcUnit;

type

TMainForm = class(TForm)

FoodGrid: TDBGrid;

Splitter1: TSplitter;

RecipesGrid: TDBGrid;

Splitter2: TSplitter;

ComponentsGrid: TDBGrid;

CookBookMenu: TMainMenu;

CookBookConnection: TADOConnection;

N1: TMenuItem;

N2: TMenuItem;

N3: TMenuItem;

OpenDBItem: TMenuItem;

CloseDBItem: TMenuItem;

N5: TMenuItem;

ExitItem: TMenuItem;

NewRecipeItem: TMenuItem;

EditRecipeItem: TMenuItem;

NewFoodItem: TMenuItem;

EditFoodItem: TMenuItem;

N4: TMenuItem;

ListCalcItem: TMenuItem;

OpenDBDialog: TOpenDialog;

FoodTable: TADOTable;

RecipesQuery: TADOQuery;

RecipesDataSource: TDataSource;

ComponentsDataSource: TDataSource;

FoodDataSource: TDataSource;

RFLinksTable: TADOTable;

ComponentsQuery: TADOQuery;

AddFoodItem: TMenuItem;

RemoveFoodItem: TMenuItem;

EditQuantityItem: TMenuItem;

DeleteFoodItem: TMenuItem;

DeleteRecipeItem: TMenuItem;

CategoryTable: TADOTable;

RecipesTable: TADOTable;

procedure OpenDBItemClick(Sender: TObject);

procedure ComponentsSync(RID: Integer);

procedure RecipesQueryAfterScroll(DataSet: TDataSet);

procedure CloseDBItemClick(Sender: TObject);

procedure NewFoodItemClick(Sender: TObject);

procedure EditFoodItemClick(Sender: TObject);

procedure DeleteFoodItemClick(Sender: TObject);

procedure NewRecipeItemClick(Sender: TObject);

procedure EditRecipeItemClick(Sender: TObject);

procedure DeleteRecipeItemClick(Sender: TObject);

procedure AddFoodItemClick(Sender: TObject);

procedure RemoveFoodItemClick(Sender: TObject);

procedure EditQuantityItemClick(Sender: TObject);

procedure ListCalcItemClick(Sender: TObject);

procedure ExitItemClick(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.ComponentsSync(RID: Integer);

begin

with ComponentsQuery do

begin

Close;

SQL.Clear;

SQL.Add('select RF_Links.ID, F_Name, Quantity');

SQL.Add('from Food, Recipes, RF_Links ');

SQL.Add('where Recipe_ID='+IntToStr(RID));

SQL.Add('and Food_ID=Food.ID');

SQL.Add('and Recipe_ID=Recipes.ID');

SQL.Add('order by Quantity desc');

Open;

end;

end;

procedure TMainForm.OpenDBItemClick(Sender: TObject);

begin

if (OpenDBDialog.Execute) then

begin

CookBookConnection.ConnectionString:=

'Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+

OpenDBDialog.FileName;

if CookBookConnection.Connected then

begin

ShowMessage('База уже открыта’);

Exit;

end;

CookBookConnection.Open;

RecipesQuery.Open;

RFLinksTable.Open;

FoodTable.Open;

CategoryTable.Open;

RecipesTable.Open;

ComponentsSync(RecipesQuery.FieldValues['id']);

end;

end;

procedure TMainForm.RecipesQueryAfterScroll(DataSet: TDataSet);

begin

if RFLinksTable.Active and ComponentsQuery.Active then

ComponentsSync(RecipesQuery.FieldValues['id']);

end;

procedure TMainForm.CloseDBItemClick(Sender: TObject);

begin

CookBookConnection.Close;

end;

procedure TMainForm.NewFoodItemClick(Sender: TObject);

begin

with FoodForm do

begin

Caption:='Новый продукт;

NameEdit.Clear;

EnergyEdit.Clear;

PriceEdit.Clear;

if ShowModal=mrOK then

with FoodTable do

begin

Append;

FieldValues['F_Name']:=NameEdit.Text;

FieldValues['Energy']:=StrToFloat(EnergyEdit.Text);

FieldValues['Price']:=StrToFloat(PriceEdit.Text);

Post;

end;

end;

end;

procedure TMainForm.EditFoodItemClick(Sender: TObject);

begin

with FoodForm do

begin

Caption:=’Изменение продукта’;

NameEdit.Text:=FoodTable.FieldValues['F_Name'];

EnergyEdit.Text:=FoodTable.FieldValues['Energy'];

PriceEdit.Text:=FoodTable.FieldValues['Price'];

if ShowModal=mrOK then

with FoodTable do

begin

Edit;

FieldValues['F_Name']:=NameEdit.Text;

FieldValues['Energy']:=StrToFloat(EnergyEdit.Text);

FieldValues['Price']:=StrToFloat(PriceEdit.Text);

Post;

end;

end;

end;

procedure TMainForm.DeleteFoodItemClick(Sender: TObject);

begin

if (MessageBox(Handle, ‘Удалить продукт?’,

‘Удаление продукта’, MB_YESNO)=IDYES) then

FoodTable.Delete;

end;

procedure TMainForm.NewRecipeItemClick(Sender: TObject);

var i: Integer;

cids: array of Integer;

begin

with RecipeForm do

begin

Caption:='Новый рецепт';

NameEdit.Clear;

PersonsEdit.Clear;

CategoryCombo.Clear;

CategoryTable.First;

SetLength(cids, CategoryTable.RecordCount);

for i:=0 to CategoryTable.RecordCount-1 do

begin

CategoryCombo.Items.Add(CategoryTable.FieldValues['C_Name']);

cids[i]:=CategoryTable.FieldValues['ID'];

CategoryTable.Next;

end;

if ShowModal=mrOK then

with RecipesTable do

begin

Append;

FieldValues['R_Name']:=NameEdit.Text;

FieldValues['Persons']:=StrToFloat(PersonsEdit.Text);

FieldValues['Category_ID']:=cids[CategoryCombo.ItemIndex];

Post;

end;

end;

RecipesQuery.Requery;

Finalize(cids);

end;

procedure TMainForm.EditRecipeItemClick(Sender: TObject);

var i: Integer;

cids: array of Integer;

begin

with RecipeForm do

begin

Caption:='Изменение рецепта';

NameEdit.Text:=RecipesQuery.FieldValues['R_Name'];

PersonsEdit.Text:=RecipesQuery.FieldValues['Persons'];

CategoryCombo.Clear;

CategoryTable.First;

SetLength(cids, CategoryTable.RecordCount);

for i:=0 to CategoryTable.RecordCount-1 do

begin

CategoryCombo.Items.Add(CategoryTable.FieldValues['C_Name']);

cids[i]:=CategoryTable.FieldValues['ID'];

if (CategoryTable.FieldValues['ID']=

RecipesQuery.FieldValues['Category_ID']) then

CategoryCombo.ItemIndex:=i;

CategoryTable.Next;

end;

if ShowModal=mrOK then

with RecipesTable do

begin

Locate('ID', RecipesQuery.FieldValues['ID'], []);

Edit;

FieldValues['R_Name']:=NameEdit.Text;

FieldValues['Persons']:=StrToFloat(PersonsEdit.Text);

FieldValues['Category_ID']:=cids[CategoryCombo.ItemIndex];

Post;

end;

end;

RecipesQuery.Requery;

Finalize(cids);

end;

procedure TMainForm.DeleteRecipeItemClick(Sender: TObject);

begin

RecipesTable.Locate('ID', RecipesQuery.FieldValues['ID'], []);

RecipesTable.Delete;

RecipesQuery.Requery;

end;

procedure TMainForm.AddFoodItemClick(Sender: TObject);

begin

with ComponentForm do

begin

Caption:='Добавление продукта';

QuantityEdit.Clear;

if ShowModal=mrOK then

begin

with RFLinksTable do

begin

Append;

FieldValues['Recipe_ID']:=RecipesQuery.FieldValues['ID'];

FieldValues['Food_ID']:=FoodTable.FieldValues['ID'];

FieldValues['Quantity']:=QuantityEdit.Text;

Post;

end;

end;

end;

ComponentsQuery.Requery;

end;

procedure TMainForm.RemoveFoodItemClick(Sender: TObject);

begin

RFLinksTable.Locate('ID', ComponentsQuery.FieldValues['ID'], []);

RFLinksTable.Delete;

ComponentsQuery.Requery;

end;

procedure TMainForm.EditQuantityItemClick(Sender: TObject);

begin

with ComponentForm do

begin

Caption:='Изменение количества';

QuantityEdit.Text:=ComponentsQuery.FieldValues['Quantity'];

if ShowModal=mrOK then

begin

with RFLinksTable do

begin

Locate('ID', ComponentsQuery.FieldValues['ID'], []);

Edit;

FieldValues['Recipe_ID']:=RecipesQuery.FieldValues['ID'];

FieldValues['Food_ID']:=FoodTable.FieldValues['ID'];

FieldValues['Quantity']:=QuantityEdit.Text;

Post;

end;

end;

end;

ComponentsQuery.Requery;

end;

procedure TMainForm.ListCalcItemClick(Sender: TObject);

var i: Integer;

begin

with ComponentsQuery do

begin

lcp:=RecipesQuery.FieldValues['Persons'];

SetLength(lc, RecordCount);

First;

ListCalcForm.Caption:='Смета на '+IntToStr(lcp)+' персон';

ListCalcForm.LCGrid.ColWidths[0]:=200;

ListCalcForm.LCGrid.ColWidths[1]:=100;

ListCalcForm.LCGrid.RowCount:=lcp+1;

ListCalcForm.LCGrid.Cells[0, 0]:='Продукт';

ListCalcForm.LCGrid.Cells[1, 0]:='Количество';

for i:=0 to RecordCount-1 do

begin

ListCalcForm.LCGrid.Cells[0, i+1]:=FieldValues['F_Name'];

ListCalcForm.LCGrid.Cells[1, i+1]:=IntToStr(FieldValues['Quantity']);

lc[i]:=FieldValues['Quantity'];

Next;

end;

end;

ListCalcForm.ShowModal;

Finalize(lc);

end;

procedure TMainForm.ExitItemClick(Sender: TObject);

begin

Close;

end;

end.

4.2. Листинг модуля FoodUnit:

unit FoodUnit;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TFoodForm = class(TForm)

NameEdit: TEdit;

Label1: TLabel;

PriceEdit: TEdit;

Label2: TLabel;

EnergyEdit: TEdit;

Label3: TLabel;

CancelButton: TButton;

OKButton: TButton;

procedure OKButtonClick(Sender: TObject);

procedure CancelButtonClick(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

FoodForm: TFoodForm;

implementation

{$R *.dfm}

procedure TFoodForm.OKButtonClick(Sender: TObject);

begin

ModalResult:=mrOK;

end;

procedure TFoodForm.CancelButtonClick(Sender: TObject);

begin

ModalResult:=mrCancel;

end;

end.

4.3. Листинг модуля RecipeUnit:

unit RecipeUnit;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TRecipeForm = class(TForm)

NameEdit: TEdit;

Label1: TLabel;

PersonsEdit: TEdit;

Label2: TLabel;

Label3: TLabel;

CategoryCombo: TComboBox;

CancelButton: TButton;

OKButton: TButton;

procedure CancelButtonClick(Sender: TObject);

procedure OKButtonClick(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

RecipeForm: TRecipeForm;

implementation

{$R *.dfm}

procedure TRecipeForm.CancelButtonClick(Sender: TObject);

begin

ModalResult:=mrCancel;

end;

procedure TRecipeForm.OKButtonClick(Sender: TObject);

begin

ModalResult:=mrOK;

end;

end.

4.4. Листинг модуля ComponentUnit:

unit ComponentUnit;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TComponentForm = class(TForm)

QuantityEdit: TEdit;

Label1: TLabel;

CancelButton: TButton;

OKButton: TButton;

procedure OKButtonClick(Sender: TObject);

procedure CancelButtonClick(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

ComponentForm: TComponentForm;

implementation

{$R *.dfm}

procedure TComponentForm.OKButtonClick(Sender: TObject);

begin

ModalResult:=mrOK;

end;

procedure TComponentForm.CancelButtonClick(Sender: TObject);

begin

ModalResult:=mrCancel;

end;

end.

1.1. Листинг модуля ListCalcUnit:

unit ListCalcUnit;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, Grids, Math;

type

TListCalcForm = class(TForm)

OKButton: TButton;

Label1: TLabel;

PersonsEdit: TEdit;

UpdateButton: TButton;

LCGrid: TStringGrid;

procedure OKButtonClick(Sender: TObject);

procedure UpdateButtonClick(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

ListCalcForm: TListCalcForm;

lc: array of Real;

lcp: Integer;

implementation

{$R *.dfm}

procedure TListCalcForm.OKButtonClick(Sender: TObject);

begin

ModalResult:=mrOK;

end;

procedure TListCalcForm.UpdateButtonClick(Sender: TObject);

var c: Real;

i: Integer;

begin

c:=StrToInt(PersonsEdit.Text)/lcp;

LCGrid.RowCount:=Length(lc)+1;

for i:=0 to Length(lc)-1 do

begin

lc[i]:=RoundTo(lc[i]*c, -2);

LCGrid.Cells[1, i+1]:=FloatToStr(lc[i]);

end;

lcp:=StrToInt(PersonsEdit.Text);

end;

end.

Содержание отчета

Программа с учетом основных рекомендаций.

Вопросы для самопроверки

1. Опишите схему получения клиентским приложением данных из БД с помощью технологии ADO.

2. Какие способы доступа к полям таблицы посредством компонента TADOTable вы знаете?

3. Что произойдет при удалении записи из таблицы продуктов, если ссылка на этот продукт присутствует в связанной таблице рецептов?

4. Зачем необходимо использовать метод Post при записи в таблицу?

5. В чем состоит необходимость использования метода Requery в тексте листингов?

Лабораторная работа № 6

Наши рекомендации