Отчет с двумя уровнями данных (master-detail)

 До сих пор мы рассматривали отчеты, в которых присутствовал только один дата-бэнд – "Данные 1 уровня". Это давало возможность печатать данные из одной таблицы БД. FastReport позволяет печатать отчеты, содержащие до 6 уровней данных (можно и больше, используя объект "Вложенный отчет", но об этом позже). В реальных приложениях  редко приходится печатать отчеты с большой вложенностью данных; как правило, ограничиваются 1-3 уровнями.

 

 Рассмотрим создание двухуровневого отчета. Он будет содержать данные из таблиц Customer и Orders. Первая таблица – это список клиентов, вторая – список заказов, сделанных клиентами. Таблицы содержат данные следующего вида:

 

Customer:

 

CustNo        Company

1221                Kauai Dive Shoppe

1231                Unisco

1351                Sight Diver

….

 

Orders:

 

OrderNo        CustNo        SaleDate

1003                1351                12.04.1988

1023                1221                01.07.1988

1052                1351                06.01.1989

1055                1351                04.02.1989

1060                1231                28.02.1989

1123                1221                24.08.1993

….

 

 Как видно, вторая таблица содержит список всех заказов, сделанных всеми компаниями. Чтобы получить список заказов, сделанных конкретной компанией, из таблицы следует отобрать записи, у которых поле CustNo = номеру выбранной компании. Отчет, построенный на таких данных, будет выглядеть следующим образом:

 

1221                Kauai Dive Shoppe

 1023                  01.07.1988

 1123                  24.08.1993

 

1231                Unisco

 1060                  28.02.1989

 

1351                Sight Diver

 1003                  12.04.1988

 1052                  06.01.1989

 1055                  04.02.1989

 

 Приступим к созданию отчета. Создадим новый проект в Delphi, на форму положим два компонента TTable, компонент TDataSource, два компонента TfrxDBDataSet и один TfrxReport. Настроим компоненты следующим образом:

 

Table1:

DatabaseName = 'DBDEMOS'

TableName = 'Customer.db'

 

Table2:

DatabaseName = 'DBDEMOS'

TableName = 'Orders.db'

 

DataSource1:

DataSet = Table1

 

frxDBDataSet1:

DataSet = Table1

UserName = 'Customers'

 

frxDBDataSet2:

DataSet = Table2

UserName = 'Orders'

 

 В дизайнере отчета подключим наши источники данных в окне "Отчет|Данные…". Положим на страницу бэнды "Данные 1 уровня" и "Данные 2 уровня":

 

_img133

 

 Обратите внимание – бэнд "Данные 1 уровня" должен располагаться выше! Если разместить его под бэндом "Данные 2 уровня", FastReport сообщит об ошибке при запуске отчета.

 

 Если сейчас запустить отчет, мы увидим, что список заказов одинаковый для каждого клиента и содержит все записи из таблицы Orders. Это произошло потому, что мы не включили фильтрацию записей в таблице Orders. Вернемся к нашим источникам данных. У компонента Table2 установим свойство MasterSource = DataSource1. Таким образом мы установили связь "главный-подчиненный". Теперь надо задать условие фильтрации записей в подчиненном источнике. Для этого вызовите редактор свойства MasterFields у компонента Table2:

 

_img134

 

 Нам надо связать два поля CustNo в обоих источниках. Для этого выберите индекс CustNo в списке сверху, выберите поля и нажмите кнопку "Add". Связка полей переместится в нижнее окно. После этого закройте редактор кнопкой ОК.

 

 При запуске отчета FastReport сделает следующее. Выбрав очередную запись из главной таблицы (Customer), он установит фильтр на подчиненную таблицу (Orders). В таблице останутся только те записи, которые удовлетворяют условию Orders.CustNo = Customer.CustNo. Т.е. для каждого клиента будут показаны только его заказы:

 

_img135

 

 Аналогичным образом можно строить отчеты, содержащие до 6 уровней данных.