При разработке в среде 1С:Предприятие 8 одним из самых мощных инструментов кастомизации являются расширения конфигурации. Они позволяют изменять логику прикладных решений, не снимая конфигурацию поставщика с поддержки. Однако при работе с механизмами печати (особенно в типовых решениях уровня «1С:Управление нашей фирмой» или «1С:Бухгалтерия») разработчики часто сталкиваются с неочевидными ошибками компиляции и исполнения кода.
В этой статье мы подробно разберем природу популярной ошибки «Метод объекта не обнаружен (Вывести)», которая возникает при попытке программного формирования макета в процедурах расширения. Мы выясним, почему «теряются» и очищаются параметры формирования, как правильно перехватывать процедуры печати БСП (Библиотеки стандартных подсистем), а также разберем тонкости настройки отладки фоновых заданий.
Давайте проанализируем ситуацию, в которой оказался разработчик. Пытаясь изменить логику заполнения печатной формы прайс-листа, он добавил в расширение процедуру-обработчик со следующей аннотацией:
&Вместо("ВывестиГруппуВТабличныйДокументПолотно")
Процедура Расш_ЗаполнитьВВидеПолотно(ПараметрыФормирования, ТабличныйДокумент, СтруктураТаблицДанных)
// Код заполнения...
ТабличныйДокумент.Вывести(ОбластьТест); // Здесь падает ошибка!
КонецПроцедуры
На первый взгляд код выглядит логичным: скопирована типовая процедура заполнения, изменен макет. Но именно здесь кроется критическая архитектурная ошибка. Разработчик перехватывает метод ВывестиГруппуВТабличныйДокументПолотно, но объявляет параметры от совершенно другой процедуры — ЗаполнитьВВидеПолотно.
Рассмотрим, как платформа 1С:Предприятие сопоставляет параметры при использовании аннотаций &Вместо, &Перед или &После. Сопоставление происходит исключительно по их порядковому номеру (позиции) в объявлении процедуры, а не по именам переменных.
Сравним оригинальные сигнатуры процедур в модуле менеджера типовой конфигурации УНФ:
ВывестиГруппуВТабличныйДокументПолотно(СтрокиДерева, ПараметрыФормирования, ТабличныйДокумент)Расш_ЗаполнитьВВидеПолотно(ПараметрыФормирования, ТабличныйДокумент, СтруктураТаблицДанных)При вызове перехваченного метода платформа выполняет трансляцию параметров следующим образом:
ПараметрыФормирования передается первый аргумент оригинальной процедуры — СтрокиДерева (тип КоллекцияСтрокДереваЗначений). Именно поэтому при отладке разработчик видит в этой переменной дерево номенклатуры вместо настроек печати.ТабличныйДокумент передается второй аргумент оригинальной процедуры — ПараметрыФормирования (тип Структура).СтруктураТаблицДанных передается реальный объект ТабличныйДокумент.Результат: Логика полностью ломается. Переменная ТабличныйДокумент внутри расширения содержит обычную структуру настроек. Когда код доходит до строки ТабличныйДокумент.Вывести(ОбластьТест), платформа пытается вызвать метод Вывести() у структуры данных, что порождает ошибку: «Метод объекта не обнаружен (Вывести)».
Чтобы исправить эту ситуацию, нам необходимо перехватывать именно ту процедуру, параметры которой мы планируем использовать. Если мы хотим полностью переопределить логику формирования печатной формы «Полотно», нам нужно применить аннотацию &Вместо к оригинальной процедуре ЗаполнитьВВидеПолотно. Ее сигнатура должна полностью соответствовать типовой конфигурации.
Проанализируем правильный вариант реализации в модуле менеджера расширения:
&Вместо("ЗаполнитьВВидеПолотно")
Процедура Расш_ЗаполнитьВВидеПолотно(ПараметрыФормирования, ТабличныйДокумент, СтруктураТаблицДанных)
// Инициализируем табличный документ (как в типовом коде)
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.Область(1, 1, 1, 1).ШиринаКолонки = 2;
// Получаем макет печатной формы.
// Обратите внимание: рекомендуется использовать собственный макет из расширения!
МакетПФ = УправлениеПечатью.МакетПечатнойФормы("Обработка.ПрайсЛистыОрганизации.ПФ_MXL_Полотно_Расширение");
// Пример вывода пользовательской области
ОбластьТест = МакетПФ.ПолучитьОбласть("Тест");
ОбластьТест.Параметры.Тест = "Мой кастомный текст";
ТабличныйДокумент.Вывести(ОбластьТест);
// Далее следует адаптированный типовой код вывода остальных областей...
ОбластьЗаголовок = СоздатьОбластьЗаголовок(ПараметрыФормирования, ТабличныйДокумент, МакетПФ);
// ...вывод шапки, строк и подвала...
КонецПроцедуры
При таком подходе позиционирование аргументов совпадает на 100%, и платформа без ошибок передает реальный табличный документ во второй параметр.
Часто разработчики пытаются добавить новые области или картинки (например, логотип компании) в оригинальный макет, просто затянув его в расширение и отредактировав. На практике это нередко приводит к конфликтам кэширования метаданных, когда изменения либо «не взлетают», либо приводят к ошибкам при обращении к областям.
Рассмотрим более надежный и профессиональный подход к кастомизации табличных макетов:
ПФ_MXL_Полотно обработки ПрайсЛистыОрганизации).ПФ_MXL_Полотно_Расширение).УправлениеПечатью.МакетПечатнойФормы, передавая полный путь к макету расширения.Это исключит наложение оригинального макета и макета расширения друг на друга и гарантирует стабильную отрисовку печатной формы на любых релизах конфигурации.
При создании расширения платформа предлагает выбрать его назначение. Этот параметр напрямую влияет на доступные возможности разработки:
Для задач изменения логики печати и структуры прайс-листа всегда устанавливайте значение свойства назначения в «Адаптация». Также убедитесь, что в свойствах расширения отключен «Безопасный режим», поскольку формирование прайс-листов часто требует работы с двоичными данными файлов картинок (логотипов) на сервере, что блокируется в безопасном режиме.
При работе с печатными формами разработчики часто жалуются, что точки останова в модуле менеджера не срабатывают, а отладка «пролетает» мимо кода. Это происходит из-за того, что формирование прайс-листа вынесено платформой в асинхронное фоновое задание, чтобы интерфейс пользователя не зависал во время тяжелых расчетов.
Разберем по шагам, как заставить отладчик останавливаться в фоновых заданиях на сервере:
-debug. Без этого ключа отладка серверного кода и фоновых процессов невозможна в принципе.Настроив автоматическое подключение к фоновым заданиям, вы сможете пошагово пройти по коду процедуры Расш_ЗаполнитьВВидеПолотно, проанализировать типы передаваемых параметров через «Табло» или «Вычислить выражение» (Ctrl + Alt + W) и оперативно выявлять любые несоответствия типов данных.