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

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

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

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

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

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

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

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

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

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

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

Обращение к реквизиту формы из модуля формы

Когда код находится в модуле формы документа, доступ к реквизитам формы прямой. В управляемой форме реквизиты формы доступны по имени напрямую или через ЭтаФорма:

&НаКлиенте

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

// Прямое обращение к реквизиту формы

ПроцентСкидки = ЭтаФорма.ПроцентСкидки;

// Обращение к реквизиту объекта (основной реквизит формы "Объект")

НомерДокумента = Объект.Номер;

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

Здесь важно различать два типа данных: Объект — это основной реквизит формы, содержащий данные документа (реквизиты, табличные части), а реквизиты формы — это дополнительные данные, созданные разработчиком в редакторе формы и существующие только пока форма открыта.

На серверных вызовах из модуля формы действуют те же правила, но с трансформацией данных. Внутри процедуры с директивой &НаСервере вы по-прежнему обращаетесь к реквизитам формы по имени, однако для работы с объектом как с прикладным типом ДокументОбъект нужна конвертация.

Передача данных из формы в объект: ДанныеФормыВЗначение

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

&НаСервере

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

// Преобразуем данные формы в объект документа

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

// Теперь доступны методы модуля объекта

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

// Возвращаем изменённые данные обратно в форму

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

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

Обратите внимание: изменения, внесённые в ДокументОбъект, не отображаются на форме автоматически. Без вызова ЗначениеВРеквизитФормы пользователь не увидит результата. Это одна из самых частых причин «непонятного» поведения — метод отработал, а форма показывает старые данные.

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

ДокументОбъект.ВыполнитьОбработку(ЭтаФорма.ВариантЗаполнения);
Как передать реквизит формы в модуль объекта
  1. 1
    Создайте в модуле объекта экспортную процедуру с параметром, например Процедура Заполнить(ПараметрЗаполнения) Экспорт
  2. 2
    В модуле формы добавьте серверную процедуру и получите объект: ДокументОбъект = РеквизитФормыВЗначение("Объект")
  3. 3
    Вызовите метод, передав реквизит формы: ДокументОбъект.Заполнить(ЭтаФорма.МойРеквизит)
  4. 4
    Верните данные на форму: ЗначениеВРеквизитФормы(ДокументОбъект, "Объект")
  5. 5
    Проверьте, что значения на форме обновились

Обращение к форме из другой формы и из внешнего кода

Иногда требуется обратиться к реквизиту формы документа из другой формы — например, из формы обработки, открытой поверх документа. Для этого форма-источник передаётся как параметр или владелец:

// В форме документа — открываем обработку и передаём себя

ОткрытьФорму("Обработка.Подбор.Форма.ФормаПодбора", , ЭтаФорма);

// В форме обработки — обращаемся к владельцу

&НаКлиенте

Процедура ПриОткрытии(Отказ)

НомерДокумента = ЭтаФорма.ВладелецФормы.Объект.Номер;

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

Такой механизм работает только на клиенте и только пока форма-владелец открыта. Если пользователь закрыл документ, обращение к ВладелецФормы вернёт ошибку. Поэтому перед использованием проверяйте владельца на Неопределено.

Из совершенно внешнего кода (общего модуля, обработки) получить форму конкретного документа штатно нельзя: формы не регистрируются в глобальном списке. Единственный легальный путь — передать ссылку на форму (как объект УправляемаяФорма) при открытии или через оповещения Оповестить / ОбработкаОповещения.

Обычные формы: особенности обращения

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

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

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

Самая распространённая ошибка — попытка использовать ЭтаФорма в модуле объекта. Платформа выдаст «Переменная не определена (ЭтаФорма)», потому что в контексте объекта этого свойства не существует. Решение — перенести код в модуль формы или передавать данные параметрами.

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

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

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

Как выбрать правильный подход

Выбор места для кода определяется тем, где живут данные и когда должен выполняться код. Если значение влияет на запись или проведение — оно обязано быть реквизитом документа. Если это временный интерфейсный параметр (например, флаг «показывать детализацию») — реквизит формы.

Маршрут решения

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

Значение нужно в ОбработкаПроведения или ПередЗаписьюПеренесите его в реквизит документа в конфигураторе — доступа к форме из модуля объекта нет
Код работает только с интерфейсом и нужен при открытой формеРазместите код в модуле формы и обращайтесь к реквизитам через ЭтаФорма или напрямую
Нужно вызвать метод объекта с данными формыИспользуйте РеквизитФормыВЗначение, вызов метода с параметром и ЗначениеВРеквизитФормы
Нужно передать данные между двумя формамиИспользуйте ВладелецФормы на клиенте или механизм Оповестить / ОбработкаОповещения

Проверить корректность решения просто: запишите и проведите документ программно (например, через консоль кода или фоновое задание). Если результат совпадает с интерактивным проведением — архитектура верная. Если поведение различается, значит где-то логика завязана на форму.

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

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

Программное проведение документа
Норма

Результат идентичен проведению из формы

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

Движения или итоги отличаются — логика зависит от формы

Обновление данных на форме после серверного вызова
Норма

Изменённые поля сразу видны пользователю

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

Данные обновляются только после переоткрытия — пропущена ЗначениеВРеквизитФормы

Запись документа через обмен данными или фоновое задание
Норма

Запись проходит без ошибок

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

Ошибки «Переменная не определена» — в модуле объекта есть обращения к форме

Часто задаваемые вопросы

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

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

Чем отличается ЭтаФорма от ЭтотОбъект в модуле формы документа?

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

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

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

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

Штатного списка открытых форм у прикладного кода нет. Правильный механизм — оповещения: форма документа при изменении вызывает Оповестить("ИзмененДокумент", Параметры, ЭтаФорма), а форма списка обрабатывает событие в ОбработкаОповещения. Обратный обмен организуется аналогично.

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

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

Работает ли обращение к реквизитам формы в мобильном клиенте и веб-клиенте?

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

Итог

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

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