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