© 2008 Ирина Цыбульникова
Для предприятий ЖКХ типичной задачей является ежемесячное выставление таких документов как счет-фактура, акт выполненных работ, платежное требование, акт сверки и некоторых других. В моей практике использовались два основных способа выставления:
Первый способ. Расчет производится индивидуально с каждым абонентом. В этом случае программа должна один (или несколько) раз в месяц сформировать комплект документов одному абоненту. Обычно комплект состоит из счета-фактуры, акта выполненных работ и платежного требования.
Второй способ. Расчет производится один раз в месяц сразу со всеми абонентами. В этом случае тот же комплект документов формируются уже в виде списка. Иногда к этому списку могут добавлять и другие документы, например, перечень счетов-фактур, реестры платежных требований, детальную расшифровку оказанных каждому абоненту услуг и пр.
Оба способа выставления встречаются примерно с одинаковой частотой. Цель этой статьи показать пример практического решения этой задачи. Будут использованы методы и примеры, описанные в статье Fast Report. Наследование на практике. Начнем с простого - с групповой печати.
Метод создания отчета для печати одному абоненту отличается от метода создания отчета для печати группе абонентов. Яркий пример — бэнды ReportTitle и ReportSummary. Представим вид документа "счет-фактура".

Если надо печатать счет-фактуру одному абоненту, то вполне можно использовать при построении отчета бэнды ReportTitle и ReportSummary, и это будет верное решение. Но если мы хотим печатать счета-фактуры сразу всем абонентам, то становится непонятно, какие надписи можно было бы поместить в заголовок и подвал отчета. Очевидно, для отчетов, предназначенных для групповой печати нужно другое решение. Вариант циклического выполнения метода OnClick кнопки "Печать" предлагаю не рассматривать. ![]()
Остается одно — построить такой универсальный отчет, который бы одинаково хорошо печатался и в индивидуальном и в групповом режиме. При этом я не буду использовать наследование от базового отчета BaseReport.fr3 (см. статью Наследование в Fast Report). Причин этому несколько, но главная из них в том, что создание комплекта документов — уникальная в своем роде задача, имеющая мало общего с созданием простых индивидуальных отчетов, для которых и был предназначен базовый отчет BaseReport.fr3.
Построить такой отчет не сложно. Сначала создадим форму заказа отчета.

Структура счета-фактуры предполагает показ данных из двух таблиц: заголовок документа и детализации документа. Наш отчет будет двухуровневым, и соответственно будет иметь два запроса связанных через TDataSource:
Затем создадим новый отчет и назовем его Invioces.fr3. В дизайнере отчета подключим источники данных. На страницу положим бэнд MasterData1 и подключим его к главному запросу idsFRReport. Это важный момент. Такая структура отчета обеспечит то, что наш отчет будет иметь столько страниц, сколько вернет главный запрос. Для того чтобы каждая счет-фактура выводилась на новой странице, выключим свойство PrintOnPreviousPage = False странице Page1. Затем добавим на отчет бэнд DetailData1, который подключим к зависимому запросу idsDtlInvoices. Этот бэнд должен располагаться под MasterData1. В итоге отчет "Счет-фактура" имеет следующий вид:

Запустим программу и увидим примерно такой результат:

Аналогично строятся и остальные отчеты для групповой печати. А с помощью ограничения, например по первичному ключу, в запросе idsFRReport, любой групповой отчет превращается в индивидуальный.
В некоторых случаях детализация счета-фактуры может быть пустой, тогда при печати мы получим чистую страницу. В этом случае надо бэнду MasterData1 установить свойство PrintIfDetailEmpty = True — это позволяет напечатать отчет с пустым списком услуг. Но и этого не достаточно, так как при печати будет видно только шапку отчета, но не будет видно итогов. Для этого изменим наш отчет, добавив группу по коду счета-фактуры. Высоту заголовка группы сделаем 0. Итоговую сумму и подписи перенесем с подвала данных на подвал группы. Теперь отчет будет иметь следующий вид:

Для демонстрации метода построения комплекта документов достаточно двух отчетов: счета-фактуры и акта выполненных работ. Используя описанный ниже метод можно при желании добавлять в комплект и любые другие документы.
Акт выполненных работ также как и счет-фактура имеет заголовок документа и детализацию. Добавим на форму заказа еще два запроса связанных через TDataSource. Также добавим два флажка, для того чтобы пользователь мог интерактивно формировать содержимое комплекта и поле для ввода количества копий.

Затем сделаем отчет "Счет-фактура" многостраничным, выбрав команду меню дизайнера отчетов "Файл"+"Новая страница". На второй странице построим отчет "Акт выполненных работ". Многостраничный отчет позволит печать либо счета-фактуры, либо акты выполненных работ, либо оба эти документа вместе. Теперь флажками на форме заказа будем управлять страницами отчета. Обратиться к объекту "страница" из Delphi можно с помощью метода TfrxReport.FindObject. Например, так:
VPageInv := FMainReport.FindObject('Page1') as TfrxPage;
if Assigned(VPageInv) then
VPageInv.Visible:= cbInvoice.Checked;
VPageAct := FMainReport.FindObject('Page2') as TfrxPage;
if Assigned(VPageAct) then
VPageAct.Visible := cbAct.Checked;
Печать комплекта документов для одного абонента будет выглядеть следующим образом:

Для того чтобы печатать комплекты документов списку абонентов надо сделать еще некоторые действия. Применим метод пакетной печати и сделаем печать документов в цикле. Использовать тот же метод, что и для одного абонента мы не можем так как, будут печататься сначала все счета-фактуры, а затем все акты.
Для организации цикла по абонентам на форму заказа положим еще один компонент типа TIBDataSet. В каждой итерации цикла для текущего абонента будем формировать комплект документов. Но при этом вместо метода TfrxReport.ShowReport используем метод TfrxReport.PrepareReport для добавления очередного комплекта в окно предварительного просмотра. По завершению цикла получим комплект документов уже разложенный по абонентам.
Для усложнения задачи вместе с комплектом документов напечатаем еще один документ — "Реестр счетов-фактур". Так как этот документ не входит в комплект одного абонента, то нет смыла создавать его на новой странице шаблона Invoice.fr3. Создадим его на отдельном отчете наследованном от базового отчета BaseReport.fr3. Для загрузки двух разных отчетов в одно окно просмотра также будем использовать метод TfrxReport.PrepareReport. Схему пакетной печати можно представить в следующем виде:

Использование цикла несколько замедлило печать документов, по сравнению с групповой печатью, но зато этот способ позволяет добиться самого удобного для пользователя результата.
К статье приложен архив example.zip с примерами, описанными в статье.
Copyright© 2008 Ирина Цыбульникова Специально для Delphi Plus