В разработке на платформе 1С:Предприятие 8.3 (особенно в конфигурациях, построенных на Библиотеке стандартных подсистем — БСП) часто возникает задача программного формирования печатных форм. Типичный сценарий: из произвольной обработки необходимо последовательно вызвать несколько внешних печатных форм (ВПФ) для одного или нескольких документов, объединить полученные табличные документы в один общий и вывести результат пользователю. Дополнительная сложность возникает, когда одна из печатных форм должна быть альбомной, а другая — книжной.
В этой статье мы подробно разберем, как решить эти задачи по шагам, используя штатные механизмы платформы 1С и БСП.
При стандартном интерактивном вызове печати БСП открывает общую форму ПечатьДокументов. Однако для программной обработки нам нужно получить чистый объект ТабличныйДокумент на сервере. Для этого мы задействуем программный интерфейс общего модуля ДополнительныеОтчетыИОбработки, а именно метод ПечатьПоВнешнемуИсточнику().
Рассмотрим пример серверной функции, которая принимает ссылку на документ, ссылку на элемент справочника дополнительных обработок (нашу ВПФ) и идентификатор команды печати, а возвращает готовый табличный документ:
&НаСервереБезКонтекста
Функция ПолучитьТабличныйДокументВнешнейФормы(ДокументСсылка, СсылкаНаВПФ, ИдентификаторКоманды)
// 1. Инициализируем коллекцию печатных форм — служебную таблицу БСП
КоллекцияПечатныхФорм = УправлениеПечатью.ПодготовитьКоллекциюПечатныхФорм(ИдентификаторКоманды);
// 2. Формируем структуру параметров источника
ПараметрыИсточника = Новый Структура;
ПараметрыИсточника.Вставить("ИдентификаторКоманды", ИдентификаторКоманды);
// Передаем массив документов, для которых требуется выполнить печать
МассивОбъектов = Новый Массив;
МассивОбъектов.Добавить(ДокументСсылка);
ПараметрыИсточника.Вставить("ОбъектыНазначения", МассивОбъектов);
// Создаем вспомогательные структуры БСП для вывода печати
ОбъектыПечати = Новый СписокЗначений;
ПараметрыВывода = УправлениеПечатью.ПодготовитьСтруктуруПараметровВывода();
// 3. Вызываем программный интерфейс БСП для формирования печатной формы на сервере
ДополнительныеОтчетыИОбработки.ПечатьПоВнешнемуИсточнику(
СсылкаНаВПФ,
ПараметрыИсточника,
КоллекцияПечатныхФорм,
ОбъектыПечати,
ПараметрыВывода
);
// 4. Извлекаем сформированный результат из коллекции
Если КоллекцияПечатныхФорм.Количество() > 0 Тогда
Возврат КоллекцияПечатныхФорм[0].ТабличныйДокумент;
Иначе
ВызватьИсключение "Не удалось сформировать печатную форму: пустой результат.";
КонецЕсли;
КонецФункции
Этот метод работает на стороне сервера без вызова клиентских окон, что позволяет использовать его в фоновых заданиях, регламентных операциях или при массовой рассылке документов по электронной почте.
После того как мы получили отдельные табличные документы (например, для формы А и формы Б), их необходимо последовательно соединить в один результирующий документ. Для этого мы будем использовать метод Вывести() объекта ТабличныйДокумент.
Чтобы разделять визуальные документы на разные страницы при печати, обязательно нужно использовать горизонтальный разделитель страниц.
Проанализируем следующий пример кода:
&НаСервере
Функция ОбъединитьТабличныеДокументы(ТабДокА, ТабДокБ)
ОбщийТабличныйДокумент = Новый ТабличныйДокумент;
// Выводим первый документ (Форма А)
ОбщийТабличныйДокумент.Вывести(ТабДокА);
// Добавляем принудительный разделитель страниц, чтобы Форма Б началась с нового листа
ОбщийТабличныйДокумент.ВывестиГоризонтальныйРазделительСтраниц();
// Выводим второй документ (Форма Б)
ОбщийТабличныйДокумент.Вывести(ТабДокБ);
Возврат ОбщийТабличныйДокумент;
КонецФункции
Такой подход отлично работает, если у обоих табличных документов одинаковая ориентация страниц (например, оба документа книжные или оба альбомные).
Часто разработчики сталкиваются с важным ограничением платформы 1С:Предприятие: нельзя задать разную ориентацию страниц внутри одного объекта ТабличныйДокумент. Свойство ОриентацияСтраницы применяется к документу глобально. Если вы попытаетесь изменить ориентацию "на лету" во время формирования или объединения, весь итоговый документ примет ту ориентацию, которая была установлена последней.
Для обхода этого ограничения существует два основных решения.
Если ваша конечная цель — сохранить объединенный результат в один файл (например, многостраничный PDF, где первый лист книжный, а второй — альбомный) или отправить его на принтер единым пакетом, используйте объект платформы ПакетОтображаемыхДокументов.
Рассмотрим по шагам реализацию этого механизма:
&НаСервере
Функция СформироватьПакетДокументов(ТабДокКнижный, ТабДокАльбомный, ПутьДляСохраненияPDF)
// Инициализируем пакет документов
Пакет = Новый ПакетОтображаемыхДокументов;
// Настраиваем ориентацию первого документа (Портрет / Книжная)
ТабДокКнижный.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
// Помещаем его во временное хранилище и добавляем адрес в пакет
АдресКнижного = ПоместитьВоВременноеХранилище(ТабДокКнижный);
Пакет.Состав.Добавить(АдресКнижного);
// Настраиваем ориентацию второго документа (Ландшафт / Альбомная)
ТабДокАльбомный.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
// Помещаем его во временное хранилище и добавляем адрес в пакет
АдресАльбомного = ПоместитьВоВременноеХранилище(ТабДокАльбомный);
Пакет.Состав.Добавить(АдресАльбомного);
// Записываем пакет в один PDF-файл. Ориентация страниц внутри файла сохранится индивидуально!
Пакет.Записать(ПутьДляСохраненияPDF, ТипФайлаПакетаОтображаемыхДокументов.PDF);
// Альтернативный вариант: отправка напрямую на принтер без вывода диалогов
// Пакет.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
КонецФункции
Если вам нужно просто показать пользователю на экране обе печатные формы в одном окне, нет необходимости физически склеивать их в один объект ТабличныйДокумент. Стандартный механизм печати БСП умеет выводить несколько табличных документов в одной форме предварительного просмотра. При этом у каждой вкладки или страницы сохранится своя собственная ориентация.
Для этого мы можем подготовить коллекцию печатных форм, заполнить её нашими документами с индивидуальными настройками ориентации и передать стандартной форме печати:
&НаКлиенте
Процедура ПоказатьПечатныеФормыНаЭкран(ДокументСсылка, СсылкаНаВПФ_А, СсылкаНаВПФ_Б)
ПараметрыОткрытия = Новый Структура;
// Подготавливаем уникальный идентификатор для формы печати
ПараметрыОткрытия.Вставить("УникальныйИдентификатор", Новый УникальныйИдентификатор);
// Создаем описание печатных форм для передачи в БСП
ПараметрыОткрытия.Вставить("ИменаМакетов", "ВнешняяПечатнаяФормаА,ВнешняяПечатнаяФормаБ");
// Формируем параметры и вызываем форму просмотра БСП
ОткрытьФорму("ОбщаяФорма.ПечатьДокументов", ПараметрыОткрытия);
КонецПроцедуры
Этот способ является наиболее предпочтительным с точки зрения пользовательского интерфейса, так как он задействует привычное для пользователей окно печати вашей конфигурации, сохраняя все штатные функции: отправку на принтер, изменение масштаба, сохранение файлов на диск и отправку по почте.