Менеджер отчётов

Общий смысл написания этой статьи состоит в том, чтобы показать, как можно легко управлять большим количеством отчётов в своей программе для определённой категории. Сама идея такой реализации использовании отчётов родилась давно, но реализовать её пришлось только недавно на своём проекте АРМ: Торговля и склад.
Сам проект, конечно, предоставлять не буду, так он коммерческий, а во-вторых “увесистый”. Но суть самого проекта, да и идеи создания менеджера отчётов распишу вкратце. Суть самого проекта заключается в реализации программного обеспечения для работы как на складе, так и на кассе (в торговом зале). Раз есть модуль склад, то он в себе подразумевает группу документов: приходные документы, расходные документы, списание товара, возврат товара, продажи по кассе и т.д. И к каждой группе документов соответствуют свои отчёты. Например, к приходным и расходным документам относятся такие отчёты как “Приходная и расходная накладная”, “Печать ценников на оприходованный товар”, к списанию товара или передачи в другой отдел соответствуют такие отчёты как “Акт на списание”, “Накладная на списание”; к документам Продажи по кассе соответствуют “Список чеков на дату”, “Справка отчёт кассира – операциониста” и т.д. Как видно из перечисляемых отчётов, их просто большое количество, а как для определённого документа выполнить тот или иной отчёт? Для этого и сделан менеджер отчётов.

Ну в общем случае, картину действий я описал, теперь приступим к реализации задуманного.

Для этого первоначально необходимо определить структуру таблички, в которой будут храниться как физические названия, так и описание отчётов. В моём случае табличка называется RPT_LIST и имеет следующую структуру:
ID_RPT // нумерация позиций отчётов
NAME_RPT //название отчёта
COMMENT_RPT // комментарий для отчёта
VALUE_RPT // значение, которому будет соответствовать тип операции
NAME_RPT_SHOT // физическое название отчёта

DDL таблицы

CREATE TABLE RPT_LIST (
ID_RPT INTEGER NOT NULL,
NAME_RPT VARCHAR(50) NOT NULL,
COMMENT_RPT VARCHAR(255) NOT NULL,
VALUE_RPT INTEGER NOT NULL,
NAME_RPT_SHORT VARCHAR(50) NOT NULL
);

Так со структурой разобрались, теперь перейдём к части проектирования проекта.

Создадим новый проект, на форму бросим Panel, на панели разместим три кнопки и назовём их btnPreview, btnPrint, btnExit. Также на форме разместим DBGrid и DBMemo. Выставим нужные Align у компонентов так, как это показано на рисунке 1.

рис. 1

Создадим DataMoule и бросим туда IBDataBase, IBTransaction, IBQuery, DataSources. Свяжем их, как обычно (подробно, смотрите в примере). Теперь дело осталось за малым: написать код и разобраться с алгоритмом действий.

Алгоритм действий очень прост: при открытии формы, в DBGrid’е формируется список отчётов в зависимости от выбранного типа операции. В нашем случае за тип операций отвечают RatioButton’s и по умолчанию выбран тип “Приход”. При выборе в гриде необходимого отчёта, в DBMemo отображается краткое описание для выбранного отчёта. Выбранный отчёт можно как просмотреть в предварительном просмотре, так и сразу вывести на печать.

С алгоритмом действий разобрались. Идём дальше…

В написании кода вообще ничего военного нет, всё очень просто.

Полный код проекта предоставлен ниже:

Код модуля DataModule (назван в примере dm)

 Tdm.DataModuleCreate(Sender: TObject);
begin
// вызываем процедуру подключения БД
frmMain.OpenBD;
// Открываем DataSet для первичного формирования группы отчётов
// для определённого типа операции
IRep.Open;
end;

Код главной формы frmMain

//процедура, которая отвечает за динамическое подключение БД
procedure TfrmMain.OpenBD;
begin
//путь до БД
dm.IBDatabase.DatabaseName := ExtractFilePath(Application.ExeName)+'\base.fdb';

with dm do
begin
try
IBDatabase.Connected := True;
IBTransaction.Active := True;
except
on E:Exception do
begin
Application.MessageBox(PChar('Не удалось подключиться к серверу!' +
#10#13+#10#13 + e.Message),'Пример',MB_OK + MB_ICONERROR);
Close;
end;
end;
end;
end;

procedure TfrmMain.RadioButton1Click(Sender: TObject);
begin
with dm.IRep do
begin
close;
sql.Clear;
sql.Text := 'select * from rpt_list where value_rpt = ' + QuotedStr(IntToStr((Sender as TRadioButton).Tag));
Open;
end;
end;

//кнопка просмотра
procedure TfrmMain.btnPreviewClick(Sender: TObject);
begin
//Создаём объект
Rep := TfrxReport.Create(self);
//загружаем отчёт
Rep.LoadFromFile(ExtractFilePath(Application.ExeName)+dm.IRep.FieldByName('name_rpt_short').AsString);
//просмотр отчёта
if rep.PrepareReport then
rep.ShowPreparedReport;
//освобождаем память
rep.Free;
end;

procedure TfrmMain.btnExitClick(Sender: TObject);
begin
Close;
end;

// кнопка печати
procedure TfrmMain.btnPrintClick(Sender: TObject);
begin
//Создаём объект
Rep := TfrxReport.Create(self);
//загружаем отчёт
Rep.LoadFromFile(ExtractFilePath(Application.ExeName)+dm.IRep.FieldByName('name_rpt_short').AsString);
//печать отчёта
if Rep.PrepareReport then
Rep.Print;
//освобождаем память
Rep.Free;
end; 

Ну, вот в принципе и вся задумка по этому делу.

Полный вид написанного выше выглядит как на рисунке 2

рис. 2

Все описанные в статье примеры можно посмотреть в архиве example.zip (841K).

База данных создавалась на СУБД FireBird 1.5.4. Для работы примера, необходимо чтобы СУБД была установлена!!!

Copyright© 2008 Савельев Андрей  Специально для Delphi Plus

Comments are closed.