К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как из формы 1С обратиться к модулю объекта

Как из формы 1С вызвать процедуру или функцию модуля объекта: ЭтотОбъект, ДанныеФормыВЗначение, ПолучитьОбъект. Примеры кода, ошибки и ограничения.

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

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

Почему из формы нельзя напрямую обратиться к модулю объекта

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

Дополнительное ограничение — разделение на клиентский и серверный контексты. Код с директивой &НаКлиенте вообще не имеет доступа к объектам базы данных: там нельзя создать объект, получить его по ссылке или вызвать его метод. Вся работа с объектами возможна только на сервере.

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

Способ 1: ДанныеФормыВЗначение и РеквизитФормыВЗначение

Основной и рекомендуемый способ для управляемых форм — преобразовать данные формы в прикладной объект, вызвать нужный метод, а затем при необходимости вернуть изменённые данные обратно в форму.

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

&НаСервере

Процедура ВыполнитьРасчетНаСервере()

ДокОбъект = РеквизитФормыВЗначение("Объект");

ДокОбъект.РассчитатьИтоги(); // процедура из модуля объекта

ЗначениеВРеквизитФормы(ДокОбъект, "Объект");

КонецПроцедуры

&НаКлиенте

Процедура Рассчитать(Команда)

ВыполнитьРасчетНаСервере();

КонецПроцедуры

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

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

Способ 2: ПолучитьОбъект() по ссылке

Если объект уже записан в базу данных, можно получить его по ссылке методом ПолучитьОбъект(). Этот вариант подходит, когда нужно работать именно с сохранёнными данными, а не с текущими данными формы, которые могут быть изменены пользователем, но ещё не записаны.

&НаСервере

Процедура ПроверитьДокументНаСервере()

ДокОбъект = Объект.Ссылка.ПолучитьОбъект();

ДокОбъект.ПроверитьКорректность(); // метод модуля объекта

КонецПроцедуры

У этого способа есть важное ограничение: для нового, ещё не записанного объекта ПолучитьОбъект() вернёт Неопределено, и попытка вызвать метод приведёт к ошибке. Кроме того, данные, полученные через ПолучитьОбъект(), не синхронизируются с данными формы автоматически — изменения в объекте не отобразятся в открытой форме.

Ещё один риск: если вызвать Записать() у объекта, полученного по ссылке, пока форма с тем же объектом открыта и изменена, при последующей записи из формы возникнет конфликт версий («Данные были изменены другим пользователем»).

Способ 3: обычные формы и свойство ЭтотОбъект

В обычных (неуправляемых) формах ситуация проще: там нет разделения на клиент и сервер, а модуль формы имеет прямой доступ к объекту через свойство ЭтотОбъект. Вызов метода модуля объекта выглядит тривиально.

Процедура КнопкаРассчитатьНажатие(Элемент)

ЭтотОбъект.РассчитатьИтоги(); // метод модуля объекта

КонецПроцедуры

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

Однако в современных конфигурациях обычные формы встречаются всё реже, поэтому основной сценарий — именно управляемые формы с преобразованием данных.

Сравнение способов и критерии выбора

Выбор способа зависит от типа формы, состояния объекта (записан или нет) и от того, нужно ли отразить результат в интерфейсе.

СпособКогда применятьОграничения
РеквизитФормыВЗначениеУправляемая форма, нужен вызов метода и возврат результата в формуТолько на сервере; затратно при больших объёмах данных
Ссылка.ПолучитьОбъект()Объект записан, работа с сохранёнными данными вне формыНе работает для новых объектов; нет синхронизации с формой
ЭтотОбъектОбычные формыНе применимо в управляемом приложении
Менеджер объекта (Справочники.Имя.Метод)Общие операции, не зависящие от конкретного экземпляраТребует переноса логики в модуль менеджера
Маршрут решения

Как выбрать действие

Управляемая форма, нужно выполнить метод и показать результат пользователюИспользуйте РеквизитФормыВЗначение + ЗначениеВРеквизитФормы в серверной процедуре
Объект записан и форма не должна менятьсяВызовите Ссылка.ПолучитьОбъект() и работайте с объектом на сервере
Логика не привязана к конкретному объекту (поиск, создание, расчёты по группе)Перенесите код в модуль менеджера и вызывайте через Справочники.Имя.Метод()
Конфигурация на обычных формахВызывайте метод напрямую через ЭтотОбъект

Альтернатива: модуль менеджера и общие модули

Частая ситуация: метод в модуле объекта фактически не использует данные конкретного экземпляра, а выполняет общую операцию — например, ищет дубли или формирует печатную форму. В таком случае правильнее разместить код в модуле менеджера объекта. Тогда из формы он вызывается напрямую, без преобразования данных:

