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