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