Рассмотрим распространенную задачу при разработке в обычных формах (на примере конфигурации «Управление торговлей», редакция 10.3): в табличной части или реквизите формы содержится поле составного типа данных. Потребителю необходимо при выборе объекта открыть форму списка не со всеми записями, а с динамически отфильтрованным набором данных в зависимости от условий (например, от выбранной в документе организации или типа сделки).
Выясним, в каком именно событии следует перехватывать открытие формы выбора и как правильно настроить отбор. Главным обработчиком для этой задачи является событие элемента формы НачалоВыбора (BeforeChoice). Именно здесь сбрасывается параметр СтандартнаяОбработка и программно вызывается подготовленная форма с нужными параметрами отбора.
Разберем по шагам, как настроить обработку события НачалоВыбора для элемента управления ячейки табличной части или реквизита формы:
СтандартнаяОбработка = Ложь.ПолучитьФормуВыбора() для нужного объекта метаданных, передавая текущий элемент управления в качестве владельца формы.Отбор полученной формы.Открыть().Проанализируем пример кода 1С, который демонстрирует данную логику:
Процедура ТабличнаяЧастьСделкаНачалоВыбора(Элемент, СтандартнаяОбработка)
// Отключаем штатное открытие формы платформой
СтандартнаяОбработка = Ложь;
// Формируем запрос для получения допустимых ссылок
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Сделки.Ссылка КАК Ссылка
|ИЗ
| Справочник.Сделки КАК Сделки
|ГДЕ
| Сделки.Организация = &ТекущаяОрганизация";
Запрос.УстановитьПараметр("ТекущаяОрганизация", Элемент.ТекущиеДанные.Организация);
ОтфильтрованныйСписок = Новый СписокЗначений;
ОтфильтрованныйСписок.ЗагрузитьЗначения(Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка"));
// Получаем форму выбора и передаем элемент как владелец
ФормаВыбора = Справочники.Сделки.ПолучитьФормуВыбора(, Элемент);
// Настраиваем элемент отбора по ссылке
ЭлементОтбораСсылка = ФормаВыбора.Отбор.Ссылка;
Если ЭлементОтбораСсылка <> Неопределено Тогда
ЭлементОтбораСсылка.ВидСравнения = ВидСравнения.ВСписке;
ЭлементОтбораСсылка.Значение = ОтфильтрованныйСписок;
ЭлементОтбораСсылка.Использование = Истина;
КонецЕсли;
// При необходимости отключаем возможность изменения пользовательского отбора
ФормаВыбора.ЭлементыФормы.СправочникСписок.НастройкаОтбора.Ссылка.Доступность = Ложь;
ФормаВыбора.ЭлементыФормы.СправочникСписок.ИерархическийПросмотр = Ложь;
// Открываем настраиваемую форму
ФормаВыбора.Открыть();
КонецПроцедуры
Посмотрим на особенности, возникающие, когда поле имеет составной тип данных (например, ссылки на справочники «Сделки», «ЗаказыПокупателей», «ДоговорыКонтрагентов»):
Неопределено), отключение СтандартнаяОбработка = Ложь предотвратит вызов диалогового окна выбора типа. Для решения этой проблемы сначала проверяется заполненность реквизита или используется функция ВвестиТип(ВыбранныйТип, ОписаниеДоступныхТипов).ПолучитьФорму(Метаданные.НайтиПоТипу(ТипЗнч(Значение)).ПолноеИмя() + ".ФормаВыбора", Элемент).Важно учесть, что пользователь может выбирать значение не только по кнопке выбора (F4), но и набирая текст на клавиатуре непосредственно в поле ввода. Событие НачалоВыбора срабатывает только при открытии диалогового окна формы выбора.
Разберем дополнительные механизмы защиты и настройки:
ОкончаниеВводаТекста: Если оставить стандартную обработку ввода по строке, платформа выполнит подбор без учета настроенного отбора. В обработчике ОкончаниеВводаТекста (или АвтоПодборТекста) также сбрасывается СтандартнаяОбработка = Ложь, выполняется поиск подходящего значения по алгоритму с учетом ограничений и результат передается в параметр Значение.СвязьПоТипу (или СвязиПараметровВыбора), позволяющее ограничить выбор определенных типов данных на основе других полей формы без написания лишнего кода.Проанализируем важный нюанс работы с отборами вида ВидСравнения.ВСписке. Если запрос возвращает большое количество записей (сотни или тысячи ссылок), передача такого списка в ФормаВыбора.Отбор.Ссылка приводит к формированию тяжелого SQL-запроса с условием IN (...). Это снижает скорость открытия формы.
Рекомендация по оптимизации: По возможности накладывайте отбор не по списку ссылок, а по имеющимся реквизитам открываемого объекта (например, ФормаВыбора.Отбор.Организация.Значение = ТекущаяОрганизация). Это позволяет СУБД строить более эффективный план выполнения запроса.