При работе с платформой 1С иногда возникает задача вывести на печать документ, который должен содержать страницы с разной ориентацией – одни в альбомной (ландшафт), другие в книжной (портрет). Казалось бы, достаточно просто установить свойство ОриентацияСтраницы для объекта ТабличныйДокумент в нужный момент. Однако, как мы выясним, это свойство применяется ко всему документу целиком, а не к отдельным его частям. Давайте разберем эту ситуацию подробнее и найдем оптимальное решение.
ОриентацияСтраницы не работает?Когда мы пытаемся установить ориентацию страницы непосредственно для объекта ТабличныйДокумент после вывода каждой области, мы сталкиваемся с тем, что последнее присвоенное значение свойства ТабДок.ОриентацияСтраницы применяется ко всему документу целиком. Это означает, что если в конце формирования документа мы установили ориентацию "Портрет", то все страницы, вне зависимости от предыдущих установок, будут напечатаны в портретной ориентации.
Представим себе такую ситуацию, как в исходном сообщении:
Если А = 1 Тогда
ТабДок.Вывести(Шапка1);
// ... Выводим данные для первой части документа
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт; // Пытаемся установить альбомную
КонецЕсли;
Если А = 2 Тогда
ТабДок.Вывести(Шапка2);
// ... Выводим данные для второй части документа
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Портрет; // Пытаемся установить книжную
КонецЕсли;
В этом случае, если условие А = 2 будет истинным, то последнее присвоение ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Портрет переопределит любые предыдущие установки, и в результате весь документ будет напечатан в портретной ориентации. Платформа 1С не поддерживает изменение ориентации в рамках одного экземпляра объекта ТабличныйДокумент.
ПакетОтображаемыхДокументовДля эффективного решения этой проблемы платформа 1С предоставляет специальный объект – ПакетОтображаемыхДокументов. Этот объект, доступный начиная с версии платформы 8.3.3, разработан именно для пакетной печати и позволяет объединять несколько независимых табличных документов в одно задание на печать. Каждый из этих отдельных табличных документов может иметь свои уникальные настройки печати, включая ориентацию страницы.
Разберем процесс формирования и печати составного документа с разной ориентацией страниц по шагам.
Вместо того чтобы пытаться управлять ориентацией внутри одного ТабличныйДокумент, мы создадим несколько независимых объектов ТабличныйДокумент. Каждый такой объект будет представлять собой отдельную "часть" нашего итогового документа и содержать свои данные и настройки ориентации.
ТабличныйДокумент для первой части (например, для альбомной ориентации).ТабличныйДокумент желаемую ориентацию страницы.Давайте посмотрим на пример кода:
// Предположим, у нас есть параметр А, определяющий тип вывода
Перем ТабличныйДокументЛандшафт;
Перем ТабличныйДокументПортрет;
Если А = 1 Тогда
// Формируем первый документ с альбомной ориентацией
ТабличныйДокументЛандшафт = Новый ТабличныйДокумент;
ТабличныйДокументЛандшафт.ИмяПараметровПечати = "ПараметрыПечатиЛандшафт"; // Необязательно, но полезно
// Допустим, у нас есть некая процедура, которая выводит данные
// и возвращает макет с данными для альбомной части
ВывестиДанныеЛандшафт(ТабличныйДокументЛандшафт);
ТабличныйДокументЛандшафт.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
ТабличныйДокументЛандшафт.Автомасштаб = Истина; // Часто полезно для ландшафта
ИначеЕсли А = 2 Тогда
// Формируем второй документ с книжной ориентацией
ТабличныйДокументПортрет = Новый ТабличныйДокумент;
ТабличныйДокументПортрет.ИмяПараметровПечати = "ПараметрыПечатиПортрет"; // Необязательно, но полезно
// Процедура, которая выводит данные для портретной части
ВывестиДанныеПортрет(ТабличныйДокументПортрет);
ТабличныйДокументПортрет.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
КонецЕсли;
// Примерные процедуры для вывода данных
Процедура ВывестиДанныеЛандшафт(ТабДок)
// В реальной ситуации здесь будет код вывода областей из макета
// Например:
Макет = ПолучитьМакет("МакетЛандшафт");
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьДанные = Макет.ПолучитьОбласть("Данные");
// ... заполнение областей ...
ТабДок.Вывести(ОбластьЗаголовок);
ТабДок.Вывести(ОбластьДанные);
ТабДок.Вывести(ОбластьЗаголовок); // Можем выводить несколько раз
КонецПроцедуры
Процедура ВывестиДанныеПортрет(ТабДок)
// В реальной ситуации здесь будет код вывода областей из макета
// Например:
Макет = ПолучитьМакет("МакетПортрет");
ОбластьЗаголовок = Макет.ПолучитьОбласть("ЗаголовокПортрет");
ОбластьДанные = Макет.ПолучитьОбласть("ДанныеПортрет");
// ... заполнение областей ...
ТабДок.Вывести(ОбластьЗаголовок);
ТабДок.Вывести(ОбластьДанные);
КонецПроцедуры
Важно: Каждый ТабличныйДокумент должен быть полностью сформирован и иметь свою заданную ориентацию до перехода к следующему шагу.
ПакетОтображаемыхДокументовПосле того как у нас есть один или несколько отдельных табличных документов, мы можем объединить их в пакет.
ПакетОтображаемыхДокументов.ТабличныйДокумент в коллекцию Состав этого пакета. Для этого часто удобно использовать временное хранилище.Давайте продолжим наш пример:
// ... код из Шага 1, формирующий ТабличныйДокументЛандшафт или ТабличныйДокументПортрет
ПакетДокументов = Новый ПакетОтображаемыхДокументов;
Если ТабличныйДокументЛандшафт <> Неопределено Тогда
АдресВХранилище = ПоместитьВоВременноеХранилище(ТабличныйДокументЛандшафт, УникальныйИдентификатор);
ПакетДокументов.Состав.Добавить(АдресВХранилище);
КонецЕсли;
Если ТабличныйДокументПортрет <> Неопределено Тогда
АдресВХранилище = ПоместитьВоВременноеХранилище(ТабличныйДокументПортрет, УникальныйИдентификатор);
ПакетДокументов.Состав.Добавить(АдресВХранилище);
КонецЕсли;
// Если нам нужно, чтобы документ A=1 и A=2 были в одном пакете,
// то логика формирования должна быть немного другой. Например:
ТабДокЧасть1 = Новый ТабличныйДокумент;
ВывестиДанныеЛандшафт(ТабДокЧасть1);
ТабДокЧасть1.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
ТабДокЧасть1.Автомасштаб = Истина;
ТабДокЧасть2 = Новый ТабличныйДокумент;
ВывестиДанныеПортрет(ТабДокЧасть2);
ТабДокЧасть2.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
ПакетДокументов = Новый ПакетОтображаемыхДокументов;
ПакетДокументов.Состав.Добавить(ПоместитьВоВременноеХранилище(ТабДокЧасть1, УникальныйИдентификатор));
ПакетДокументов.Состав.Добавить(ПоместитьВоВременноеХранилище(ТабДокЧасть2, УникальныйИдентификатор));
В этом примере мы создали два отдельных табличных документа, каждый со своей ориентацией, и добавили их в коллекцию Состав пакета. Обратите внимание, что объекты ТабличныйДокумент сначала помещаются во временное хранилище, а затем в Состав пакета добавляется ссылка на это хранилище. Это стандартная практика при работе с пакетами.
После того как ПакетОтображаемыхДокументов полностью сформирован, мы можем его распечатать или сохранить в файл.
// Для печати пакета
ПакетДокументов.Напечатать();
// Или для сохранения в файл PDF
// ПараметрыСохранения = Новый ПараметрыСохраненияДокумента;
// ПараметрыСохранения.ТипФайла = ТипФайлаТабличногоДокумента.PDF;
// ПакетДокументов.Сохранить("C:\МоиДокументы\ОтчетСРазнойОриентацией.pdf", ПараметрыСохранения);
При печати или сохранении в PDF каждый документ в пакете сохранит свою индивидуальную ориентацию. Это и является ключевым преимуществом использования ПакетОтображаемыхДокументов.
Рассмотрим и другие возможные способы, которые, однако, не всегда являются оптимальными для данной задачи.
Этот подход заключается в том, чтобы сформировать несколько независимых табличных документов и выводить их на печать по очереди. При этом для каждого нового табличного документа можно установить свою ориентацию.
Если А = 1 Тогда
ТабДок1 = Новый ТабличныйДокумент;
ВывестиДанныеЛандшафт(ТабДок1);
ТабДок1.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
ТабДок1.Показать(); // Или ТабДок1.Напечатать();
КонецЕсли;
Если А = 2 Тогда
ТабДок2 = Новый ТабличныйДокумент;
ВывестиДанныеПортрет(ТабДок2);
ТабДок2.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
ТабДок2.Показать(); // Или ТабДок2.Напечатать();
КонецЕсли;
Недостатки:
Напечатать()) или ему придется нажимать кнопку "Печать" несколько раз для каждого документа (если используется Показать()). Это неудобно, если требуется единый логический документ.В программах 1С обычно есть возможность настроить параметры страницы (ориентацию, поля, масштаб) через меню "Еще" -> "Параметры страницы" перед печатью. Однако этот способ позволяет выбрать только одну ориентацию для всего документа целиком, а не для отдельных страниц.
Недостатки:
ТабличномуДокументу, что не решает задачу смешанной ориентации.При работе с печатью и ПакетОтображаемыхДокументов мы должны учитывать несколько важных аспектов.
Одним из значительных преимуществ использования ПакетОтображаемыхДокументов является возможность сохранения полученного составного документа в формате PDF. В этом случае каждая часть документа сохранит свою заданную ориентацию, и итоговый PDF-файл будет содержать страницы с правильной ориентацией.
Поведение метода ПакетОтображаемыхДокументов.Напечатать() может зависеть от режима совместимости платформы, в котором работает ваша конфигурация. В старых режимах совместимости каждый документ из пакета может отправляться на печать как отдельное задание. В более новых версиях платформы (без использования режимов совместимости со старыми версиями) может создаваться одно общее задание на принтер для всего пакета, что является более предпочтительным поведением.
Иногда проблемы с ориентацией страниц могут быть связаны не только с логикой 1С, но и с настройками принтера или его драйверами. Всегда стоит проверять, как принтер ведет себя при печати документов с разной ориентацией из других приложений (например, из Microsoft Word или любого другого текстового редактора). Если другие приложения печатают ландшафт и портрет корректно, то проблема, скорее всего, кроется в коде 1С.
В некоторых случаях, если нам нужно задать общие параметры для всего документа (например, имя принтера, количество копий), мы можем передавать параметры печати в функцию вызова печатной формы. Однако, для решения задачи смешанной ориентации, этот подход не подойдет, так как ОриентацияСтраницы внутри одного ТабличногоДокумента все равно будет применяться глобально.
Таким образом, для решения задачи вывода единого логического документа, содержащего страницы с разной ориентацией (как альбомной, так и книжной), наиболее универсальным, надежным и рекомендованным подходом в платформе 1С является формирование нескольких отдельных объектов ТабличныйДокумент, каждый со своей ориентацией, и их последующее объединение с помощью объекта ПакетОтображаемыхДокументов. Этот метод обеспечивает гибкость и корректность печати в сложных сценариях, сохраняя при этом удобство для пользователя, поскольку весь документ обрабатывается как единое целое.