Как программно установить отбор по списку товаров в периодическом независимом регистре сведений

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие 8 часто возникает задача фильтрации данных в периодических регистрах сведений. Особый интерес представляет случай, когда необходимо установить отбор не по одному конкретному значению, а по целому списку (массиву) элементов, например, по списку номенклатуры. В этой статье мы подробно разберем, как реализовать такой функционал в различных типах форм, рассмотрим ограничения объектов платформы и найдем наиболее эффективные способы решения задачи.

Особенности работы с отборами в обычных формах

Если вы работаете с обычными формами, задача решается через обращение к свойству Отбор табличного поля, которое отображает список записей регистра. Важно понимать, что объект Отбор для регистра сведений в экранной форме позволяет использовать различные виды сравнения, в том числе и работу со списками.

Разберем по шагам, как программно установить такой фильтр. Предположим, у нас есть массив или список значений СписокТоваров, по которым нужно отфильтровать записи. Проанализируем программный код:


// Получаем доступ к отбору списка регистра сведений
ЭлементОтбора = РегистрСведенийСписок.Отбор.Номенклатура;

// Включаем использование отбора
ЭлементОтбора.Использование = Истина;

// Устанавливаем вид сравнения "ВСписке"
ЭлементОтбора.ВидСравнения = ВидСравнения.ВСписке;

// Передаем подготовленный список значений или массив
ЭлементОтбора.Значение = СписокТоваров;

В данном примере РегистрСведенийСписок — это основное действие (тип значения РегистрСведенийСписок.<ИмяРегистра>), связанное с табличным полем на форме. Установив ВидСравнения.ВСписке, мы позволяем платформе автоматически сформировать запрос к базе данных, который выберет только нужные позиции.

Реализация в управляемых формах через динамический список

В современных конфигурациях на управляемых формах работа с данными регистров строится на использовании объекта ДинамическийСписок. Здесь механизм установки отборов несколько отличается, так как он базируется на системе компоновки данных (СКД).

Рассмотрим алгоритм программной установки отбора в управляемом приложении:

  1. Находим нужный элемент отбора в коллекции КомпоновкаДанных.Отбор.Элементы.
  2. Если элемента нет, создаем новый.
  3. Устанавливаем левое значение (поле компоновки), вид сравнения и правое значение (наш список).

Посмотрим на пример реализации:


// Очистим старые отборы по полю Номенклатура, если они были
ПолеОтбора = Новый ПолеКомпоновкиДанных("Номенклатура");
Для Каждого Элемент Из Список.Отбор.Элементы Цикл
    Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") 
        И Элемент.ЛевоеЗначение = ПолеОтбора Тогда
        Список.Отбор.Элементы.Удалить(Элемент);
    КонецЕсли;
КонецЦикла;

// Добавляем новый элемент отбора
НовыйОтбор = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйОтбор.ЛевоеЗначение  = ПолеОтбора;
НовыйОтбор.ВидСравнения   = ВидСравненияКомпоновкиДанных.ВСписке;
НовыйОтбор.ПравоеЗначение = МассивНоменклатуры; // Ваш массив товаров
НовыйОтбор.Использование  = Истина;
НовыйОтбор.РежимОтображения = РежимОтображенияЭлементаОтбораКомпоновкиДанных.Недоступный;

Обратите внимание на свойство РежимОтображения. Если мы установим значение Недоступный, пользователь не сможет случайно удалить или изменить этот программный фильтр в настройках списка, что гарантирует целостность отображаемых данных.

Ограничения объекта РегистрСведенийНаборЗаписей

Выясним причину, по которой иногда возникают сложности при программной обработке данных без использования экранных форм. Если ваша задача — не просто показать данные пользователю, а прочитать их или изменить в коде (например, в фоновом задании), вы, скорее всего, обратитесь к объекту РегистрСведенийНаборЗаписей.

Важный технический нюанс: объект Отбор у набора записей крайне ограничен. Он поддерживает только вид сравнения Равно. Вы не можете написать НаборЗаписей.Отбор.Номенклатура.ВидСравнения = ВидСравнения.ВСписке — это вызовет ошибку платформы. Набор записей предназначен для работы с конкретными комбинациями измерений.

В этом случае у нас есть два пути:

  1. Циклический обход: выполнять чтение набора записей в цикле для каждого товара из списка. Это допустимо, если товаров в списке мало (например, 2-3 позиции).
  2. Использование запроса: это наиболее правильный и производительный метод для работы с большими списками.

Эффективное получение данных через запрос (СрезПоследних)

Поскольку наш регистр периодический, нам чаще всего нужны не все записи за всю историю, а актуальные значения на определенную дату (например, текущую цену). Для этого мы будем использовать виртуальную таблицу СрезПоследних. Проанализируем ситуацию: использование конструкции ГДЕ после получения данных работает медленно. Правильнее передавать список товаров сразу в параметры виртуальной таблицы.

Разберем пример эффективного запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
    |	ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
    |ИЗ
    |	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, Номенклатура В (&СписокТоваров)) КАК ЦеныНоменклатурыСрезПоследних";

Запрос.УстановитьПараметр("Период", ТекущаяДата());
Запрос.УстановитьПараметр("СписокТоваров", МассивТоваров);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Обработка полученных данных
    Сообщить("Товар: " + Выборка.Номенклатура + " Цена: " + Выборка.Цена);
КонецЦикла;

Этот метод работает на порядок быстрее циклического обращения к наборам записей, так как СУБД выполняет фильтрацию на своей стороне, используя индексы.

Рекомендации по индексации

Для того чтобы любые отборы (и в формах, и в запросах) работали мгновенно, необходимо проверить настройки регистра в Конфигураторе. Убедитесь, что для измерения Номенклатура установлено свойство Индексировать. В периодических регистрах платформа автоматически создает составные индексы (Измерения + Период), но дополнительная индексация ведущих измерений помогает оптимизировать сложные выборки по спискам.

Подведем итог: выбор метода установки отбора зависит от вашей цели. Для визуального отображения в обычных формах используйте ВидСравнения.ВСписке, в управляемых — ЭлементОтбораКомпоновкиДанных. Для программной обработки данных всегда отдавайте предпочтение запросам к виртуальным таблицам с передачей списка в параметры условия.

← На главную