При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда стандартные механизмы, работающие в модуле формы, ведут себя иначе в модулях команд. Одной из таких проблем является ошибка компиляции или выполнения: «Процедура или функция с указанным именем не определена», даже если визуально процедура присутствует в тексте модуля и её имя написано верно. Рассмотрим подробнее, почему это происходит и как правильно организовать взаимодействие клиента и сервера в модуле команды.
Проанализируем типичный пример кода в модуле команды, который приводит к ошибке:
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
Фор = ПолучитьФорму("Документ.Важный.ФормаОбъекта");
ДанныеФормы = Фор.Объект;
ЗаполнитьДокНаСервере(ДанныеФормы);
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ЗаполнитьДокНаСервере(ДанныеФормы)
ДокОбъект = ДанныеФормыВЗначение(ДанныеФормы, Тип("ДокументОбъект.Важный"));
// Логика заполнения...
ЗначениеВДанныеФормы(ДокОбъект, ДанныеФормы);
КонецПроцедуры
На первый взгляд код выглядит логичным, однако платформа выдает ошибку, сообщая, что процедура ЗаполнитьДокНаСервере не найдена. Основная причина кроется в использовании директивы &НаСервереБезКонтекста внутри модуля команды.
Выясним причину такого поведения системы. В управляемом приложении 1С модули делятся на контекстные и внеконтекстные. Модуль управляемой формы имеет свой контекст (данные формы), поэтому в нем разделение на &НаСервере (с передачей контекста) и &НаСервереБезКонтекста (без передачи) имеет критическое значение для производительности.
Однако модуль команды сам по себе является внеконтекстным. У него нет «своих» данных формы или реквизитов. В связи с этим в модуле команды директива &НаСервереБезКонтекста не поддерживается или интерпретируется платформой как некорректная для вызова с клиента. В модулях команд допустимы только следующие директивы:
Как только мы заменяем &НаСервереБезКонтекста на &НаСервере, платформа корректно «видит» процедуру, и ошибка определения имени исчезает. Важно понимать: серверный вызов из модуля команды в любом случае будет «безконтекстным» по отношению к какой-либо форме, так как модуль команды не связан с конкретным экземпляром формы напрямую.
Разберем следующую проблему: даже после исправления директивы программисты часто сталкиваются с тем, что данные не возвращаются в форму или возникают ошибки типизации. Рассмотрим, что происходит в строке ДанныеФормы = Фор.Объект;.
Когда мы получаем форму через ПолучитьФорму, свойство Объект имеет тип ДанныеФормыСтруктура. Передавая этот объект в серверную процедуру модуля команды, мы должны быть уверены в следующем:
ДанныеФормы копируется целиком. Если документ содержит тысячи строк в табличных частях, это приведет к значительным задержкам.ДанныеФормыВЗначение требует точного указания типа. Если в параметре ДанныеФормы передана структура, не соответствующая типу ДокументОбъект, возникнет ошибка выполнения.Вместо того чтобы пытаться «насиловать» сервер передачей тяжелых объектов данных формы из модуля команды, мы рекомендуем использовать более изящный подход. Если ваша цель — заполнить новый документ, лучше подготовить структуру данных на сервере и вернуть её на клиент.
Посмотрим на пример правильной реализации:
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
// 1. Получаем заполненную структуру данных с сервера
СтруктураЗаполнения = ПодготовитьДанныеНаСервере();
// 2. Открываем форму с параметрами заполнения
ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", СтруктураЗаполнения);
ОткрытьФорму("Документ.Важный.ФормаОбъекта", ПараметрыФормы);
КонецПроцедуры
&НаСервере
Функция ПодготовитьДанныеНаСервере()
Результат = Новый Структура;
Результат.Вставить("Дата", ТекущаяДатаСеанса());
Результат.Вставить("Организация", Справочники.Организации.ПустаяСсылка());
// Заполняем другие реквизиты...
Возврат Результат;
КонецФункции
В данном случае обработка данных будет происходить в модуле самого документа в процедуре ОбработкаЗаполнения, что является стандартом разработки «1С:Совместимо».
Если же форма уже открыта и вам нужно программно изменить её данные из модуля команды (что встречается реже), проанализируем последовательность действий:
&НаСервере.ДанныеФормы.ДанныеФормыВЗначение, вносим изменения в объект.ЗначениеВДанныеФормы, чтобы обновить структуру.КопироватьДанныеФормы, если вы работали с копией.Пример корректного серверного метода в модуле команды:
&НаСервере
Процедура ЗаполнитьДокНаСервере(ДанныеФормы)
// Преобразуем данные формы в реальный объект для работы с его методами
ДокОбъект = ДанныеФормыВЗначение(ДанныеФормы, Тип("ДокументОбъект.Важный"));
// Выполняем действия, доступные только на сервере (например, работа с запросами)
ДокОбъект.ЗаполнитьПоОстаткам();
// Возвращаем измененный объект обратно в структуру данных формы
ЗначениеВДанныеФормы(ДокОбъект, ДанныеФормы);
КонецПроцедуры
Проанализировав ситуацию, мы выяснили, что ошибка «Процедура не определена» в модуле команды чаще всего вызвана использованием директивы &НаСервереБезКонтекста. Модуль команды не поддерживает это ключевое слово, так как сам не обладает контекстом формы.
Основные правила для работы в модулях команд:
&НаСервере вместо &НаСервереБезКонтекста.ДанныеФормы между клиентом и сервером в команде — это ресурсоемкая операция сериализации.ОбработкаЗаполнения в модуле объекта.Соблюдение этих простых правил позволит вам избежать труднодиагностируемых ошибок и сделает ваш код более производительным и соответствующим стандартам платформы 1С:Предприятие 8.3.