Как вызвать неэкспортную функцию через расширение и исправить ошибку вызова метода с аннотацией Вместо

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

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

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

Почему возникает ошибка при прямом вызове метода расширения

Проанализируем механику перехвата методов платформой 1С:Предприятие 8.3. Аннотация &Вместо предназначена исключительно для изменения поведения типового метода при его штатном вызове самой системой. Когда типовой код обращается к оригинальной функции, платформа перехватывает управление и передает его в расширяющий метод. В этот момент неявно формируется стек перехвата, благодаря которому метод глобального контекста ПродолжитьВызов() знает, какую именно оригинальную реализацию нужно запустить.

Если же разработчик пытается вызвать метод расширения напрямую по его собственному имени из внешней обработки или другого модуля (например, Документы.ВедомостьНаВыплатуЗарплатыПеречислением.РасшПечатьПер_ПечатьСписокПеречислений(...)), стек перехвата не инициализируется. В этой ситуации платформа не может выполнить ПродолжитьВызов() и выбрасывает исключение времени выполнения.

Способ 1. Создание экспортной функции-обертки (рекомендуемый вариант)

Рассмотрим штатный и наиболее надежный способ вызова неэкспортных алгоритмов. Модуль расширения и исходный модуль конфигурации исполняются в общем контексте — в едином пространстве имен. Это означает, что из любого метода расширения доступны все локальные (неэкспортные) функции и процедуры оригинального модуля напрямую по их именам без каких-либо специальных директив.

Разберем по шагам создание метода-обертки:

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

Посмотрим на пример правильного кода функции-обертки в модуле менеджера расширения:


// Собственная экспортная функция расширения без аннотаций перехвата
Функция РасшПечатьПер_ПечатьСписокПеречисленийЭкспорт(МассивОбъектов, ОбъектыПечати) Экспорт

	// Прямой вызов неэкспортной типовой функции оригинального модуля менеджера
	Результат = ПечатьСписокПеречислений(МассивОбъектов, ОбъектыПечати);
	
	Возврат Результат;

КонецФункции

Теперь из любого внешнего кода (из внешней обработки или подключаемой печатной формы) можно вызвать нашу функцию-обертку:


РезультатПечати = Документы.ВедомостьНаВыплатуЗарплатыПеречислением.РасшПечатьПер_ПечатьСписокПеречисленийЭкспорт(МассивДокументов, КоллекцияОбъектов);

При таком подходе не требуется копировать код исходной функции и переносить вспомогательные процедуры. Весь типовой алгоритм выполняется в своем «родном» модуле со всеми внутренними взаимосвязями.

Решение проблемы с видимостью общих модулей и контролем синтаксиса

При работе с расширениями разработчики нередко сталкиваются с ошибками синтаксического контроля вида Переменная не определена или сообщениями о том, что общие модули недоступны из расширения. Выясним причину этого поведения:

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

Способ 2. Экспорт метода через аннотацию ИзменениеИКонтроль

Если версия режима совместимости конфигурации — 8.3.14 или выше, можно сделать исходный метод экспортным напрямую с помощью директивы &ИзменениеИКонтроль.

Рассмотрим, как это реализуется:

  1. Заимствуем метод ПечатьСписокПеречислений в расширение с аннотацией &ИзменениеИКонтроль.
  2. С помощью инструкции препроцессора #Вставка добавляем ключевое слово Экспорт в заголовок функции.

Посмотрим на пример реализации:


&ИзменениеИКонтроль("ПечатьСписокПеречислений")
Функция РасшПечатьПер_ПечатьСписокПеречислений(МассивОбъектов, ОбъектыПечати) #Вставка Экспорт #КонецВставки
	// Вся типовая реализация метода остается без изменений
	// ...
КонецФункции

В результате исходный типовой метод становится экспортным, и к нему можно обращаться из внешнего кода по стандартному имени Документы.ВедомостьНаВыплатуЗарплатыПеречислением.ПечатьСписокПеречислений(...).

← На главную