При разработке и адаптации типовых решений на платформе 1С:Предприятие часто возникает задача изменить поведение конкретной процедуры формы документа без снятия основной конфигурации с поддержки. Однако при попытке просто объявить в модуле расширения процедуру с префиксом или с тем же именем разработчики сталкиваются с тем, что код либо игнорируется, либо вызывает ошибку синтаксического контроля «Процедура с таким именем уже определена». Разберем, почему так происходит и как правильно переопределять процедуры управляемых форм в расширениях.
Рассмотрим частую ошибку, когда в форму расширения добавляется процедура с префиксом расширения, например:
&НаКлиенте
Процедура даг_ПробитьЧекЗавершение(Результат, ДополнительныеПараметры) Экспорт
// Пользовательский код обработки завершения
КонецПроцедуры
Если в типовой конфигурации вызов осуществляется асинхронно через объект ОписаниеОповещения, инициатор операции обращается к процедуре по ее оригинальному строковому имени ("ПробитьЧекЗавершение"). Простое добавление нового метода с префиксом даг_ не связывает его с типовым алгоритмом. Платформа продолжает вызывать исходную процедуру формы, игнорируя созданный метод.
Если же объявить процедуру с точно таким же именем без специальных инструкций, платформа выдаст ошибку дублирования имени метода.
Начиная с версии платформы 8.3.9 и соответствующего режима совместимости, в 1С реализован полноценный механизм перехвата процедур и функций при помощи аннотаций. Это основной и наиболее правильный способ модификации логики типовых модулей без снятия с поддержки.
Разберем доступные аннотации перехвата:
ПродолжитьВызов().Посмотрим на пример правильного переопределения процедуры обратного вызова в модуле расширения формы:
&НаКлиенте
&Вместо("ПробитьЧекЗавершение")
Процедура даг_ПробитьЧекЗавершение(Результат, ДополнительныеПараметры)
Если Результат.ВыполненаОперацияНаУстройстве И Результат.ИзмененныеДанныеЗаписаны Тогда
ТолькоПросмотр = Истина;
ЗагрузитьНовыйЧек();
ИначеЕсли Результат.ВыполненаОперацияНаУстройстве И Не Результат.ИзмененныеДанныеЗаписаны Тогда
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Данные", Объект.Ссылка);
ПараметрыФормы.Вставить("ДанныеДляЖурналаРегистрации", ДанныеДляЖурналаРегистрации);
ПараметрыФормы.Вставить("ТекстСообщения", НСтр("ru = 'ВНИМАНИЕ! Чек пробит, но не зафиксирован в системе.'"));
ОткрытьФорму("Документ.ЧекККМ.Форма.ОшибкаЗаписи", ПараметрыФормы, ЭтотОбъект);
КонецЕсли;
КонецПроцедуры
Важные правила при использовании аннотаций перехвата:
&НаКлиенте, &НаСервере, &НаСервереБезКонтекста) у метода в расширении обязана в точности совпадать с директивой перехватываемого метода.Если необходимо переопределить стандартное событие формы (например, ПриСозданииНаСервере) или команду, заимствованную в расширение, важно помнить о привязке обработчика:
даг_ПриСозданииНаСервере), необходимо в свойствах формы расширения в палитре свойств явно привязать событие ПриСозданииНаСервере к новой процедуре.&После("ПриСозданииНаСервере") или &Перед("ПриСозданииНаСервере"), явная привязка в свойствах не требуется — платформа свяжет вызовы автоматически по имени аннотации.Рассмотрим пример добавления условного оформления динамических данных при открытии формы с использованием аннотации &После:
&НаСервере
&После("ПриСозданииНаСервере")
Процедура даг_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
даг_ОформитьТабличнуюЧасть();
КонецПроцедуры
&НаСервере
Процедура даг_ОформитьТабличнуюЧасть()
// Пользовательская логика настройки условного оформления
ЭлементУО = УсловноеОформление.Элементы.Добавить();
ПолеУО = ЭлементУО.Поля.Элементы.Добавить();
ПолеУО.Поле = Новый ПолеКомпоновкиДанных("Товары");
ЭлементОтбора = ЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Количество");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.МеньшеИлиРавно;
ЭлементОтбора.ПравоеЗначение = 0;
ЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.Красный);
КонецПроцедуры
Если на проекте используется современная версия платформы (8.3.15 и новее) с соответствующим режимом совместимости, вместо полного перекрытия через &Вместо рекомендуется применять аннотацию &ИзменениеИКонтроль("<ИмяМетода>").
Этот механизм позволяет с помощью инструкций препроцессора #Вставка и #Удаление изменить только нужный фрагмент кода внутри типовой процедуры. Это значительно снижает затраты на обновление конфигурации, так как платформа контролирует совпадение неизмененного тела процедуры с оригиналом из основной конфигурации.