Как программно установить отбор в динамическом списке на управляемой форме 1С?

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

Работа с управляемыми формами в 1С подразумевает частое использование объекта ДинамическийСписок. Это мощный инструмент для отображения данных из таблиц базы данных или результатов запросов. Однако, одна из самых распространенных задач, с которой мы сталкиваемся при разработке, — это необходимость отфильтровать этот список при открытии формы или по нажатию кнопки, основываясь на каких-то конкретных условиях. Рассмотрим подробно, как мы можем программно управлять отборами, разберем структуру настроек компоновки данных и проанализируем лучшие практики решения этой задачи.

Постановка задачи и понимание структуры

Прежде чем мы перейдем к написанию кода, давайте разберемся, с чем именно нам предстоит работать. У реквизита формы типа ДинамическийСписок есть свойство КомпоновщикНастроек. Именно через него происходит управление тем, как данные будут выводиться пользователю. Глубокое понимание программной работы с компоновщиком настроек в 1С 8.3 позволяет четко разграничить области ответственности различных коллекций — для быстрой отладки этих параметров есть консоль настройки компоновщика и отладки запросов СКД. Внутри компоновщика нас интересуют две основные коллекции:

  1. Настройки (Settings) — это текущие настройки, которые применяются к списку.
  2. ПользовательскиеНастройки (UserSettings) — это те настройки, которые пользователь видит в интерфейсе (например, в панели быстрых отборов) и может менять самостоятельно.

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

Давайте рассмотрим несколько способов решения задачи: от "классического" метода с использованием чистого API платформы до более современного подхода с использованием Библиотеки Стандартных Подсистем (БСП).

Способ 1. Использование методов БСП (Библиотеки Стандартных Подсистем)

Если ваша конфигурация построена на базе БСП (а это большинство современных типовых решений: 1С:ERP, 1С:Бухгалтерия, 1С:УТ и т.д.), то наиболее правильным и быстрым путем будет использование БСП для управления динамическими списками. Это сэкономит время и избавит от написания громоздких конструкций. Чтобы лучше ориентироваться в доступном функционале библиотеки, полезно изучить справочник по методам БСП с примерами использования.

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

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


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

// Вызываем метод БСП
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
    Список, 
    ПолеОтбора, 
    ЗначениеОтбора, 
    ВидСравнения, 
    "Период (с текущей даты)", // Представление отбора
    Истина // Использовать отбор
);

Разберем параметры, которые мы передали:

  1. Список — это реквизит нашей формы (сам динамический список).
  2. ПолеОтбора — имя поля, по которому фильтруем. Обратите внимание, что мы инициализируем объект ПолеКомпоновкиДанных.
  3. ЗначениеОтбора — то значение, с которым будем сравнивать.
  4. ВидСравнения — условие (Равно, Больше, ВСписке и т.д.).
  5. Представление — заголовок отбора, который увидит пользователь.
  6. Истина — флаг, включающий использование отбора сразу после установки.

Этот метод удобен тем, что он автоматически ищет существующий элемент отбора с таким же полем. Если находит — обновляет его, если нет — создает новый. Это избавляет нас от дублирования отборов при повторном вызове кода.

Способ 2. Нативная работа с коллекцией элементов отбора

Теперь представим ситуацию, что мы пишем "с нуля" или в конфигурации нет БСП. В этом случае нам придется работать напрямую с объектной моделью Схемы Компоновки Данных (СКД). Этот процесс более трудоемкий, но позволяет глубже понять механику платформы. Чтобы значительно сократить объем рутинного кода в таких задачах, можно использовать СКДБилдер, который упрощает программное создание СКД.

Давайте проанализируем, как создать элемент отбора вручную:


// 1. Получаем доступ к коллекции элементов отбора
ЭлементыОтбора = Список.КомпоновщикНастроек.Настройки.Отбор.Элементы;

// 2. Создаем новый элемент отбора
НовыйОтбор = ЭлементыОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

// 3. Указываем левое значение (Поле)
НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент");

// 4. Указываем вид сравнения
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;

// 5. Указываем правое значение (Значение фильтра)
НовыйОтбор.ПравоеЗначение = Объект.СсылкаНаКонтрагента;

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

// 7. Опционально: режим отображения
НовыйОтбор.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ;

