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