Помощь Выход

Глава 7. Печать нескольких отчетов на одной странице

Если отчеты невелики по объему и их может поместиться более одного на странице, то вполне естественным желанием является печатать несколько отчетов на одной странице. Как правило, при этом используется альбомная ориентация страницы, которая выбирается в диалоге Файл\Параметры страницы на вкладке Страница. Кроме того, на вкладке Столбцы можно указать число столбцов (аналогично многоколонной верстке в Word; по умолчанию 1), размещаемых на одной странице, их ширину и величину интервала между столбцами и строками отчета (т.е. расстояние между отчетами по вертикали). Чтобы каждый следующий отчет начинался с нового столбца для соответствующего раздела отчета (например, примечания группы), устанавливается свойство Новая строка или столбец, а не Конец страницы.

Реализация печати двух накладных на одной странице показана на рисунке; необходимые для этого параметры страницы представлены на рисунке ниже. Разумеется, ширина отчета в режиме конструктора должна быть такой, чтобы имелась возможность разместить два столбца на одной странице. Например, для бумаги формата А4 ширина столбца может составлять 13-14 см для альбомной ориентации страницы. Если столбец не помещается целиком на странице по горизонтали, информация будет обрезана и напечатана не будет. Можно выполнить «обрезку» самостоятельно, если убрать флажок «по размеру данных» в параметрах страницы и задать ширину столбца меньше, чем реально имеющаяся ширина отчета.

Заметим, что параметры страницы сохраняются с каждым отчетом и могут отличаться для разных отчетов.

Если требуется каждый отчет напечатать в нескольких экземплярах, число копий можно указать в диалоге Файл\Печать.... Кроме того, можно дополнительно использовать опцию «разобрать по копиям», тогда два экземпляра одного и того же отчета будут находиться на соседних страницах.

Как же поступить в том случае, если источника записей для отчета не существует, а требуется просто напечатать несколько пустых бланков для заполнения вручную с максимальной экономией бумаги? В данном случае можно назначить любую таблицу или запрос в качестве источника записей, несмотря на то, что отчет не будет содержать ни одного элемента управления, связанного с полями этого источника записей. Число записей в этой таблице или запросе и будет определять количество отчетов для печати. Поскольку требуется полностью заполнить страницу бланками, необходимое число записей должно быть не меньше числа бланков, размещаемых на одной странице отчета. Точного равенства не требуется, т.к. достаточно сформировать лишь одну заполненную страницу и при печати задать требуемое число экземпляров этой страницы. Желательно, чтобы число записей не было слишком велико, иначе форматирование отчета займет больше времени.

Печать отчета, количество экземпляров которого определяется значением в некотором поле

Теперь решим задачу печати этикеток или ценников, которые, например, должны клеиться на каждую упаковку. Число упаковок нам известно, т.к. оно хранится в поле Кол_во_упак базы данных, а также выводится на форме Прием товаров, где уместно организовать печать этикеток. При этом, как и в предыдущей задаче, требуется печатать максимальное число отчетов на одной странице.

Непосредственно свести эту задачу к рассмотренной ранее задаче печати квитанций нельзя, поскольку число экземпляров заранее неизвестно. Более того, это количество может меняться от записи к записи. Поэтому создадим сначала таблицу, в которую программным образом будем вводить такое количество строк, сколько упаковок имеется в наличии для данного товара. Эта таблица (назовем ее Число ценников), которая определяет число копий, должна иметь поле внешнего ключа КодТовара для связи с таблицей Товары. Нужно, чтобы это поле содержало такое количество одинаковых значений для каждого товара, которое определяется количеством упаковок. Тогда при связи этих двух таблиц в запросе, который и будет источником данных для отчета-ценника, мы получим нужное количество записей на каждый товар, для которого будут печататься ценники. Информацию в таблицу Число ценников будем вводить программно, используя для этого процедуру VBA, связанную с событием печати отчета. Однако сначала конкретизируем задачу и построим запрос, решающий проблему для одной из записей.


Внимание

Таблицу Число ценников лучше хранить локально в файле приложения, а не использовать связанную таблицу. Это позволит одновременно печатать отчет для разных товаров на разных компьютерах, где будут установлены копии приложения, т.к. содержимое этой таблицы может быть разным и не вызывать конфликта при одновременной работе.

