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