&НаСервере

Функция ПолучитьПечатнуюФормуНаСервере()

Возврат Документы.РеализацияТоваров.СформироватьПечатнуюФорму(Объект.Ссылка);

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

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

Куда поместить логику

Модуль объекта

Логика использует реквизиты конкретного экземпляра: проверки, расчёты табличных частей, обработчики проведения

Модуль менеджера

Операции над коллекцией или без привязки к экземпляру: поиск, печать, создание по шаблону

Общий модуль

Переиспользуемый код, нужный из разных объектов и механизмов

Типичные ошибки и как их избежать

Первая ошибка — попытка вызвать метод объекта из клиентской процедуры. Код &НаКлиенте с обращением к РеквизитФормыВЗначение не скомпилируется: эти методы доступны только на сервере. Решение — клиентская процедура-обёртка, вызывающая серверную.

Вторая ошибка — забыть вернуть изменённые данные в форму. После РеквизитФормыВЗначение вы работаете с копией данных: все изменения, сделанные методом объекта, останутся в этой копии и не отобразятся в форме, если не вызвать ЗначениеВРеквизитФормы.

Третья ошибка — вызов неэкспортной процедуры. Если в модуле объекта процедура объявлена без Экспорт, при обращении возникнет ошибка «Процедура или функция с указанным именем не определена». Проверьте объявление метода.

Четвёртая ошибка — использование ПолучитьОбъект() для нового объекта. Перед вызовом проверяйте ссылку: Если Не Объект.Ссылка.Пустая() Тогда ....

Типичные ошибки
01
Вызов РеквизитФормыВЗначение в клиентской процедуре — метод доступен только на сервере, код не скомпилируется
02
Пропуск ЗначениеВРеквизитФормы после вызова метода — изменения не отображаются в форме
03
Обращение к процедуре без Экспорт — ошибка «процедура не определена»
04
ПолучитьОбъект() для незаписанного объекта — результат Неопределено и ошибка вызова метода
05
Запись объекта, полученного по ссылке, при открытой форме — конфликт версий при сохранении

Проверка результата

После внедрения вызова проверьте цепочку целиком: клиентская команда вызывает серверную процедуру, та получает объект, метод выполняется, данные возвращаются в форму. Удобно временно добавить вывод в сообщение или использовать отладчик с точкой останова в модуле объекта — так вы убедитесь, что управление действительно доходит до нужного метода.

Обратите внимание на производительность: РеквизитФормыВЗначение сериализует все данные формы, включая табличные части. Для документов с тысячами строк это заметная операция. Если метод обращается только к нескольким реквизитам шапки, рассмотрите передачу параметров напрямую в метод модуля менеджера.

Контрольные точки

Как проверить результат

Выполнение метода
Норма

Точка останова в модуле объекта срабатывает, метод отрабатывает без исключений

Тревожный признак

Ошибка «процедура не определена» — проверьте Экспорт и имя метода

Отображение изменений
Норма

После выполнения команды данные в форме обновились

Тревожный признак

Данные не изменились — не вызван ЗначениеВРеквизитФормы

Новый объект
Норма

Код корректно работает для незаписанного объекта

Тревожный признак

Ошибка при ПолучитьОбъект() — добавьте проверку ссылки

Частые вопросы

Можно ли вызвать модуль объекта из формы без записи объекта?

Да. Способ с РеквизитФормыВЗначение не требует записи: данные формы преобразуются в объект в памяти, метод выполняется, изменения возвращаются в форму. Запись в базу при этом не происходит.

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

Чаще всего вызываемый метод в модуле объекта объявлен без ключевого слова Экспорт, либо имя указано с опечаткой. Реже причина в том, что метод находится в модуле менеджера, а вызывается у объекта (или наоборот).

Как вызвать метод объекта из формы списка?

В форме списка нет реквизита «Объект», поэтому используйте ссылку текущей строки: Элементы.Список.ТекущиеДанные.Ссылка, затем на сервере Ссылка.ПолучитьОбъект() и вызов метода. Для незаписанных объектов в форме списка их просто не бывает.

Что быстрее: РеквизитФормыВЗначение или ПолучитьОбъект()?

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

Работает ли ЭтотОбъект в управляемой форме?

Нет. В управляемой форме ЭтотОбъект ссылается на саму форму (УправляемаяФорма), а не на прикладной объект. Прямой доступ к объекту через ЭтотОбъект доступен только в обычных формах.

Как передать параметры в метод модуля объекта?

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

Итог

Что важно запомнить

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