Давайте подробно разберем важные нюансы этого кода.

Во-первых, свойство ЛевоеЗначение всегда ожидает объект типа ПолеКомпоновкиДанных. Передача просто строки приведет к ошибке или некорректной работе.

Во-вторых, свойство РежимОтображения. Если мы хотим, чтобы пользователь увидел этот отбор над списком и мог его отключить "галочкой", мы устанавливаем РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ. Если же это "технический" отбор, который пользователю менять нельзя, выбираем Недоступный.

Работа с фиксированными настройками

Иногда нам нужно установить жесткий отбор, который пользователь вообще не должен видеть в настройках и не должен иметь возможности отключить. Для таких целей идеально подходят фиксированные настройки и параметры запроса динамического списка. Подобные механизмы часто применяются, когда реализуется настройка видимости объектов пользователями в списке базы 1С.

Рассмотрим ситуацию: мы открываем форму выбора номенклатуры, и нам нужно показать только услуги. Пользователь может накладывать свои фильтры поверх, но товары он видеть не должен ни при каких обстоятельствах.


// Создаем новый элемент отбора
ЭлементОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

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

Отличие этого кода только в том, что мы обращаемся к Список.КомпоновщикНастроек.ФиксированныеНастройки. Все, что попадает сюда, применяется к запросу динамического списка через логическое "И" с основными настройками, но скрыто от глаз пользователя в стандартном окне настроек.

Группы отборов (И / ИЛИ)

Часто возникают задачи сложнее, чем просто "Поле = Значение". Например, нам нужно отобрать документы, где "Ответственный = Иванов" ИЛИ "Ответственный = Петров". Для реализации такой логики полезно изучить тему о сложных условиях в динамических списках. В некоторых случаях могут потребоваться дополнительные отборы по диапазону значений или списку соответствий шаблону.

Давайте посмотрим, как создать логическую структуру "ИЛИ":


// 1. Создаем группу с типом "ГруппаИли"
ГруппаИли = Список.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаИли.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;

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

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

Создавая ГруппаЭлементовОтбораКомпоновкиДанных, мы можем строить сложные логические деревья условий, комбинируя И, ИЛИ и НЕ. Например, для расширенных возможностей фильтрации по строкам удобно использовать механизм подобно в списке для отборов на соответствие шаблону.

Очистка и проверка существующих отборов

При программной работе с отборами есть риск накопления дублей. Если ваш код выполняется, например, при нажатии кнопки на форме, каждый клик может добавлять новый элемент в коллекцию Элементы. Это приведет к тому, что запрос станет перегруженным и нечитаемым.

Поэтому хорошей практикой считается предварительная очистка или поиск существующего элемента. Разберем функцию для безопасного добавления отбора:


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

КонецПроцедуры

Использование параметров запроса вместо отборов

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

Например, если в тексте запроса списка написано:


ВЫБРАТЬ
    Заказ.Ссылка,
    Заказ.Дата,
    Заказ.Клиент
ИЗ
    Документ.ЗаказКлиента КАК Заказ
ГДЕ
    Заказ.Статус = &Статус

То вместо добавления элемента отбора через компоновщик, мы должны установить значение параметра. Делается это следующим образом:


Список.Параметры.УстановитьЗначениеПараметра("Статус", Перечисления.СтатусыЗаказов.ВРаботе);

Разберем преимущества этого метода:

Однако, этот метод подходит только для условий, которые должны применяться всегда или логика которых заложена в структуре запроса жестко.

Выводы и рекомендации

Подводя итог, можно выделить несколько правил для работы с отборами динамического списка:

  1. Если конфигурация типовая — используйте ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка. Это стандарт де-факто.
  2. Если нужно скрыть отбор от пользователя — используйте ФиксированныеНастройки.
  3. Если условие является фундаментальной частью логики списка — используйте параметры произвольного запроса.
  4. Всегда проверяйте наличие дублей при добавлении отборов вручную, чтобы избежать ошибок исполнения и "раздувания" настроек.

Применяя эти подходы, вы сможете создавать гибкие и удобные интерфейсы, внедряя при необходимости дополнительные элементы управления, такие как флажок в динамическом списке в 1С 8.3, которые корректно реагируют на контекст работы пользователя и не вызывают проблем с производительностью.

← На главную