Разработчики, привыкшие к удобству управляемых форм на платформе «1С:Предприятие 8», часто сталкиваются с трудностями при возвращении к обычным формам (ОФ). Одной из таких проблем является настройка отбора при выборе элементов справочника. В управляемом приложении достаточно настроить свойства Параметры выбора или Связи параметров выбора прямо в конфигураторе, и платформа сделает всё сама. Однако в обычных формах эти механизмы попросту не работают.
В этой статье мы подробно разберем, как решить задачу фильтрации номенклатуры по её реквизиту (например, по реквизиту ВидНоменклатуры) в обычном приложении. Мы рассмотрим несколько сценариев поведения пользователя: интерактивный выбор мышкой по кнопке «...», ручной ввод текста с клавиатуры (быстрый поиск) и использование выпадающих списков.
Прежде чем перейти к коду, выясним причину проблемы. Свойства метаданных Параметры выбора были добавлены разработчиками платформы специально для управляемого интерфейса. Обычный интерфейс (толстый клиент, обычные формы) их игнорирует. Единственная связь на уровне метаданных, которую понимает обычная форма, — это Связь по владельцу (например, подчиненный справочник ЕдиницыИзмерения автоматически фильтруется по владельцу Номенклатура).
Для фильтрации по любому другому реквизиту нам придется прибегнуть к написанию кода в модуле формы. Наша цель — перехватить действия пользователя и принудительно наложить нужные условия.
Рассмотрим ситуацию, когда пользователь нажимает на кнопку выбора в поле ввода номенклатуры или в ячейке табличной части. Нам необходимо открыть форму выбора справочника Номенклатура, в которой уже будет установлен жесткий отбор по определенному виду номенклатуры (например, «Металлоконструкции»), и заблокировать для пользователя возможность этот отбор снять.
Для реализации этого сценария мы задействуем событие поля ввода НачалоВыбора. Выполним следующие шаги:
НачалоВыбора и сгенерируем обработчик в модуле формы.Проанализируем пример кода для обработчика:
Процедура ТЧНоменклатураНачалоВыбора(Элемент, СтандартнаяОбработка)
// 1. Отключаем стандартное открытие формы выбора платформой
СтандартнаяОбработка = Ложь;
// 2. Получаем форму выбора номенклатуры.
// Вторым и третьим параметрами передаем Элемент (наше поле ввода),
// чтобы форма знала, куда вернуть результат выбора.
ФормаВыбора = Справочники.Номенклатура.ПолучитьФормуВыбора("ФормаВыбора", Элемент, Элемент);
// 3. Накладываем программный отбор по ВидуНоменклатуры
ОтборВид = ФормаВыбора.Отбор.ВидНоменклатуры;
ОтборВид.ВидСравнения = ВидСравнения.Равно;
// Получаем нужное значение вида номенклатуры (например, по наименованию или ссылке)
НужныйВид = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Металлоконструкции");
Если ЗначениеЗаполнено(НужныйВид) Тогда
ОтборВид.Значение = НужныйВид;
ОтборВид.Использование = Истина;
КонецЕсли;
// 4. Блокируем для пользователя возможность изменения или отключения этого отбора в форме выбора
Попытка
ФормаВыбора.ЭлементыФормы.СправочникСписок.НастройкаОтбора.ВидНоменклатуры.Доступность = Ложь;
Исключение
// Исключение обработает ситуацию, если имя элемента списка в форме выбора отличается от стандартного
КонецПопытки;
// 5. Открываем настроенную форму выбора
ФормаВыбора.Открыть();
КонецПроцедуры
При таком подходе при нажатии на «...» откроется форма, где будут показаны только металлоконструкции. Пользователь не сможет отключить этот фильтр в панели отборов, что гарантирует корректность ввода данных.
Предыдущее решение отлично работает, если пользователь пользуется мышкой. Но что произойдет, если он начнет вводить наименование товара прямо с клавиатуры? Стандартный автоподбор платформы проигнорирует наш программный отбор в НачалоВыбора и предложит варианты из всего справочника Номенклатура.
Чтобы избежать этой уязвимости, нам необходимо обработать событие ОкончаниеВводаТекста. Этот обработчик срабатывает, когда пользователь заканчивает набирать текст и нажимает клавишу Enter или пытается перейти на другое поле.
Разберем по шагам алгоритм работы этого события:
СтандартнаяОбработка = Ложь).Номенклатура, которые содержат введенный пользователем текст И одновременно соответствуют нашему фильтру по реквизиту ВидНоменклатуры.Рассмотрим пример программной реализации этой логики:
Процедура ТЧНоменклатураОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
// Отменяем стандартный алгоритм подбора платформы
СтандартнаяОбработка = Ложь;
// Игнорируем пустой ввод
Если ПустаяСтрока(Текст) Тогда
Возврат;
КонецЕсли;
// Выполняем поиск по базе данных с учетом фильтра
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ
| И Номенклатура.ВидНоменклатуры.Наименование = &ВидНоменклатуры
| И Номенклатура.Наименование ПОДОБНО &ТекстПоиска";
Запрос.УстановитьПараметр("ВидНоменклатуры", "Металлоконструкции");
// Используем конструкцию ПОДОБНО для поиска по подстроке
Запрос.УстановитьПараметр("ТекстПоиска", "%" + Текст + "%");
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
КоличествоРезультатов = РезультатЗапроса.Количество();
Если КоличествоРезультатов = 0 Тогда
// Ничего не найдено — сообщаем об этом пользователю
Предупреждение("В справочнике не найдены металлоконструкции с текстом: """ + Текст + """!");
Значение = Неопределено;
ИначеЕсли КоличествоРезультатов = 1 Тогда
// Найдено точное совпадение — сразу подставляем значение
Значение = РезультатЗапроса[0].Ссылка;
Иначе
// Найдено несколько вариантов — выводим список для быстрого выбора
СписокВыбора = Новый СписокЗначений;
СписокВыбора.ЗагрузитьЗначения(РезультатЗапроса.ВыгрузитьКолонку("Ссылка"));
ВыбранныйЭлемент = ВыбратьИзСписка(СписокВыбора, Элемент);
Если ВыбранныйЭлемент <> Неопределено Тогда
Значение = ВыбранныйЭлемент.Значение;
Иначе
Значение = Неопределено;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Этот метод гарантирует, что пользователь не сможет обойти установленные ограничения ни при использовании мыши, ни при активной работе на клавиатуре.
В некоторых бизнес-процессах список разрешенных элементов относительно невелик (например, в рамках выбранного вида номенклатуры содержится всего от 10 до 100 наименований). В этом случае отличным и очень удобным решением будет превратить стандартное поле ввода в полноценный выпадающий список (Combo Box).
Для настройки такого поведения выполним следующие действия в конфигураторе:
РежимВыбораИзСписка в значение Истина.КнопкаСпискаВыбора зададим значение Истина.Теперь нам нужно программно заполнить этот список выбора актуальными данными. Делать это лучше всего при открытии формы или при активации строки табличной части (если отбор зависит от контекста строки):
Процедура ЗаполнитьСписокВыбораНоменклатуры(ЭлементФормы)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ
| И Номенклатура.ВидНоменклатуры.Наименование = &ВидНоменклатуры";
Запрос.УстановитьПараметр("ВидНоменклатуры", "Металлоконструкции");
ТаблицаДанных = Запрос.Выполнить().Выгрузить();
// Очищаем старые значения списка выбора элемента формы
ЭлементФормы.СписокВыбора.Очистить();
// Загружаем новые отфильтрованные данные
ЭлементФормы.СписокВыбора.ЗагрузитьЗначения(ТаблицаДанных.ВыгрузитьКолонку("Ссылка"));
КонецПроцедуры
Преимущество этого метода: пользователю не нужно открывать тяжелые модальные окна справочника. Он просто нажимает на стрелочку вниз и выбирает значение из ограниченного, заранее отфильтрованного списка.
В конце темы на форуме прозвучало предложение использовать событие модуля менеджера справочника ОбработкаПолученияДанныхВыбора(). Разберем этот момент подробнее, чтобы вы не тратили на него время при разработке под обычные формы.
Данный обработчик действительно является мощным инструментом для кастомизации автоподбора, но он был реализован разработчиками платформы исключительно для управляемого приложения. В режиме обычного приложения это событие в модуле менеджера вызываться не будет, поэтому все манипуляции с отборами в ОФ по-прежнему необходимо проводить на уровне событий элементов самой формы.
Мы рассмотрели три надежных способа программного ограничения выбора номенклатуры по её реквизитам в обычных формах 1С 8.3. Использование комбинации событий НачалоВыбора и ОкончаниеВводаТекста дает стопроцентную защиту от ввода некорректных данных, а перевод поля ввода в режим выбора из списка значительно ускоряет работу пользователей при небольших объемах номенклатурных позиций.