При работе в 1С часто возникает задача, когда один физический документ, зарегистрированный в системе, на печать должен выводиться в виде нескольких отдельных листов или документов. Например, когда табличная часть одного документа поступления или реализации делится по складам, поставщикам, договорам или просто по ограничению количества строк на одну страницу. При этом бизнес-требования часто диктуют необходимость вывода уникального номера для каждой печатной формы в формате «НомерДокумента/НомерСтраницы» (например, 15/1, 15/2, 15/3).
В этой статье мы подробно разберем, как правильно реализовать такую логику в коде 1С. Мы выясним, почему не нужно трогать автонумерацию в базе данных, как правильно получить «чистый» номер без префиксов и как динамически сформировать дробные номера в процессе вывода печатной формы.
Первой реакцией начинающего разработчика может быть попытка создать подписку на событие ПриУстановкеНовогоНомера или изменить номер самого документа в транзакции записи. Однако делать этого категорически нельзя по следующим причинам:
/) в стандартное текстовое поле номера может сбить механизм автонумерации платформы 1С. Последующие документы перестанут нумероваться автоматически.Таким образом, правильный подход заключается в том, что в информационной базе документ хранится под своим обычным номером (например, 0000-000225), а в печатную форму динамически выводится измененное представление: 225/1, 225/2 и так далее.
Обычно в 1С номера документов содержат префиксы организаций, префиксы узлов распределенных информационных баз (РИБ) и ведущие нули. На печать такой номер в сыром виде выводить не принято. Для получения красивого номера используются стандартные функции БСП (Библиотеки стандартных подсистем) или общих модулей типовых конфигураций.
Рассмотрим, как получить очищенный номер в современных конфигурациях на управляемых формах (БСП):
// Получаем чистый номер без префиксов и ведущих нулей
ЧистыйНомер = ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(СсылкаНаДокумент.Номер, Истина, Истина);
Если вы работаете в старой конфигурации на обычных формах (например, УТ 10.3 или УПП 1.3), используйте аналогичную функцию общего назначения:
// Для старых конфигураций
ЧистыйНомер = ОбщегоНазначения.ПолучитьНомерНаПечать(СсылкаНаДокумент);
Перед тем как писать код вывода, нам нужно определиться, по какому принципу мы делим табличную часть. Существует два основных сценария:
Давайте подробно разберем по шагам программную реализацию первого сценария (деление по группировке) с использованием горизонтальных разделителей страниц ВывестиГоризонтальныйРазделительСтраниц(). Этот метод позволяет принтеру понять, где заканчивается одна дробная часть документа и начинается другая.
Ниже представлен готовый пример функции формирования печатного документа:
Функция СформироватьПечатныеФормы(МассивОбъектов, ОбъектыПечати) Экспорт
ТабДок = Новый ТабличныйДокумент;
ТабДок.ТолькоПросмотр = Истина;
ТабДок.ОтображатьСетку = Ложь;
// Получаем макет нашей печатной формы
Макет = ПолучитьМакет("МакетПечатиСРазделением");
Для Каждого СсылкаИзМассива Из МассивОбъектов Цикл
// Получаем базовый номер документа без лишних нулей и префиксов
БазовыйНомер = ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(СсылкаИзМассива.Номер, Истина, Истина);
// Выгружаем табличную часть "Товары" для последующей группировки
ТаблицаТоваров = СсылкаИзМассива.Товары.Выгрузить();
// Создаем копию для получения уникального списка группировок (например, по реквизиту "Склад")
ТаблицаГрупп = ТаблицаТоваров.Скопировать();
ТаблицаГрупп.Свернуть("Склад");
ИндексСписка = 0;
КоличествоГрупп = ТаблицаГрупп.Количество();
Для Каждого СтрокаГруппы Из ТаблицаГрупп Цикл
ИндексСписка = ИндексСписка + 1;
// Если это не первая страница, принудительно вставляем разделитель для принтера
Если ТабДок.ВысотаТаблицы > 0 Тогда
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
// Формируем динамический дробный номер
// Если документ один и не делится (группа всего одна), выводим обычный номер
Если КоличествоГрупп > 1 Тогда
ДробныйНомер = Строка(БазовыйНомер) + "/" + Строка(ИндексСписка);
Иначе
ДробныйНомер = БазовыйНомер;
КонецЕсли;
// Заполняем область "Шапка"
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьШапка.Parameters.НомерДокумента = ДробныйНомер;
ОбластьШапка.Parameters.ДатаДокумента = Формат(СсылкаИзМассива.Дата, "ДФ=dd.MM.yyyy");
ОбластьШапка.Parameters.СкладНаименование = СтрокаГруппы.Склад;
ТабДок.Вывести(ОбластьШапка);
// Заполняем область "ШапкаТаблицы"
ОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ШапкаТаблицы");
ТабДок.Вывести(ОбластьШапкаТаблицы);
// Выбираем только те строки, которые относятся к текущему складу
ПараметрыОтбора = Новый Структура("Склад", СтрокаГруппы.Склад);
СтрокиДляПечати = ТаблицаТоваров.НайтиСтроки(ПараметрыОтбора);
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
НомерСтроки = 0;
ИтогоСуммаПоЛисту = 0;
Для Каждого СтрокаТЧ Из СтрокиДляПечати Цикл
НомерСтроки = НомерСтроки + 1;
ОбластьСтрока.Parameters.Заполнить(СтрокаТЧ);
ОбластьСтрока.Parameters.НП = НомерСтроки;
ТабДок.Вывести(ОбластьСтрока);
ИтогоСуммаПоЛисту = ИтогоСуммаПоЛисту + СтрокаТЧ.Сумма;
КонецЦикла;
// Заполняем область "Подвал" для текущей части документа
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
ОбластьПодвал.Parameters.ВсегоСумма = ИтогоСуммаПоЛисту;
ТабДок.Вывести(ОбластьПодвал);
КонецЦикла;
КонецЦикла;
Возврат ТабДок;
КонецФункции
Проанализировав данный код, мы видим, что переменная ДробныйНомер собирается динамически прямо в цикле обхода групп табличной части. Она передается в параметр макета НомерДокумента вместо стандартного реквизита. В результате пользователь получает красивую печатную форму, разбитую на страницы, где каждая страница имеет логически понятную нумерацию: 225/1, 225/2 и т.д.
Чтобы внедрить данное решение в вашу рабочую базу 1С, настоятельно рекомендуется не изменять типовую конфигурацию напрямую. Снятие документов с поддержки значительно усложнит последующие обновления программы.
Оптимальным решением будет создание Внешней печатной формы (ВПФ). Вы можете скопировать стандартный макет и процедуру печати во внешнюю обработку, зарегистрировать ее в системе через справочник «Дополнительные отчеты и обработки» и назначить для нужного типа документа. Это позволит сохранить конфигурацию полностью типовой, обеспечив при этом требуемый бизнес-функционал дробной нумерации при печати.