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