Как правильно выбрать макет печатной формы УПД в зависимости от даты документа в 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Розница Бухгалтерский учет Торговля и дистрибуция
← На главную

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

Разберем типичную проблему, возникающую при попытке проверить дату документа перед получением макета, выясним причину возникновения ошибки «Ошибка чтения значения» и рассмотрим корректные способы реализации переключения макетов.

Анализ проблемы и причин ошибки

Рассмотрим ситуацию, когда в процедуре формирования печатного документа (например, ЗаполнитьТабличныйДокументУПД) разработчик пытается получить реквизит Дата из выборки результата запроса до входа в цикл обработки строк:


ДанныеПечати = ДанныеДляПечати.РезультатПоШапке.Выбрать();
Если ДанныеПечати.Дата >= ('20171001') Тогда
    Макет = УправлениеПечатью.МакетПечатнойФормы("Обработка.ПечатьОбщихФорм.ПФ_MXL_УниверсальныйПередаточныйДокумент011017");
Иначе
    Макет = УправлениеПечатью.МакетПечатнойФормы("Обработка.ПечатьОбщихФорм.ПФ_MXL_УниверсальныйПередаточныйДокумент");
КонецЕсли;

При выполнении этого кода платформа 1С выдает ошибку чтения значения. Проанализируем, почему это происходит:

  1. Непозиционированная выборка данных: метод Выбрать() возвращает объект типа ВыборкаИзРезультатаЗапроса, указатель которого изначально находится в начальном состоянии (перед первой записью). Пока не вызван метод ДанныеПечати.Следующий(), выборка не содержит текущей строки, и обращение к любому полю, включая ДанныеПечати.Дата, вызывает исключение.
  2. Неверная типизация литерала даты: конструкция ('20171001') в круглых скобках интерпретируется как строковый литерал, а не значение типа Дата. В языке 1С литерал даты задается в одинарных апострофах без круглых скобок — например, '20171001' или '20171001000000'.

Решение 1: Выбор макета внутри цикла по документам

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

Разберем по шагам правильное размещение условия:


ДанныеПечати = ДанныеДляПечати.РезультатПоШапке.Выбрать();
ВыборкаПоДокументам = ДанныеДляПечати.РезультатПоТабличнойЧасти.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
ПервыйДокумент = Истина;

Пока ДанныеПечати.Следующий() Цикл
    
    // Проверяем дату после позиционирования выборки на текущем документе
    Если ДанныеПечати.Дата >= '20171001' Тогда
        Макет = УправлениеПечатью.МакетПечатнойФормы("Обработка.ПечатьОбщихФорм.ПФ_MXL_УниверсальныйПередаточныйДокумент011017");
    Иначе
        Макет = УправлениеПечатью.МакетПечатнойФормы("Обработка.ПечатьОбщихФорм.ПФ_MXL_УниверсальныйПередаточныйДокумент");
    КонецЕсли;
    
    // Далее следует стандартный вывод областей шапки, строк и подвала
    // ...
КонецЦикла;

Решение 2: Оптимизация производительности при пакетной печати

Обратим внимание на производительность: постоянный вызов функции УправлениеПечатью.МакетПечатнойФормы() внутри тела цикла приводит к избыточным операциям чтения макета из метаданных на каждой итерации. Если на печать отправляется большой реестр документов, это существенно замедляет формирование отчета.

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


// Предварительно получаем оба макета до начала обхода выборки
МакетСтарый = УправлениеПечатью.МакетПечатнойФормы("Обработка.ПечатьОбщихФорм.ПФ_MXL_УниверсальныйПередаточныйДокумент");
МакетНовый  = УправлениеПечатью.МакетПечатнойФормы("Обработка.ПечатьОбщихФорм.ПФ_MXL_УниверсальныйПередаточныйДокумент011017");

ДанныеПечати = ДанныеДляПечати.РезультатПоШапке.Выбрать();
ВыборкаПоДокументам = ДанныеДляПечати.РезультатПоТабличнойЧасти.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
ПервыйДокумент = Истина;

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

Важные нюансы при работе с формами УПД

Рассмотрим дополнительные моменты, которые необходимо учитывать при разработке:

  1. Дата первичного документа и дата счета-фактуры: в типовых решениях (например, «1С:Бухгалтерия предприятия» или «1С:Розница») выбор формы бланка УПД привязан к дате счета-фактуры. Если документ отгрузки и счет-фактура имеют разные даты, в условии следует использовать именно дату счета-фактуры.
  2. Соответствие параметров макетов: при смене макета необходимо убедиться, что вспомогательные процедуры (ЗаполнитьРеквизитыШапкиУПД, ЗаполнитьРеквизитыСтрокиТовара, ЗаполнитьРеквизитыПодвалаУПД) корректно обрабатывают области нового макета. В новых редакциях УПД добавляются дополнительные колонки (например, код вида товара, идентификатор госконтракта), параметры которых должны присутствовать в структуре данных.
  3. Использование внешних печатных форм: для сохранения конфигурации на типовой поддержке рекомендуется выносить измененный алгоритм печати во внешнюю печатную форму (ВПФ) через механизм дополнительных отчетов и обработок БСП.
← На главную