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