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