При разработке и адаптации типовых решений на платформе 1С:Предприятие 8.3 программисты часто используют механизм расширений. Это позволяет кастомизировать систему, не снимая основную конфигурацию с поддержки. Однако при работе с расширениями модулей менеджеров (особенно при переопределении печатных форм в таких конфигурациях, как Управление торговлей, ERP или Комплексная автоматизация) разработчики нередко сталкиваются с неприятной проблемой: код в расширении не выполняется, а отладчик упрямо игнорирует установленные точки останова.
В этой статье мы подробно разберем, почему возникает эта проблема, как настроить отладку, чтобы система заходила в доработанные процедуры, а также выясним, как правильно работать с макетами печатных форм, добавленными в расширение.
Как показывает практика практикующих специалистов, одной из неочевидных причин, почему расширение модуля менеджера игнорируется системой, является баг конкретного релиза платформы 1С:Предприятие. В версиях платформы (например, в некоторых релизах веток 8.3.14 и 8.3.15) наблюдались внутренние ошибки кэширования метаданных. При динамическом обновлении конфигурации или частом перезапуске отладки расширение модуля менеджера могло физически «отваливаться» или не регистрироваться в контуре выполнения.
Для устранения этой проблемы рекомендуется выполнить следующие действия:
В современных конфигурациях 1С на базе Библиотеки стандартных подсистем (БСП) формирование печатных форм практически всегда происходит на сервере в фоновом режиме. Если у вас в настройках отладки не включено автоматическое подключение к фоновым заданиям, отладчик просто не остановится на вашей точке останова в расширении, хотя сам код при этом может успешно выполняться.
Проанализируем ситуацию и настроим отладку по шагам:
Если вы используете аннотацию &Вместо для полной замены стандартного метода конфигурации, платформа накладывает жесткие требования на структуру объявляемой процедуры или функции. Количество, порядок и имена параметров в расширении должны строго совпадать с оригинальным методом в основной конфигурации.
Разберем пример правильного переопределения функции печати. Предположим, оригинальная функция в модуле менеджера обработки выглядит следующим образом:
Функция СформироватьПечатнуюФорму(МассивОбъектов, ПараметрыПечати) Экспорт
// Исходный код конфигурации
КонецФункции
В расширении сигнатура принимаемых параметров должна в точности дублировать оригинал. Посмотрим на правильный код в модуле расширения:
&Вместо("СформироватьПечатнуюФорму")
Функция Расш1_СформироватьПечатнуюФорму(МассивОбъектов, ПараметрыПечати)
// Наш доработанный код
Результат = ПродолжитьВызов(МассивОбъектов, ПараметрыПечати);
Возврат Результат;
КонецФункции
Если при обновлении основной конфигурации разработчики вендора добавят в функцию третий параметр (например, ОбъектыПечати), а в вашем расширении останется старая сигнатура из двух параметров, платформа проигнорирует метод расширения и выполнит стандартный код без вывода каких-либо предупреждений на экран.
После того как нам удалось заставить работать код модуля менеджера в расширении, возникает следующая задача: получить макет печатной формы, который мы добавили в это же расширение.
Попытка обратиться к макету через функции БСП напрямую по полному пути, как показано в коде ниже, часто приводит к ошибке, поскольку БСП не всегда может корректно распознать префиксы расширений в строковых путях:
// Такой вариант часто выдает ошибку "Макет не найден"
Макет = УправлениеПечатью.МакетПечатнойФормы("Расширение_Имя.Обработки.ПечатьОбщихФорм.ПФ_MXL_МойМакет");
Рассмотрим два надежных и проверенных способа решения этой задачи.
Если код выполняется непосредственно в модуле менеджера того объекта (справочника, документа или обработки), в расширение которого добавлен новый макет, самым простым и лаконичным решением будет использование встроенного метода ПолучитьМакет().
Контекст выполнения в расширении устроен таким образом, что система в первую очередь ищет макет во внутреннем пространстве имен самого расширения, а уже затем обращается к основной конфигурации. Посмотрим на пример кода:
// Обращаемся напрямую к имени макета, добавленному в расширение
Макет = ПолучитьМакет("ПФ_MXL_МойМакет");
Или, если мы пишем код внутри модуля менеджера:
Макет = ЭтотОбъект.ПолучитьМакет("ПФ_MXL_МойМакет");
Этот способ является наиболее безопасным, так как он не зависит от работы сторонних функций БСП и гарантированно вернет нужный табличный документ.
Если вам необходимо получить макет из другого места программы или гарантировать, что обращение идет именно к объекту расширения, можно применить программное обращение через менеджер соответствующего объекта 1С.
Выясним, как выглядит такое обращение на примере обработки:
// Получаем макет обработки, добавленной или расширенной в системе
Макет = Обработки.УАС_ПечатьОбщихФорм.ПолучитьМакет("УАС_ПФ_MXL_СертификатыНоменклатуры");
Даже если сама обработка принадлежит основной конфигурации, но макет с именем УАС_ПФ_MXL_СертификатыНоменклатуры добавлен только в расширение, платформа успешно найдет и вернет его, объединив структуры метаданных при запуске предприятия.
Еще один важный нюанс, влияющий на исполнение кода и получение макетов — это параметр Безопасный режим в настройках подключения расширения. Если у расширения в справочнике «Расширения» (или в панели администрирования) установлен флаг «Безопасный режим», платформа может блокировать некоторые операции с файловой системой, внешними компонентами или вызовами привилегированных модулей.
Для стабильной работы сложных печатных форм и обработчиков печати рекомендуется снять этот флаг в режиме «1С:Предприятие» (меню НСИ и администрирование -> Печатные формы, отчеты и обработки -> Расширения) либо в свойствах расширения в конфигураторе установить свойство Безопасный режим = Ложь.
Применяя данные рекомендации и последовательно проверяя настройки отладки, соответствие сигнатур методов и способы обращения к метаданным, вы сможете быстро локализовать и устранить любые проблемы при разработке расширений в 1С.