Разработка и Конфигурация · 10 мин
Как вызвать процедуру из расширения в 1С
Как вызвать процедуру из расширения 1С: аннотации ИзменениеИКонтроль, Вместо, Перед и После, вызов общих модулей, типичные ошибки и проверка результата.
Расширение в 1С позволяет добавлять и изменять логику типовой конфигурации без снятия её с поддержки. Однако вызов процедуры из расширения работает не так, как обычный вызов внутри основной конфигурации: здесь действуют особые правила видимости, аннотации перехвата и ограничения платформы. Непонимание этих правил приводит к ошибкам «Процедура или функция не обнаружена» и к молча не выполняющемуся коду.
В материале разобраны основные сценарии: вызов процедуры расширения из модуля основной конфигурации, перехват типовых процедур через аннотации, вызов собственных общих модулей расширения и работа с подписками на события. Примеры приведены для управляемых форм и актуальных версий платформы 1С:Предприятие 8.3.
Как устроена видимость кода расширения
Расширение подключается к информационной базе поверх основной конфигурации. Код расширения «видит» объекты и модули основной конфигурации, но обратное неверно: типовая конфигурация ничего не знает о существовании расширения. Поэтому прямой вызов вида МойМодульРасширения.МояПроцедура() из типового общего модуля невозможен — при проверке модуля будет ошибка.
Это принципиальное ограничение, а не недоработка. Расширение может быть отключено или удалено, и конфигурация обязана оставаться работоспособной. Поэтому все сценарии вызова строятся вокруг двух механизмов: перехвата вызовов типовых процедур и собственных объектов расширения, к которым обращается код самого расширения.
Перехват типовой процедуры через аннотации
Самый частый сценарий — нужно, чтобы вместо типовой процедуры (или в дополнение к ней) выполнился код расширения. Для этого модуль, содержащий процедуру, заимствуется в расширение, а процедура объявляется с одной из аннотаций.
Аннотации &Перед и &После
Аннотация &Перед("ИмяТиповойПроцедуры") выполняет код расширения до вызова типовой процедуры, &После — после её завершения. Сигнатура (состав параметров) должна полностью совпадать с типовой процедурой, иначе перехват не сработает.
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Код расширения выполнится после типового обработчика
Сообщить("Форма создана, расширение сработало");
КонецПроцедуры
Аннотация &Вместо
Аннотация &Вместо полностью подменяет типовую процедуру. Типовой код при этом не выполняется, если его не вызвать явно через ПродолжитьВызов(). Это рискованный вариант: при обновлении типовой конфигурации изменения в перекрытой процедуре не применятся, и логика может устареть.
&Вместо("РассчитатьСкидку")
Функция Расш1_РассчитатьСкидку(ПараметрыДокумента)
Если ПараметрыДокумента.ЕстьАкция Тогда
Возврат 10; // своя логика
КонецЕсли;
Возврат ПродолжитьВызов(ПараметрыДокумента); // типовая логика
КонецФункции
Аннотация &ИзменениеИКонтроль
Аннотация &ИзменениеИКонтроль — самый безопасный способ перехвата. Типовой текст процедуры вставляется в расширение целиком между директивами #Область, и разработчик вносит точечные правки, помечая их комментариями. При обновлении конфигурации платформа сравнивает типовой текст с зафиксированным и сообщает о расхождениях, позволяя контролируемо перенести изменения.
Вызов процедуры из собственного общего модуля расширения
Внутри расширения можно создавать собственные общие модули. Вызов процедуры из такого модуля ничем не отличается от обычного: МойОбщийМодуль.ВыполнитьОбработку(Параметр). Главное условие — вызывающий код тоже должен находиться в расширении: в заимствованной форме, в перехваченной процедуре, в подписке на событие расширения.
Типичная архитектура выглядит так: перехваченная процедура содержит минимум кода и делегирует работу собственному общему модулю расширения. Это упрощает сопровождение: вся прикладная логика собрана в одном месте, а перехватчики остаются тонкими и легко переносятся при обновлении.
- 1Добавьте в расширение собственный общий модуль, установите нужные флаги (Сервер, ВызовСервера, Клиент)
- 2Создайте в нём экспортную процедуру с ключевым словом Экспорт
- 3Заимствуйте в расширение модуль формы или объекта, откуда нужен вызов
- 4Добавьте перехватчик с аннотацией (&После, &Вместо или &ИзменениеИКонтроль)
- 5В теле перехватчика вызовите процедуру своего общего модуля
- 6Обновите конфигурацию базы данных и проверьте работу в режиме Предприятия
Вызов через подписки на события и переопределяемые модули
Если перехват конкретной процедуры невозможен или неудобен, используют подписки на события. Расширение позволяет создавать собственные подписки на события объектов (ПриЗаписи, ОбработкаПроведения и другие) и привязывать их к обработчикам в общих модулях расширения. Это фактически вызов процедуры расширения по событию, инициированному платформой.
Второй путь — переопределяемые модули типовой конфигурации (например, модули с суффиксом «Переопределяемый» в конфигурациях на БСП). Типовой код сам вызывает процедуры этих модулей, поэтому перехват процедуры в таком модуле через &ИзменениеИКонтроль даёт легальную точку расширения, предусмотренную поставщиком. Это предпочтительный вариант, когда он доступен.
Сравнение способов вызова
Подходят для добавления логики без изменения типовой. Ограничение: нельзя изменить результат типовой функции напрямую.
Полная подмена логики. Риск: пропуск изменений типовой процедуры при обновлении конфигурации.
Точечное изменение с контролем при обновлении. Требует дисциплины при переносе правок.
Вызов по событию платформы без перехвата конкретной процедуры. Не подходит для обработчиков форм.
Ограничения и контекст вызова
При вызове процедур расширения нужно учитывать контекст исполнения. Клиентская процедура не может вызвать серверную напрямую — потребуется серверная процедура в общем модуле с флагом «Вызов сервера» или серверный вызов из модуля формы. Также в расширениях есть ограничения на изменение некоторых объектов: например, нельзя расширять модули менеджеров некоторых типов объектов в старых версиях платформы, а безопасный режим расширения запрещает обращения к файловой системе и COM-объектам.
Отдельный момент — фоновые задания. Процедуру общего модуля расширения можно запустить через ФоновыеЗадания.Выполнить("МойМодуль.МояПроцедура", Параметры), если расширение подключено в сеансе, где выполняется задание. Если расширение подключено только для конкретного пользователя, фоновое задание из сеанса другого пользователя процедуру не найдёт.
Проверка результата и типичные ошибки
После подключения расширения проверьте, что перехват реально срабатывает: поставьте точку останова в отладчике или временно выведите сообщение. Если процедура не вызывается, чаще всего причина в несовпадении сигнатуры, в том, что расширение не применено к базе (кнопка «Обновить» в списке расширений), или в неподходящем режиме совместимости.
Ещё одна проверка — журнал регистрации и окно ошибок при запуске. Если при обновлении конфигурации расширение перестало применяться, платформа сообщит о несовместимости: обычно это удалённый или переименованный заимствованный объект. В таком случае перехватчик нужно пересоздать заново от актуальной типовой процедуры.
Как проверить результат
Точка останова в процедуре расширения активируется при выполнении операции
Отладчик не заходит в процедуру — проверьте аннотацию и сигнатуру
В списке расширений статус без ошибок, база обновлена
Расширение отмечено как неприменённое или с предупреждением
Код модуля расширения выполняется и возвращает результат
Ошибка «Процедура или функция не обнаружена»
Что важно запомнить
Из основной конфигурации процедуру расширения вызвать нельзя — работайте через перехват (&ИзменениеИКонтроль предпочтительнее &Вместо), собственные общие модули расширения и подписки на события. Следите за совпадением сигнатур, контекстом исполнения и применением расширения к базе.
Частые вопросы
Можно ли вызвать процедуру расширения напрямую из типового общего модуля?
Нет, типовая конфигурация не видит объекты расширения. Обходные пути — перехват процедуры переопределяемого модуля, который типовой код вызывает сам, либо подписка на событие, обработчик которой находится в расширении.
Почему перехватчик с аннотацией &После не выполняется?
Чаще всего не совпадает сигнатура: состав и порядок параметров должны точно повторять типовую процедуру. Также проверьте, что расширение применено к базе, а заимствованный модуль не изменился при обновлении конфигурации.
Чем &ИзменениеИКонтроль лучше &Вместо?
&ИзменениеИКонтроль сохраняет типовой текст процедуры внутри расширения и при обновлении конфигурации показывает расхождения, позволяя перенести правки контролируемо. &Вместо полностью подменяет процедуру, и изменения поставщика применяться не будут.
Можно ли вызвать процедуру расширения из фонового задания?
Да, через ФоновыеЗадания.Выполнить с указанием имени метода общего модуля расширения. Условие — расширение должно быть подключено в сеансе, где выполняется задание, иначе метод не будет найден.
Работает ли вызов процедур расширения в безопасном режиме?
Безопасный режим не запрещает сам вызов процедур, но ограничивает опасные операции: доступ к файловой системе, COM-объектам, внешним компонентам. Если процедура расширения использует такие операции, её нужно перепроектировать или отключить безопасный режим для данного расширения с пониманием рисков.