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

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

При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда стандартные механизмы, работающие в модуле формы, ведут себя иначе в модулях команд. Одной из таких проблем является ошибка компиляции или выполнения: «Процедура или функция с указанным именем не определена», даже если визуально процедура присутствует в тексте модуля и её имя написано верно. Рассмотрим подробнее, почему это происходит и как правильно организовать взаимодействие клиента и сервера в модуле команды.

Разбор ситуации: анализ исходного кода

Проанализируем типичный пример кода в модуле команды, который приводит к ошибке:


&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    Фор = ПолучитьФорму("Документ.Важный.ФормаОбъекта");
    ДанныеФормы = Фор.Объект;
    ЗаполнитьДокНаСервере(ДанныеФормы);
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ЗаполнитьДокНаСервере(ДанныеФормы)
    ДокОбъект = ДанныеФормыВЗначение(ДанныеФормы, Тип("ДокументОбъект.Важный"));
    // Логика заполнения...
    ЗначениеВДанныеФормы(ДокОбъект, ДанныеФормы);    
КонецПроцедуры

На первый взгляд код выглядит логичным, однако платформа выдает ошибку, сообщая, что процедура ЗаполнитьДокНаСервере не найдена. Основная причина кроется в использовании директивы &НаСервереБезКонтекста внутри модуля команды.

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

Выясним причину такого поведения системы. В управляемом приложении 1С модули делятся на контекстные и внеконтекстные. Модуль управляемой формы имеет свой контекст (данные формы), поэтому в нем разделение на &НаСервере (с передачей контекста) и &НаСервереБезКонтекста (без передачи) имеет критическое значение для производительности.

Однако модуль команды сам по себе является внеконтекстным. У него нет «своих» данных формы или реквизитов. В связи с этим в модуле команды директива &НаСервереБезКонтекста не поддерживается или интерпретируется платформой как некорректная для вызова с клиента. В модулях команд допустимы только следующие директивы:

  1. &НаКлиенте — для кода, исполняемого на стороне пользователя.
  2. &НаСервере — для выполнения серверных операций.

Как только мы заменяем &НаСервереБезКонтекста на &НаСервере, платформа корректно «видит» процедуру, и ошибка определения имени исчезает. Важно понимать: серверный вызов из модуля команды в любом случае будет «безконтекстным» по отношению к какой-либо форме, так как модуль команды не связан с конкретным экземпляром формы напрямую.

Причина 2: Правила типизации и передачи данных

Разберем следующую проблему: даже после исправления директивы программисты часто сталкиваются с тем, что данные не возвращаются в форму или возникают ошибки типизации. Рассмотрим, что происходит в строке ДанныеФормы = Фор.Объект;.

Когда мы получаем форму через ПолучитьФорму, свойство Объект имеет тип ДанныеФормыСтруктура. Передавая этот объект в серверную процедуру модуля команды, мы должны быть уверены в следующем:

Рекомендуемое решение задачи

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

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


&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    // 1. Получаем заполненную структуру данных с сервера
    СтруктураЗаполнения = ПодготовитьДанныеНаСервере();
    
    // 2. Открываем форму с параметрами заполнения
    ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", СтруктураЗаполнения);
    ОткрытьФорму("Документ.Важный.ФормаОбъекта", ПараметрыФормы);
КонецПроцедуры

&НаСервере
Функция ПодготовитьДанныеНаСервере()
    Результат = Новый Структура;
    Результат.Вставить("Дата", ТекущаяДатаСеанса());
    Результат.Вставить("Организация", Справочники.Организации.ПустаяСсылка());
    // Заполняем другие реквизиты...
    Возврат Результат;
КонецФункции

В данном случае обработка данных будет происходить в модуле самого документа в процедуре ОбработкаЗаполнения, что является стандартом разработки «1С:Совместимо».

Если необходимо изменить уже открытую форму

Если же форма уже открыта и вам нужно программно изменить её данные из модуля команды (что встречается реже), проанализируем последовательность действий:

  1. В модуле команды вызываем серверную процедуру с директивой &НаСервере.
  2. Передаем туда ДанныеФормы.
  3. На сервере используем ДанныеФормыВЗначение, вносим изменения в объект.
  4. Используем ЗначениеВДанныеФормы, чтобы обновить структуру.
  5. Важный момент: Чтобы изменения отразились в интерфейсе, на клиенте после серверного вызова может потребоваться принудительное обновление, например, через метод формы КопироватьДанныеФормы, если вы работали с копией.

Пример корректного серверного метода в модуле команды:


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

Подведем итоги

Проанализировав ситуацию, мы выяснили, что ошибка «Процедура не определена» в модуле команды чаще всего вызвана использованием директивы &НаСервереБезКонтекста. Модуль команды не поддерживает это ключевое слово, так как сам не обладает контекстом формы.

Основные правила для работы в модулях команд:

Соблюдение этих простых правил позволит вам избежать труднодиагностируемых ошибок и сделает ваш код более производительным и соответствующим стандартам платформы 1С:Предприятие 8.3.

← На главную