При разработке механизмов печати в системе 1С:Предприятие программисты часто сталкиваются с классическим ограничением платформы: свойство ОриентацияСтраницы (Портрет или Ландшафт) задается только для всего объекта ТабличныйДокумент целиком. Нельзя сделать так, чтобы первая страница одного табличного документа была книжной, а вторая — альбомной. Если попытаться изменить свойство ориентации во время вывода секций макета, весь результирующий документ примет то положение, которое было установлено последним.
Особенно остро эта проблема проявляется при групповой печати. Например, когда пользователь выделяет в списке несколько документов РеализацияТоваровУслуг и отправляет их на печать. Документы с небольшим количеством позиций отлично укладываются на вертикальный лист (Портрет), а многострочные документы требуют горизонтального формата (Ландшафт), чтобы не обрезались колонки.
Если объединить все печатные формы в один ТабличныйДокумент, мы потеряем возможность задавать индивидуальную ориентацию. Если же формировать отдельные файлы и отправлять их на принтер по очереди, операционная система разобьет их на разные задания. В результате порядок печати на сетевом принтере может легко нарушиться, и пользователю придется вручную сортировать пачку бумаги. Выясним, как элегантно обойти это ограничение и реализовать корректную печать.
Рассмотрим конкретную ситуацию. У нас есть 5 документов, которые необходимо распечатать строго по порядку их номеров:
Если мы разделим их на два результирующих табличных документа по типу ориентации, то в первый документ попадут файлы №1, №2 и №4 (альбомные), а во второй — №3 и №5 (книжные). При отправке этих двух документов на принтер мы получим две независимые задачи. Принтер выдаст сначала альбомные листы, а затем книжные. Хронологический порядок документов будет полностью нарушен. Нам необходимо решение, которое позволит отправить все документы одним заданием, сохранив при этом индивидуальные настройки страниц.
Начиная с версии платформы 1С 8.3.3, разработчикам доступен специализированный объект — ПакетОтображаемыхДокументов. Это наиболее современный, надежный и технически правильный способ решения нашей задачи. Он работает как своеобразный контейнер, объединяющий независимые табличные документы в единый пакет.
Разберем алгоритм работы с этим объектом по шагам:
ТабличныйДокумент.ПакетОтображаемыхДокументов, в состав которого последовательно (в строго нужном хронологическом порядке) добавляются адреса из временного хранилища.Пакет.Напечатать().Проанализируем пример программного кода, реализующий данный подход:
// Создаем пакет для объединения печатных форм
Пакет = Новый ПакетОтображаемыхДокументов;
Для Каждого ДокументСсылка Из МассивДокументов Цикл
// Формируем индивидуальный табличный документ для каждой реализации
ТабДок = СформироватьПечатнуюФорму(ДокументСсылка);
// Определяем ориентацию в зависимости от количества строк в документе
КоличествоСтрок = ДокументСсылка.Товары.Количество();
Если КоличествоСтрок > 15 Тогда
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
Иначе
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
КонецЕсли;
// Помещаем табличный документ во временное хранилище
АдресХранилища = ПоместитьВоВременноеХранилище(ТабДок, Новый УникальныйИдентификатор);
// Добавляем элемент в пакет отображаемых документов
ЭлементПакета = Пакет.Состав.Добавить();
ЭлементПакета.Данные = АдресХранилища;
КонецЦикла;
// Отправляем пакет на принтер как единую задачу
Пакет.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
Преимущества использования пакетов:
Записать() с типом файла ТипФайлаПакетаОтображаемыхДокументов.PDF позволяет сохранить все документы в один PDF-файл, в котором страницы будут иметь разную ориентацию.Если по каким-то причинам вы работаете на устаревших версиях платформы или конфигурации, где применение пакетов ограничено, можно реализовать последовательную отправку на печать каждого документа отдельно в цикле. При этом для каждого документа формируется свой ТабличныйДокумент, устанавливается ориентация и вызывается метод Напечатать().
Для Каждого ДокументСсылка Из МассивДокументов Цикл
ТабДок = СформироватьПечатнуюФорму(ДокументСсылка);
Если ДокументСсылка.Товары.Количество() > 15 Тогда
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
Иначе
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
КонецЕсли;
// Печатаем документ напрямую без вывода диалогового окна
ТабДок.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
КонецЦикла;
Этот способ прост в реализации, однако имеет существенные недостатки. Он отправляет на принтер множество мелких задач. Если принтер сетевой и им активно пользуются другие сотрудники, чужие документы могут вклиниться в очередь между вашими файлами, нарушив хронологический порядок.
В исключительных случаях, когда необходимо получить именно один физический файл в формате .mxl, содержащий визуально разные страницы, используют обходной путь «верстки» макета:
ТабличныйДокумент жестко настраивается в вертикальном формате (Портрет).ОриентацияТекста = 90 (или 270). Колонки исходного макета при этом фактически превращаются в строки.Этот метод чрезвычайно сложен в разработке, требует ручного пересчета ширин колонок и высот строк для повернутых областей и практически не применяется на практике из-за высокой трудоемкости поддержки. Однако знать о его существовании полезно.
Если вы разрабатываете печатную форму в конфигурации, использующей БСП (например, Управление торговлей, ERP или Комплексная автоматизация), то подсистема печати уже имеет встроенные механизмы интеграции с пакетами документов.
При формировании коллекции печатных форм через стандартный механизм БСП, вы можете возвращать массив структур, содержащих отдельные табличные документы. БСП самостоятельно скомпонует их в пакет отображаемых документов перед выводом на экран или отправкой на принтер, гарантируя сохранение масштабов, полей и ориентации страниц для каждого объекта отдельно.