Как подсчитать количество страниц в табличном документе 1С и реализовать нумерацию «Лист X из Y»?

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

При разработке печатных форм в 1С:Предприятие часто возникает задача вывести общее количество страниц документа в подвале или заголовке каждой страницы. Стандартные колонтитулы не всегда подходят из-за жестких требований к оформлению документа. В этой статье мы подробно разберем, как программно определить количество страниц и реализовать нумерацию «Страница N из Всего» несколькими способами.

Метод 1. Использование штатной функции КоличествоСтраниц()

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

Рассмотрим пример использования:


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

Важные нюансы работы метода:

  1. Зависимость от принтера: Метод КоличествоСтраниц() обращается к драйверу принтера, установленного по умолчанию в операционной системе. Если принтер не установлен или драйвер работает некорректно, метод может вернуть 0 или неверное значение.
  2. Серверный вызов: При выполнении кода на стороне сервера (особенно под управлением Linux) необходимо убедиться, что в системе установлены шрифты (например, msttcorefonts), иначе расчет высоты строк будет неточным.
  3. Автомасштаб: Если для документа установлено свойство АвтоМасштаб = Истина, вызывать метод следует только после того, как в документ выведены все области, иначе итоговый масштаб (и количество страниц) еще не определены системой.

Метод 2. Расчет через ПроверитьВывод()

Проанализируем ситуацию, когда нам нужно выводить номер текущей страницы непосредственно в процессе формирования документа. Для этого используется метод ПроверитьВывод(). Он возвращает Истина, если переданный массив областей помещается на текущую страницу.

Разберем алгоритм реализации:


НомерСтраницы = 1;
Для Каждого СтрокаДанных Из СписокТоваров Цикл
    ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
    // Заполняем параметры области...
    
    // Проверяем, поместится ли строка на текущий лист
    МассивОбластей = Новый Массив;
    МассивОбластей.Добавить(ОбластьСтрока);
    
    Если НЕ ТабДокумент.ПроверитьВывод(МассивОбластей) Тогда
        ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
        НомерСтраницы = НомерСтраницы + 1;
        // Здесь можно вывести заголовок таблицы на новой странице
    КонецЕсли;
    
    ТабДокумент.Вывести(ОбластьСтрока);
КонецЦикла;

Метод 3. Реализация нумерации «Страница N из M» через поиск и замену

Выясним причину популярности этого метода: он позволяет вывести общее количество страниц даже в заголовке первой страницы, когда система еще «не знает», сколько страниц получится в итоге. Идея заключается в использовании текстовой метки-заполнителя.

Пошаговый алгоритм:

  1. В макете, в области колонтитула или подвала, создаем шаблон вида: Страница [НомерСтр] из [ВсегоСтраниц].
  2. Вместо параметра ВсегоСтраниц в макете пишем уникальную текстовую метку, например, %ВсегоЛ%.
  3. Формируем документ как обычно, подсчитывая текущий номер страницы через ПроверитьВывод().
  4. После завершения формирования получаем итоговое количество страниц методом КоличествоСтраниц().
  5. Запускаем цикл поиска и замены метки во всем документе.

Рассмотрим программную реализацию этого процесса:


// 1. Формируем документ
ТабДок = Новый ТабличныйДокумент;
// ... (заполнение данными) ...

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

// 3. Производим замену метки во всем документе
ОбластьВсегоСтраниц = ТабДок.НайтиТекст("%ВсегоЛ%");
Пока ОбластьВсегоСтраниц <> Неопределено Цикл
    ОбластьВсегоСтраниц.Текст = СтрЗаменить(ОбластьВсегоСтраниц.Текст, "%ВсегоЛ%", ВсегоСтраницВДокументе);
    // Ищем следующее вхождение
    ОбластьВсегоСтраниц = ТабДок.НайтиТекст("%ВсегоЛ%");
КонецЦикла;

Метод 4. Оптимизация для больших документов

Посмотрим на ситуацию со стороны производительности. На очень больших документах (сотни страниц) метод НайтиТекст() может работать медленно. Чтобы ускорить процесс, мы можем заранее сохранять ссылки на области, где требуется замена.

Рассмотрим этот прием подробнее:


МассивОбластейДляЗамены = Новый Массив;

Для НомерСтр = 1 По СписокДанных.Количество() Цикл
    Область = Макет.ПолучитьОбласть("ПодвалСтраницы");
    Область.Параметры.ТекстВсегоСтраниц = "%ВсегоЛ%";
    ТабДок.Вывести(Область);
    
    // Сохраняем ссылку на только что выведенную область
    ПоследняяОбласть = ТабДок.Область(ТабДок.ВысотаТаблицы, , ТабДок.ВысотаТаблицы);
    МассивОбластейДляЗамены.Добавить(ПоследняяОбласть);
КонецЦикла;

// В конце просто перебираем массив, не используя полнотекстовый поиск
ИтогоСтраниц = ТабДок.КоличествоСтраниц();
Для Каждого ОбластьКЗамене Из МассивОбластейДляЗамены Цикл
    ОбластьКЗамене.Текст = СтрЗаменить(ОбластьКЗамене.Текст, "%ВсегоЛ%", ИтогоСтраниц);
КонецЦикла;

Дополнительные рекомендации

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

  1. Явное указание настроек страницы: Перед расчетом всегда программно устанавливайте ориентацию и размер страницы. Это гарантирует, что КоличествоСтраниц() вернет один и тот же результат на разных компьютерах.
    
    ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
    ТабДок.РазмерСтраницы = "A4";
    ТабДок.АвтоМасштаб = Истина;
    
  2. Работа на сервере без принтера: Если документ формируется в фоновом задании на сервере, где нет установленных принтеров, используйте свойство ИмяПринтера или предварительно настройте виртуальный PDF-принтер в системе.
  3. Фиксированная высота строк: Если дизайн макета позволяет, используйте фиксированную высоту строк. Это позволит рассчитать количество страниц простым делением общего количества строк на количество строк, помещающихся на одном листе. Это самый быстрый, но наименее гибкий способ.

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

← На главную