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

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

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

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

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

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

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

Как устроено взаимодействие формы и объекта

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

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

Первое обязательное условие для любого способа: процедура в модуле объекта должна быть объявлена с ключевым словом Экспорт. Без него метод остаётся приватным, и попытка вызова завершится ошибкой «Метод объекта не обнаружен».

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

Процедура ЗаполнитьПоУмолчанию() Экспорт

// логика заполнения

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

Вызов в обычной форме через ЭтотОбъект

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

// Модуль обычной формы

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

ЭтотОбъект.ЗаполнитьПоУмолчанию();

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

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

Если процедура объекта должна вернуть результат, используйте функцию с Экспорт и обрабатывайте возвращаемое значение в форме обычным присваиванием.

Вызов в управляемой форме через ДанныеФормыВЗначение

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

Преобразование выполняется двумя методами формы: РеквизитФормыВЗначение("Объект") создаёт объект из данных формы, а ЗначениеВРеквизитФормы(ОбъектДанных, "Объект") переносит изменения обратно. Оба метода доступны только в серверном контексте.

// Модуль управляемой формы

&НаСервере

Процедура ЗаполнитьНаСервере()

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

ОбъектДанных.ЗаполнитьПоУмолчанию();

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

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

&НаКлиенте

Процедура Заполнить(Команда)

ЗаполнитьНаСервере();

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

Порядок действий для управляемой формы
  1. 1
    В модуле объекта объявите процедуру с ключевым словом Экспорт
  2. 2
    В модуле формы создайте серверную процедуру с директивой &НаСервере
  3. 3
    Получите объект: РеквизитФормыВЗначение("Объект")
  4. 4
    Вызовите экспортную процедуру полученного объекта
  5. 5
    Верните данные: ЗначениеВРеквизитФормы(ОбъектДанных, "Объект")
  6. 6
    Из клиентского обработчика команды вызовите серверную процедуру
  7. 7
    Проверьте, что данные в форме обновились и объект помечен как изменённый

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

Почему вызов возможен только на сервере

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

Стандартный шаблон — пара процедур: клиентская обрабатывает команду или событие, серверная выполняет работу с объектом. Если из клиентского контекста нужно передать параметры, передайте их аргументами серверной процедуры.

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

Альтернатива: вынос логики в общий модуль

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

Где размещать процедуру

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

Логика неотделима от объекта: проверки заполнения, обработка проведения, работа с движениями. Требует преобразования данных формы в объект.

Общий серверный модуль

Логика используется из нескольких мест или работает по ссылке. Вызывается из формы напрямую, без РеквизитФормыВЗначение.

Модуль менеджера объекта

Операции над коллекциями объектов или созданием новых (печатные формы, заполнение по шаблону). Также доступен напрямую с сервера.

Модуль объекта остаётся правильным местом для методов, которые обязаны работать с незаписанными данными текущего экземпляра: например, пересчёт табличной части до записи. Если метод может работать со ссылкой на уже записанный объект — рассмотрите общий модуль или модуль менеджера.

Типичные ошибки и их диагностика

Большинство проблем при таком вызове сводится к нескольким повторяющимся причинам. Их легко распознать по тексту ошибки и контексту, в котором она возникает.

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

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

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

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

Компиляция модуля формы
Норма

Конфигуратор не сообщает об ошибках при проверке модуля

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

Сообщение «Процедура или функция с указанным именем не определена»

Вызов в отладчике
Норма

Точка останова в модуле объекта срабатывает, объект содержит актуальные данные формы

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

Отладчик в модуль объекта не попадает — вызов не дошёл

Состояние формы после вызова
Норма

Изменённые поля видны в форме, заголовок показывает признак модифицированности

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

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

Запись объекта
Норма

После вызова и записи изменения сохранены в базе

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

После записи данные потеряны — объект изменялся вне связи с формой

Практические рекомендации по организации кода

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

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

При отладке помните, что серверный код отлаживается на сервере: в конфигураторе должна быть включена отладка на сервере 1С (или отладка по протоколу HTTP для клиент-серверного режима). Иначе точки останова в модуле объекта просто не сработают, и создастся ложное впечатление, что метод не вызывается.

Итог

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

Обычная форма — вызов через ЭтотОбъект.ИмяПроцедуры(). Управляемая форма — только на сервере: РеквизитФормыВЗначение, вызов экспортной процедуры, ЗначениеВРеквизитФормы. Ключевое слово Экспорт обязательно. Частую или переиспользуемую логику выносите в общие модули.

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

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

Нет. Модуль объекта исполняется только на сервере, поэтому без серверной процедуры-посредника обойтись нельзя. Клиентская процедура обязана вызвать серверную, а та уже работает с объектом.

Что делать, если ошибка «Метод объекта не обнаружен», хотя процедура есть?

Проверьте три вещи: наличие ключевого слова Экспорт после заголовка процедуры, отсутствие опечатки в имени и то, что вы вызываете метод у правильного экземпляра — результата РеквизитФормыВЗначение, а не у данных формы напрямую.

Как вызвать процедуру объекта для записанного документа, не изменяя форму?

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

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

Нет, в управляемой форме такого свойства у формы нет. Попытка обращения приведёт к ошибке. Используйте РеквизитФормыВЗначение с именем основного реквизита формы.

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

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

Почему после вызова процедуры форма не стала модифицированной?

Признак модифицированности обычно появляется после ЗначениеВРеквизитФормы, если данные действительно изменились. Если признака нет, проверьте, что процедура объекта реально меняет реквизиты, и что обратное преобразование выполняется после вызова, а не до него.