Почему при перехвате метода в расширении 1С возникает ошибка «Процедура или функция не определена (ОткрытьФормуМодально)»?

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

При разработке расширений конфигурации разработчики часто сталкиваются с ситуацией, когда типовой код, перенесенный в расширение с помощью аннотации &Вместо, перестает проходить синтаксическую проверку или вызывает исключение. Типичный пример — ошибка компиляции при вызове клиентских интерфейсных методов, таких как ОткрытьФормуМодально, ОткрытьФорму или Предупреждение с пометкой «(Проверка: Сервер)».

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

Причина ошибки: контекст компиляции по умолчанию

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

Справочник.Номенклатура.Форма.ФормаЭлемента.Форма(6,19): Процедура или функция с указанным именем не определена (ОткрытьФормуМодально) (Проверка: Сервер)

Обратим внимание на указание контекста проверки. В модулях управляемых форм 1С действует следующее правило: если перед процедурой или функцией не указана явная директива компиляции, платформа по умолчанию считает данный метод серверным (&НаСервере).

Аннотация &Вместо("ИмяПроцедуры") указывает платформе лишь на то, какой именно метод основной конфигурации подлежит замене, но она не определяет контекст выполнения процедуры в расширении. В результате метод компилируется на сервере, где клиентские функции работы с интерфейсом (включая открытие форм и диалоги) попросту отсутствуют.

Решение 1: Корректное указание директивы компиляции и префикса метода

Чтобы метод расширения выполнялся в клиентском контексте, необходимо явно объявить директиву &НаКлиенте сразу после аннотации &Вместо. Кроме того, по стандартам разработки 1С не рекомендуется называть процедуру в расширении точно так же, как в основной конфигурации — ей следует задать уникальный префикс расширения во избежание коллизий имен.

Рассмотрим правильный синтаксис перехвата клиентской процедуры:


&Вместо("ВыбратьКартинкуИзПрисоединенныхФайлов")
&НаКлиенте
Процедура Расш1_ВыбратьКартинкуИзПрисоединенныхФайлов(Команда)
    
    _ПараметрыВыбора = Новый Структура("ВладелецФайла, ЗакрыватьПриВыборе, РежимВыбора", 
                                       Объект.Ссылка, Истина, Истина);
    ЗначениеВыбора = ОткрытьФормуМодально("ОбщаяФорма.ПрисоединенныеФайлы", _ПараметрыВыбора);
    
    Если ЗначениеЗаполнено(ЗначениеВыбора) Тогда
        Объект.ФайлКартинки = ЗначениеВыбора;
        АдресКартинки = НавигационнаяСсылкаКартинки(Объект.ФайлКартинки, УникальныйИдентификатор);
    КонецЕсли;
    
КонецПроцедуры

Разберем по шагам ключевые правила оформления перехвата:

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

Решение 2: Переход на асинхронную модель работы (отказ от модальности)

Если в конфигурации отключен режим совместимости или свойство «Режим использования модальности» установлено в значение «Не использовать», синхронный вызов ОткрытьФормуМодально приведет к ошибке времени выполнения.

В современных типовых конфигурациях вместо блокирующего модального вызова рекомендуется применять асинхронное открытие формы с использованием объекта ОписаниеОповещения.

Посмотрим на пример перевода исходного алгоритма на асинхронный вызов:


&Вместо("ВыбратьКартинкуИзПрисоединенныхФайлов")
&НаКлиенте
Процедура Расш1_ВыбратьКартинкуИзПрисоединенныхФайлов(Команда)
    
    ПараметрыВыбора = Новый Структура("ВладелецФайла, ЗакрыватьПриВыборе, РежимВыбора", 
                                      Объект.Ссылка, Истина, Истина);
    
    Оповещение = Новый ОписаниеОповещения("Расш1_ПослеВыбораКартинки", ЭтотОбъект);
    
    ОткрытьФорму("ОбщаяФорма.ПрисоединенныеФайлы", 
                 ПараметрыВыбора, 
                 ЭтотОбъект, 
                 , 
                 , 
                 , 
                 Оповещение, 
                 РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
                 
КонецПроцедуры

&НаКлиенте
Процедура Расш1_ПослеВыбораКартинки(ЗначениеВыбора, ДополнительныеПараметры) Экспорт
    
    Если ЗначениеЗаполнено(ЗначениеВыбора) Тогда
        Объект.ФайлКартинки = ЗначениеВыбора;
        АдресКартинки = НавигационнаяСсылкаКартинки(Объект.ФайлКартинки, УникальныйИдентификатор);
    КонецЕсли;
    
КонецПроцедуры

Использование параметра РежимОткрытияОкнаФормы.БлокироватьОкноВладельца позволяет сохранить поведение интерфейса аналогичным модальному (пользователь не сможет нажимать кнопки родительской формы до завершения выбора), полностью соблюдая требования платформы к работе без модальности.

← На главную