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