Как настроить сквозную нумерацию колонтитулов при печати нескольких табличных документов в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке печатных форм в системе «1С:Предприятие 8» программисты часто сталкиваются с ситуацией, когда один отчет или пакет документов должен состоять из нескольких разделов с разной ориентацией страниц. Например, первый раздел (титульный лист и общие сведения) должен быть портретным, а второй раздел (большая спецификация или аналитическая таблица) — ландшафтным.

Поскольку параметры страницы (ориентация, поля, масштаб) в 1С задаются для всего объекта ТабличныйДокумент целиком, объединить такие разделы в один документ невозможно. Нам приходится формировать два отдельных табличных документа. Но как в таком случае обеспечить красивую сквозную нумерацию страниц в формате «Страница X из Y» во всех документах пакета? В этой статье мы подробно разберем, как решить эту задачу стандартными средствами платформы 1С.

В чем сложность сквозной нумерации нескольких документов?

Если мы используем стандартный механизм колонтитулов табличного документа, то для вывода номеров страниц обычно применяются специальные шаблоны-макросы:

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

Для решения этой проблемы нам необходимо решить две задачи:

  1. Указать второму документу, что его нумерация должна начинаться не с единицы, а с определенного числа (равного количеству страниц первого документа плюс один).
  2. Рассчитать общее количество страниц по всем документам вместе и вывести это статическое число в колонтитулы вместо стандартного макроса [&СтраницВсего].

Выясним, как это реализовать по шагам.

Шаг 1. Установка начального номера страницы

Начиная с версии платформы 1С:Предприятие 8.3.12, у объекта ТабличныйДокумент появилось замечательное свойство — НомерПервойСтраницы. Оно позволяет явно указать начальное число для отсчета страниц при выводе колонтитулов.

По умолчанию это свойство равно Неопределено (или 0), что означает стандартный отсчет с 1. Если же мы программно присвоим этому свойству значение, например, 3, то первая страница этого табличного документа получит в колонтитуле номер 3, вторая — 4 и так далее.

Проанализируем пример кода:


// Задаем начальный номер страницы для второго документа
ТабДок2.НомерПервойСтраницы = 3;

Это свойство отлично работает не только при прямой печати из 1С, но и при экспорте табличного документа в сторонние форматы, такие как XLSX (Open XML) или ODS (OpenDocument). Приложение, открывающее файл (например, Microsoft Excel), считает эту настройку и продолжит нумерацию корректно.

Шаг 2. Расчет общего количества страниц и формирование колонтитулов

Макрос [&СтраницВсего] не умеет самостоятельно суммировать страницы из разных объектов ТабличныйДокумент. Поэтому нам придется отказаться от его автоматического использования. Вместо этого мы будем рассчитывать общее число страниц программно и подставлять его в текст колонтитула как обычную строку.

Для этого мы воспользуемся методом КоличествоСтраниц() объекта ТабличныйДокумент. Этот метод принудительно рассчитывает, сколько физических листов бумаги займет документ при печати с текущими настройками принтера, масштаба и полей.

Рассмотрим детальный алгоритм и код реализации этой логики:


// 1. Полностью формируем и заполняем оба табличных документа
// (код заполнения документов опущен для краткости)

// 2. Получаем количество страниц в каждом документе
СтраницВПервом = ТабДок1.КоличествоСтраниц();
СтраницВоВтором = ТабДок2.КоличествоСтраниц();

// Вычисляем общую сумму страниц для сквозного колонтитула
ВсегоСтраниц = СтраницВПервом + СтраницВоВтором;

// 3. Настраиваем колонтитулы для первого документа
ТабДок1.НижнийКолонтитул.Выводить = Истина;
// Используем динамический номер страницы и статическое общее количество
ТабДок1.НижнийКолонтитул.ТекстВЦентре = "Страница [&НомерСтраницы] из " + Строка(ВсегоСтраниц);

// 4. Настраиваем смещение и колонтитулы для второго документа
ТабДок2.НомерПервойСтраницы = СтраницВПервом + 1;
ТабДок2.НижнийКолонтитул.Выводить = Истина;
ТабДок2.НижнийКолонтитул.ТекстВЦентре = "Страница [&НомерСтраницы] из " + Строка(ВсегоСтраниц);

В результате выполнения этого кода мы получим идеальную сквозную нумерацию. Если первый документ занимает 2 страницы, а второй — 4 страницы, то колонтитулы распределятся следующим образом:

Важный подводный камень: Метод КоличествоСтраниц()

Разберем один важный нюанс, с которым часто сталкиваются разработчики при работе на серверной стороне (в фоновых заданиях или серверных модулях). Метод КоличествоСтраниц() выполняет расчет на основе параметров принтера по умолчанию, установленного в операционной системе.

Если код выполняется на сервере 1С:Предприятия, под учетной записью службы сервера должен быть установлен хотя бы один принтер (пусть даже виртуальный, например, Microsoft XPS Document Writer). Если принтер по умолчанию на сервере отсутствует или недоступен, метод КоличествоСтраниц() может вернуть 0 или вызвать ошибку выполнения. Всегда учитывайте этот момент при проектировании серверной печати.

Шаг 3. Пакетная печать и сохранение в PDF с разной ориентацией страниц

Если мы просто по очереди отправим два документа на принтер методами ТабДок1.Напечатать() и ТабДок2.Напечатать(), система создаст два независимых задания печати. Это неудобно по нескольким причинам:

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

Посмотрим на пример кода, который объединяет наши документы в пакет и сохраняет его в один PDF-файл с сохранением сквозной нумерации и ориентации страниц:


// Создаем объект пакета документов
Пакет = Новый ПакетОтображаемыхДокументов;

// Помещаем первый табличный документ во временное хранилище и добавляем в пакет
АдресВХ1 = ПоместитьВоВременноеХранилище(ТабДок1);
ЭлементПакета1 = Пакет.Состав.Добавить(АдресВХ1);
ЭлементПакета1.Имя = "Часть_1_Портретная";

// Помещаем второй табличный документ во временное хранилище и добавляем в пакет
АдресВХ2 = ПоместитьВоВременноеХранилище(ТабДок2);
ЭлементПакета2 = Пакет.Состав.Добавить(АдресВХ2);
ЭлементПакета2.Имя = "Часть_2_Ландшафтная";

// Вариант 1. Отправляем пакет на печать одним заданием
Пакет.Напечатать(Истина); // Параметр Истина показывает диалог выбора принтера один раз для всего пакета

// Вариант 2. Сохраняем весь пакет в один многостраничный PDF-файл
ИмяФайлаPDF = ПолучитьИмяВременногоФайла("pdf");
Пакет.Записать(ИмяФайлаPDF, ТипФайлаПакетаОтображаемыхДокументов.PDF);

Использование ПакетОтображаемыхДокументов гарантирует, что при печати на физическом принтере или при сохранении в PDF-файл ландшафтные страницы останутся ландшафтными, портретные — портретными, а сквозная нумерация колонтитулов не собьется.

Резюме

Мы успешно решили задачу сквозной нумерации колонтитулов для документов с разной структурой и ориентацией страниц. Подведем итоги нашего разбора:

  1. Используйте свойство НомерПервойСтраницы для смещения стартового номера во втором и последующих документах.
  2. Откажитесь от макроса [&СтраницВсего] в пользу программного сложения результатов метода КоличествоСтраниц() всех выводимых документов.
  3. Для удобства пользователей и предотвращения разрывов при отправке на печать всегда объединяйте разнородные табличные документы в единый ПакетОтображаемыхДокументов.
← На главную