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

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

При переходе с разработки управляемых форм на обычные формы (или при поддержке старых конфигураций) программисты часто сталкиваются с непониманием того, как работает клиент-серверное взаимодействие. Ошибка «Процедура или функция с указанным именем не определена» в обычном приложении часто возникает из-за попытки использовать механизмы управляемого приложения (такие как директивы &НаСервере) там, где они не поддерживаются. Разберем эту ситуацию подробно, проанализируем причины возникновения ошибки и найдем правильные способы организации кода.

Причина 1: Неправильное использование директив компиляции

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

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


#Если Сервер Тогда
Функция ПечатьТОРГ13() Экспорт
    // Код, который должен выполняться только на сервере
КонецФункции
#КонецЕсли

Однако даже правильное использование препроцессора не решит проблему видимости функции из формы. Если вы находитесь в модуле формы и хотите вызвать экспортную функцию из модуля объекта этой же обработки, система не найдет её по простому имени ПечатьТОРГ13(). Она будет искать её только внутри модуля самой формы.

Причина 2: Контекст вызова функции в обычной форме

Рассмотрим ситуацию: функция расположена в модуле объекта, а вызывается из модуля формы. В управляемых формах мы привыкли, что серверный контекст доступен «напрямую» через вызов метода. В обычных формах объект управления (обработка или документ) доступен через переменную ЭтотОбъект (в форме обработки) или ДокументОбъект (в форме документа).

Чтобы форма «увидела» функцию из модуля объекта, вызов должен выглядеть так:


Процедура СоздатьЭД()
    Если ВидДокумента = Перечисления.ВидыДокументовЭДО.Торг13 Тогда
        // Обращаемся через контекст объекта
        МакетДокумента = ЭтотОбъект.ПечатьТОРГ13();
    КонецЕсли;
КонецПроцедуры

Если же вы используете РеквизитФормыВЗначение("Объект"), как предлагалось в некоторых сообщениях форума, помните — этот метод предназначен только для управляемых форм. В обычной форме объект уже находится в памяти клиента целиком, и дополнительные преобразования не требуются.

Причина 3: Передача мутабельных значений

Выясним причину другой важной ошибки, упомянутой в обсуждении: «Попытка передачи с клиента на сервер мутабельного значения». Эта проблема возникает, когда вы пытаетесь передать сложный объект (например, ВыборкаИзРезультатаЗапроса, СтрокаТабличнойЧасти или ДокументОбъект) в метод общего модуля, который выполняется на сервере.

Проанализируем ситуацию: обычное приложение чаще всего работает в режиме Толстого клиента. Это означает, что модуль формы и модуль объекта выполняются на стороне клиента. Как только вы вызываете функцию общего модуля, у которого стоит флаг Сервер, 1С пытается передать параметры по сети на сервер. Но сложные объекты (мутабельные) не могут быть сериализованы (превращены в набор байтов для передачи).

Как решить проблему с мутабельными значениями:

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

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


// На клиенте (в модуле формы или объекта)
ДанныеДляСервера = Новый Структура;
ДанныеДляСервера.Вставить("Номенклатура", ВыборкаСтрокТовары.Номенклатура);
ДанныеДляСервера.Вставить("Серия", ВыборкаСтрокТовары.Серия);

// Вызов функции серверного общего модуля
Результат = ФормированиеПечатныхФормСервер.ПредставлениеСерий(ДанныеДляСервера);

Как правильно организовать вызов сервера в обычном приложении

Рассмотрим по шагам правильный алгоритм действий, если вам нужно выполнить тяжелый запрос на сервере из обычной формы:

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

Важно помнить, что в режиме обычного приложения разделение на клиент и сервер не такое жесткое, как в управляемом. Если ваша конфигурация работает исключительно в файловом режиме или в толстом клиенте без сервера 1С:Предприятия, то весь код фактически выполняется в одном процессе. Однако архитектурно правильно всегда разделять интерфейсную логику и логику работы с данными, чтобы избежать ошибок при переходе на клиент-серверный вариант работы.

Резюме для исправления конкретного случая автора

Проанализировав ситуацию автора темы, можно сделать следующие выводы:

Таким образом, понимание того, что в обычных формах объект «живет» на клиенте целиком, а связь с сервером осуществляется через специально настроенные общие модули, позволяет избежать большинства ошибок типизации и видимости методов.

← На главную