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