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