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

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

1С: как передать параметр при закрытии формы

Как передать параметр при закрытии формы в 1С 8.3: метод Закрыть(), ОповеститьОВыборе, описание оповещения о закрытии. Примеры кода на управляемых формах.

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

Выбор механизма зависит от того, как открыта форма (модально или нет), кто является владельцем формы и нужно ли обрабатывать результат асинхронно. Ошибка в выборе приводит к типичным проблемам: значение теряется, форма-владелец не узнаёт о результате, либо код падает с ошибкой «недопустимое значение параметра».

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

Как работает возврат значения при закрытии формы

Когда форма закрывается, платформа может передать в вызвавший код одно значение — «результат закрытия». Это значение произвольного типа: строка, число, ссылка, структура, массив. Оно попадает в обработчик, назначенный через ОписаниеОповещения, либо возвращается методом модального открытия.

Важно понимать: просто вызвать Закрыть() без параметра недостаточно — в обработчик оповещения придёт Неопределено. Чтобы результат дошёл до получателя, его нужно явно указать: Закрыть(РезультатВыбора). При этом у формы должен быть корректно настроен владелец или описание оповещения, иначе значение просто некуда доставить.

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

Способ 1: Закрыть() с параметром и описание оповещения

Это основной рекомендуемый способ для управляемых форм в немодальном режиме. При открытии формы вы передаёте описание оповещения, а закрываемая форма возвращает результат через параметр метода Закрыть().

Код в форме-владельце, которая открывает дочернюю форму:

&НаКлиенте

Процедура ПодобратьТовар(Команда)

Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияФормыПодбора", ЭтотОбъект);

ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаПодбора",

, ЭтотОбъект, , , , Оповещение);

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

&НаКлиенте

Процедура ПослеЗакрытияФормыПодбора(Результат, ДополнительныеПараметры) Экспорт

Если Результат = Неопределено Тогда

Возврат; // пользователь закрыл форму крестиком или по Esc

КонецЕсли;

// Результат — то, что передано в Закрыть()

Для Каждого Строка Из Результат.ПодобранныеТовары Цикл

НоваяСтрока = Объект.Товары.Добавить();

НоваяСтрока.Номенклатура = Строка.Номенклатура;

НоваяСтрока.Количество = Строка.Количество;

КонецЦикла;

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

Код в закрываемой форме подбора:

&НаКлиенте

Процедура ПеренестиВДокумент(Команда)

Результат = Новый Структура;

Результат.Вставить("ПодобранныеТовары", СобратьПодобранныеТовары());

Закрыть(Результат);

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

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

Порядок действий для возврата значения
  1. 1
    В форме-владельце создайте ОписаниеОповещения с именем экспортной процедуры-обработчика
  2. 2
    Передайте оповещение седьмым параметром в ОткрытьФорму()
  3. 3
    В закрываемой форме сформируйте результат (структуру, ссылку, массив)
  4. 4
    Вызовите Закрыть(Результат) в команде подтверждения
  5. 5
    В обработчике проверьте Результат на Неопределено перед использованием

Способ 2: модальное открытие формы

Если логика требует остановить выполнение кода до закрытия формы, используется модальный режим. Метод ОткрытьФормуМодально() сам возвращает результат закрытия — тот самый параметр, переданный в Закрыть():

&НаКлиенте

Процедура ВвестиКомментарий(Команда)

Результат = ОткрытьФормуМодально(

"ОбщаяФорма.ФормаВводаКомментария");

Если Результат <> Неопределено Тогда

Объект.Комментарий = Результат;

КонецЕсли;

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

Модальный режим имеет серьёзное ограничение: в тонком и веб-клиенте он по умолчанию запрещён, и конфигурация должна иметь соответствующий режим использования модальности. В современных конфигурациях (БСП и типовые на её основе) модальные вызовы считаются устаревшей практикой — вместо них используют описания оповещений. Перед использованием проверьте свойство конфигурации «Режим использования модальности».

Для блокирующего, но немодального поведения есть альтернатива — открыть форму с параметром РежимОткрытияОкнаФормы.БлокироватьОкноВладельца и обычным описанием оповещения. Пользователь не сможет переключиться на родительское окно, а код останется асинхронным и совместимым с веб-клиентом.

Сравнение способов возврата значения

Закрыть() + ОписаниеОповещения

Рекомендуемый способ для управляемых форм. Асинхронный, работает в веб-клиенте, требует экспортного обработчика.

ОткрытьФормуМодально()

Простой линейный код, но требует разрешённой модальности и не работает в веб-клиенте без настроек. Устаревшая практика.

ОповеститьОВыборе()

Стандартный механизм выбора: срабатывает обработчик ОбработкаВыбора формы-владельца. Подходит для форм выбора справочников и документов.

Оповестить()