На рисунке изображены таблица Товары, содержащая используемые в отчете записи, и таблица Число ценников, содержащая в данный момент пять одинаковых строк. Количество этих строк и задает число ценников (по числу упаковок) для товара с кодом 186. Для большей наглядности в таблицу Число ценников добавлено еще одно необязательное числовое поле Количество, как бы говорящее о том, что мы будем печатать по одному ценнику на каждую упаковку.

Если связать теперь эти таблицы в запросе, то мы получим требуемый источник записей для печати отчета (пока только для одной конкретной записи)

Размер отчета (ценника) фиксирован и не зависит от записи. Поэтому в параметрах страницы можно точно указать максимальное число столбцов, определяемое числом этикеток, помещающихся на странице по горизонтали.

Отчет содержит два поля Наименование и Цена_розн, а источником данных для него, естественно, является запрос Запрос для ценников.

Чтобы напечатать требуемое число таких ценников, будем формировать строки таблицы Число ценников. Прежде чем перейти к наполнению данными этой таблицы, заметим только, что для более экономного использования бумаги можно организовать печать отчета не для одной записи (одного товара), а для группы записей, скажем, партии товара, определяемой накладной на прием. Так мы и поступим, причем будем печатать ценники одновременно с печатью накладной на прием, т.е. дополним событийную процедуру для кнопки печати накладных необходимыми программными кодами.

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


Set rst = CurrentDb.OpenRecordset("Число ценников", Dynaset)
With rst
Do While Not .EOF
.Delete
.MoveNext
Loop
End With

Здесь сначала создается динамический набор записей rst из таблицы Число ценников, а затем в цикле по всем записям выполняется удаление записей таблицы. Для удаления записей используется метод Delete и цикл Do While. Эту операцию можно также выполнить при помощи запроса на удаление, сформулированного на языке SQL:


DoCmd.RunSQL "DELETE FROM [Число ценников]"

Напомним, что справочная информация об операторах языка VBA содержится в приложении 3.2. Операторы манипуляции данными языка SQL рассматриваются в главах 11 и 12.

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


CritStr = "[Поставщик]="
Поставщик_
_
" and [Дата_поступления]=#"
Format([Дата_поступления], "mm-dd-yy")
"#"
Set rstOr = CurrentDb.OpenRecordset("Select * from Товары where "
CritStr)

Заметим, что при создании набора записей rstOr используется формулировка запроса на языке SQL. Теперь, зная число упаковок каждого товара из накладной, мы заново сформируем таблицу Число ценников, используя для этого динамический набор записей rst. Как видно из приведенного ниже фрагмента, таблица формируется для всех товаров, составляющих накладную (цикл по всем записям rstOr). При добавлении записей используется метод AddNew.


Do While Not rstOr.EOF
For i = 1 To rstOr![Кол_во_упак]
rst.AddNew

rst!КодТовара = rstOr![Код_товара]
rst!Количество = 1
rst.Update
Next
rstOr.MoveNext
Loop

Осталось напечатать накладную и ценники. Это, как и ранее, делается при помощи команды DoCmd.OpenReport


stDocName = "Накладная на прием"
DoCmd.OpenReport stDocName, acPreview, , CritStr
stDocName = "Ценник"
DoCmd.OpenReport stDocName, acPreview, , CritStr

Вся событийная процедура щелчка по кнопке Печать накладных на форме Прием товаров примет вид


Sub Печать_Click()
Dim rst As Recordset, rstOr As Recordset, i As Integer
Dim stDocName As String
Dim CritStr As String
stDocName = "Накладная на прием"
CritStr = "[Поставщик]="
Поставщик_
_
" and [Дата_поступления]=#"
Format([Дата_поступления], "mm-dd-yy")
"#"
DoCmd.OpenReport stDocName, acViewPreview, , CritStr
Set rst = CurrentDb.OpenRecordset("Число ценников")
Set rstOr = CurrentDb.OpenRecordset("Select * from Товары where "
CritStr)
With rst
Do While Not .EOF
.Delete
.MoveNext
Loop
Do While Not rstOr.EOF
For i = 1 To rstOr![Кол_во_упак]
AddNew
!КодТовара = rstOr![Код_товара]
!Количество = 1
.Update
Next
rstOr.MoveNext
Loop

End With
stDocName = "Ценник"
DoCmd.OpenReport stDocName, acPreview, , CritStr
End Sub

Результат выполнения этой процедуры (отчет для печати ценников в режиме предварительного просмотра) показан на рисунке. Предварительно в диалоговом окне Параметры страницы для данного отчета устанавливается требуемое число столбцов (в рассматриваемом примере 5), чтобы обеспечить максимальное заполнение пространства страницы листа бумаги.