Почему при отладке печатной формы в 1С передается не то имя макета и как правильно заполнять дублирующиеся параметры

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

Разработка и отладка внешних печатных форм (ВПФ) в современных конфигурациях 1С (таких как «Управление торговлей», «ERP Управление предприятием» или «Комплексная автоматизация») часто преподносит сюрпризы начинающим разработчикам. Механизмы Библиотеки стандартных подсистем (БСП) берут на себя управление процессом вывода документов на печать, из-за чего стандартная отладка в Конфигураторе может выглядеть запутанной. В этой статье мы подробно разберем, почему в коде фигурируют неожиданные имена макетов, как устроен механизм печати БСП, и почему одинаковые параметры в макете могут заполняться по-разному.

Часть 1. Механизм БСП: почему ИмяМакета принимает значение «УПД» вместо реального имени макета

Разработчики часто сталкиваются с ситуацией, когда при пошаговой отладке в функцию НужноПечататьМакет в качестве параметра ИмяМакета передается короткая строка (например, "УПД"), в то время как сам макет в метаданных обработки называется длинно и официально — "ПФ_MXL_УниверсальныйПередаточныйДокумент". Выясним причину такого поведения системы.

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

  1. Регистрация печатной формы: Во внешней печатной форме обязательно присутствует функция СведенияОВнешнейОбработке(). В ней описываются параметры регистрации обработки в системе, включая таблицу команд. Для каждой команды разработчик вручную задает свойство Идентификатор. Например, для печати УПД логично задать идентификатор "УПД".
  2. Формирование коллекции печатных форм: Когда пользователь нажимает кнопку печати в режиме «1С:Предприятие», подсистема печати БСП формирует специальную таблицу — КоллекцияПечатныхФорм. В этой коллекции колонка ИмяМакета хранит именно Идентификатор команды, который был передан при регистрации, а не имя физического макета MXL из метаданных.
  3. Проверка необходимости печати: В процедуре Печать() внешней обработки происходит обход коллекции. Функция БСП УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "УПД") проверяет, выбрал ли пользователь именно эту команду.
  4. Связывание с реальным макетом: И только после того, как система убедилась, что нужно печатать форму с идентификатором "УПД", разработчик в коде вручную обращается к реальному макету из метаданных своей обработки.

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


Процедура Печать(МассивОбъектовНазначения, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт

    // Проверяем, нужно ли формировать печатную форму с идентификатором "УПД"
    Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "УПД") Тогда
        
        // Получаем табличный документ печатной формы
        ТабличныйДокумент = СформироватьПечатнуюФормуУПД(МассивОбъектовНазначения, ОбъектыПечати);
        
        // Связываем результат с коллекцией по идентификатору команды
        УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
            КоллекцияПечатныхФорм, 
            "УПД", 
            "Универсальный передаточный документ", 
            ТабличныйДокумент
        );
        
    КонецЕсли;

КонецПроцедуры

А уже внутри функции СформироватьПечатнуюФормуУПД мы получаем непосредственный макет из метаданных нашей внешней обработки:


Функция СформироватьПечатнуюФормуУПД(МассивОбъектовНазначения, ОбъектыПечати)
    
    // Здесь мы обращаемся к реальному имени макета в нашей обработке
    Макет = ПолучитьМакет("ПФ_MXL_УниверсальныйПередаточныйДокумент");
    
     ТабличныйДокумент = Новый ТабличныйДокумент;
    // ... дальнейший код заполнения областей и вывода в ТабличныйДокумент ...
    
    Возврат ТабличныйДокумент;
КонецФункции

Важный совет по отладке: Если при пошаговой отладке дебаггер ведет себя нетипично, перескакивает через строки кода или открывает неожиданные модули (как описано в сообщении 3 темы), убедитесь, что вы отлаживаете именно ту обработку, которая запущена в режиме предприятия. Очень часто разработчики забывают обновить файл внешней печатной формы в справочнике «Дополнительные отчеты и обработки». В этом случае система выгружает из базы данных во временный каталог старую версию файла и выполняет ее код, а точки останова в вашем открытом файле могут срабатывать со сдвигом строк или не срабатывать вовсе.

Часть 2. Почему одинаковые параметры в одной области макета могут заполняться по-разному

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

Проанализируем возможные причины такого поведения платформы 1С:

1. Разница между типом заполнения «Параметр» и «Шаблон»

В свойствах ячейки табличного документа в 1С есть свойство «Заполнение», которое может принимать значения: Текст, Параметр или Шаблон. Если для первой ячейки вы установили тип Параметр и написали в ней ФИО, а для второй по ошибке установили тип Шаблон (или оставили тип Параметр, но написали текст в квадратных скобках [ФИО]), то заполняться они будут совершенно по-разному.

Ячейка с типом Шаблон требует строгого синтаксиса: текст внутри нее должен содержать квадратные скобки для подстановки параметров, например: Ответственный: [ФИО]. Если тип заполнения указан неверно, платформа проигнорирует передачу значения в эту ячейку.

2. Физическое несовпадение областей макета

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

Если ячейки принадлежат разным областям макета, то код присвоения значения параметру должен быть выполнен для каждой области отдельно перед ее выводом на печать:


// Пример раздельного заполнения областей
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
ОбластьПодвал.Параметры.ФИО = "Иванов И.И."; // Заполнит параметр только в этой области
ТабДок.Вывести(ОбластьПодвал);

ОбластьПодписи = Макет.ПолучитьОбласть("ПодвалПодписи");
ОбластьПодписи.Параметры.ФИО = "Иванов И.И."; // Требуется повторное заполнение для другой области
ТабДок.Вывести(ОбластьПодписи);

3. Переопределение макетов пользователями в режиме «1С:Предприятие»

Это самый коварный нюанс работы с печатными формами в БСП. В системе существует встроенный механизм, позволяющий пользователям редактировать макеты печатных форм прямо в пользовательском режиме (раздел Администрирование -> Макеты печатных форм).

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

Решение проблемы:

  1. Перейдите в режим «1С:Предприятие».
  2. Откройте форму «Макеты печатных форм» (в разных конфигурациях она может находиться в разделе «Администрирование» или «Печатные формы, отчеты и обработки»).
  3. Найдите ваш макет (в данном случае УПД). Обратите внимание на его значок — если он изменен, рядом будет стоять соответствующая отметка.
  4. Нажмите кнопку «Использовать стандартный макет» (или удалите измененный макет). После этого система снова начнет считывать актуальный макет из вашей обработки.

4. Использование дублирующих параметров с уникальными именами

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

Рассмотрим пример такого заполнения:


ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");

// Явно заполняем разные параметры одним и тем же значением
ФИООтветственного = "Петров В.В.";
ОбластьПодвал.Параметры.ФИОПолучателя = ФИООтветственного;
ОбластьПодвал.Параметры.ФИОСдавшего   = ФИООтветственного;

ТабДок.Вывести(ОбластьПодвал);

Такой подход гарантирует абсолютную предсказуемость вывода данных в форму и существенно облегчит чтение и поддержку кода другими разработчиками в будущем.

← На главную