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