При работе с первичными документами, особенно с транспортными накладными (ТН), часто возникает законодательное или внутреннее требование: на каждом экземпляре документа должен быть указан его порядковый номер (например, «Экземпляр № 1», «Экземпляр № 2» и так далее). Стандартный механизм печати 1С, использующий свойство КоличествоЭкземпляров объекта ТабличныйДокумент, в данном случае не подходит, так как принтер просто дублирует один и тот же сформированный образ, и текст в нем остается неизменным.
В этой статье мы подробно разберем, как программно реализовать вывод номера экземпляра, чтобы каждая копия документа была уникальной. Мы проанализируем различные подходы — от простых циклов до оптимизированного формирования единого пакета на печать.
Разберем типичную ситуацию: программист устанавливает значение ТабличныйДокумент.КоличествоЭкземпляров = 4; и отправляет документ на принтер. В этом случае 1С формирует одну страницу в памяти и передает драйверу принтера команду «напечатать это 4 раза». Поскольку формирование происходит один раз, мы никак не можем изменить содержимое ячейки «Номер экземпляра» для второй или третьей копии.
Чтобы решить эту задачу, нам необходимо пойти другим путем: сформировать один длинный табличный документ, который будет содержать в себе все необходимые копии одну за другой, разделенные разрывами страниц.
Это самый надежный и распространенный метод в среде 1С. Мы будем использовать цикл для заполнения областей макета и вывода их в итоговый документ. Рассмотрим по шагам, как это реализовать.
Шаг 1. Подготовка итогового документа и макета.
Сначала мы создаем пустой табличный документ, который в итоге будет отправлен на печать, и получаем макет нашей накладной.
Шаг 2. Запуск цикла по количеству копий.
Выясним, сколько экземпляров нужно напечатать (например, через запрос к пользователю или из настроек системы), и запустим цикл.
Разберем пример кода:
// Создаем итоговый документ
ТабДокИтоговый = Новый ТабличныйДокумент;
ТабДокИтоговый.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ТРАНСПОРТНАЯ_НАКЛАДНАЯ";
// Определяем количество копий
КоличествоКопий = 4;
Макет = ПолучитьМакет("МакетТН");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
Для НомерЭкземпляра = 1 По КоличествоКопий Цикл
// Если это не первый экземпляр, добавляем разрыв страницы
Если НомерЭкземпляра > 1 Тогда
ТабДокИтоговый.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
// Заполняем параметры шапки, включая номер экземпляра
ОбластьШапка.Параметры.НомерЭкземпляраТекст = "Экземпляр № " + НомерЭкземпляра;
// Здесь также заполняются остальные параметры (Организация, Контрагент и т.д.)
ОбластьШапка.Параметры.Заполнить(ДанныеДляПечати);
// Выводим заполненную область в итоговый документ
ТабДокИтоговый.Вывести(ОбластьШапка);
// Аналогично выводим строки таблицы и подвал
// ...
КонецЦикла;
// Включаем разбор по копиям для удобства принтера
ТабДокИтоговый.РазборПоКопиям = Истина;
ТабДокИтоговый.Показать();
В данном примере функция ВывестиГоризонтальныйРазделительСтраниц() гарантирует, что каждый новый экземпляр начнется с нового листа бумаги. Это критически важно, так как транспортная накладная может занимать несколько страниц.
Если печатная форма очень сложная, содержит много данных и расчетных полей, повторное формирование каждой копии "с нуля" в цикле может замедлить работу системы. В таком случае мы можем применить метод копирования уже заполненной области.
Проанализируем ситуацию: данные во всех экземплярах (кроме номера) идентичны. Мы можем один раз сформировать эталонный экземпляр в памяти, а затем просто дублировать его, меняя только одну ячейку.
Рассмотрим алгоритм действий:
НайтиТекст() или прямое обращение к области, чтобы заменить номер экземпляра.Пример реализации:
// Формируем эталон
ТабЭкземпляр = СформироватьОдинЭкземпляр(Данные);
Для Индекс = 1 По КоличествоКопий Цикл
Если Индекс > 1 Тогда
ТабДокИтоговый.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
// Находим область с текстом "Экземпляр №" и меняем ее
ОбластьНомера = ТабЭкземпляр.НайтиТекст("Экземпляр №");
Если ОбластьНомера <> Неопределено Тогда
ОбластьНомера.Текст = "Экземпляр № " + Индекс;
КонецЕсли;
ТабДокИтоговый.Вывести(ТабЭкземпляр);
КонецЦикла;
Стоит отметить, что согласно Постановлению Правительства №2116, экземпляры транспортной накладной часто должны различаться не только цифрой, но и указанием того, кому предназначен данный лист. Например:
Для реализации такой логики лучше всего подготовить массив или соответствие, которое мы будем использовать в нашем основном цикле формирования документа.
Предназначение = Новый Массив;
Предназначение.Добавить(" (для грузоотправителя)");
Предназначение.Добавить(" (для грузополучателя)");
Предназначение.Добавить(" (для перевозчика)");
Предназначение.Добавить(" (дополнительный)");
Для Сч = 1 По КоличествоКопий Цикл
// ... логика вывода ...
ТекстПояснения = "";
Если Сч <= Предназначение.Количество() Тогда
ТекстПояснения = Предназначение[Сч - 1];
КонецЕсли;
ОбластьШапка.Параметры.НомерЭкземпляра = "Экземпляр № " + Сч + ТекстПояснения;
// ...
КонецЦикла;
При реализации печати нескольких экземпляров в одном документе следует учитывать несколько моментов:
1. Колонтитулы: Если вы используете свойство ВерхнийКолонтитул или НижнийКолонтитул, помните, что они применяются ко всему табличному документу. Если вам нужно, чтобы в колонтитуле отображался номер экземпляра, стандартный механизм [&НомерСтраницы] не поможет, так как он будет считать сквозные страницы всего документа (например, 1-12). В этом случае номер экземпляра лучше выводить непосредственно в тело макета (в область шапки или подвала), а не в системный колонтитул.
2. Двусторонняя печать: Если принтер настроен на двустороннюю печать, использование ВывестиГоризонтальныйРазделительСтраниц() может привести к тому, что первый лист второго экземпляра напечатается на обороте последнего листа первого экземпляра. Чтобы этого избежать, количество страниц в одном экземпляре должно быть четным, либо нужно программно проверять количество страниц и добавлять пустой лист при необходимости.
3. Свойство РазборПоКопиям: Всегда устанавливайте ТабличныйДокумент.РазборПоКопиям = Истина;. Хотя в нашем случае мы и так формируем страницы по порядку, эта настройка помогает драйверам принтеров корректно обрабатывать задания большого объема.
Подведем итог: наиболее правильным и гибким способом вывода номера экземпляра в 1С является формирование единого ТабличногоДокумента внутри цикла. Это позволяет полностью контролировать содержимое каждой страницы и гарантирует корректный результат независимо от модели принтера и настроек его драйвера.