Широковещательное событие по имени. Подходит, когда получателей несколько или владелец неизвестен, но требует аккуратности с уникальностью имён событий.

Способ 3: ОповеститьОВыборе для форм выбора

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

В форме-владельце значение приходит в предопределённый обработчик ОбработкаВыбора:

&НаКлиенте

Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)

Если ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.Номенклатура") Тогда

Объект.ОсновнойТовар = ВыбранноеЗначение;

КонецЕсли;

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

В форме выбора достаточно вызвать:

ОповеститьОВыборе(ТекущаяСтрокаНоменклатуры);

Если форма открыта в режиме выбора (параметр РежимВыбора = Истина), платформа сама закроет её после оповещения. Если форма открыта обычным способом, закрывать её нужно явно. Важное отличие от описания оповещения: ОбработкаВыбора вызывается только у непосредственного владельца формы, указанного при открытии.

Способ 4: Оповестить и глобальные события

Когда получатель результата не является владельцем формы или получателей несколько, используют метод Оповестить(ИмяСобытия, Параметр, Источник). Любая открытая форма, в которой есть обработчик ОбработкаОповещения, получит это событие:

// В закрываемой форме

Оповестить("ИзмененыНастройкиОбмена", НовыеНастройки, ЭтотОбъект);

Закрыть();

// В форме-получателе

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ИзмененыНастройкиОбмена" Тогда

ПрименитьНастройки(Параметр);

КонецЕсли;

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

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

Передача нескольких значений и сложных данных

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

Результат = Новый Структура;

Результат.Вставить("ВыбранныйКонтрагент", Контрагент);

Результат.Вставить("Договор", Договор);

Результат.Вставить("СогласованнаяСумма", Сумма);

Результат.Вставить("БылиИзменения", Истина);

Закрыть(Результат);

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

Если нужно передать данные, которые не должны покидать сервер (например, большие выборки), лучше вернуть через Закрыть() только ключ (например, адрес во временном хранилище), а сами данные получатель заберёт из хранилища вызовом ПолучитьИзВременногоХранилища().

bsl
&НаКлиенте
Процедура ОК(Команда)
    Результат = Новый Структура("АдресДанных", АдресВоВременномХранилище);
    Закрыть(Результат);
КонецПроцедуры

Проверка результата и типичные ошибки

После внедрения механизма проверьте три контрольные точки: значение доходит до обработчика, имеет ожидаемый тип, и отказ от выбора (закрытие крестиком) обрабатывается корректно. Самая частая ошибка — отсутствие проверки на Неопределено: пользователь закрыл форму без выбора, а код пытается обратиться к полям результата и падает.

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

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

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

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

Обработчик вызывается
Норма

Точка останова в обработчике срабатывает при закрытии формы

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

Обработчик молчит — проверьте Экспорт и параметры ОткрытьФорму()

Содержимое результата
Норма

Результат имеет ожидаемый тип и заполненные поля

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

Неопределено или пустая структура — проверьте параметр Закрыть()

Отказ от выбора
Норма

При закрытии крестиком код владельца ничего не меняет и не падает

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

Ошибка обращения к полям Неопределено

FAQ

Что приходит в обработчик, если форму закрыли крестиком?

При закрытии формы стандартными средствами (крестик, Esc, системное меню) метод Закрыть() с параметром не вызывается, поэтому в обработчик описания оповещения приходит Неопределено. Всегда начинайте обработчик с проверки Результат = Неопределено и выхода из процедуры.

Можно ли передать параметр при закрытии формы, открытой не из кода, а интерактивно?

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

Почему обработчик оповещения не вызывается, хотя Закрыть(Результат) выполняется?

Наиболее вероятные причины: процедура-обработчик объявлена без Экспорт; описание оповещения передано не седьмым параметром ОткрытьФорму(); форма открыта через ПолучитьФорму() + Открыть(), где оповещение не поддерживается. Проверьте сигнатуру вызова ОткрытьФорму() и наличие ключевого слова Экспорт у обработчика.

Как передать таблицу значений при закрытии формы?

Напрямую таблицу значений на клиенте создать нельзя. На клиенте упакуйте данные в массив структур и передайте его в Закрыть(). Альтернатива — поместить таблицу во временное хранилище на сервере и вернуть через Закрыть() только адрес хранилища, а получатель извлечёт данные вызовом ПолучитьИзВременногоХранилища().

Чем ОповеститьОВыборе отличается от Закрыть(Результат)?

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

Работает ли Закрыть(Результат) в обычных формах?

Да, в обычных формах метод Закрыть(Параметр) также существует, а результат возвращается через ОткрытьМодально() или обработчик ОбработкаВыбора при ОповеститьОВыборе(). Однако механизм ОписаниеОповещения — особенность управляемых форм; в обычных формах его нет.

Итог

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

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