Как программно установить отбор в динамическом списке 1С, чтобы пользователь мог его отключить?

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

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

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

Выясняем причину: почему блокируется программный отбор?

Рассмотрим типичный код, который часто используют разработчики для установки отбора в динамическом списке (именно с него начинается обсуждение на форуме):


ИскЭлементОтбора = Неопределено;
Для Каждого ЭлементОтбора ИЗ ЭтаФорма.Список.Отбор.Элементы Цикл
    Если ЭлементОтбора.Представление = "_Контрагент" Тогда
        ИскЭлементОтбора = ЭлементОтбора;
        Прервать;
    КонецЕсли;
КонецЦикла;

Если ИскЭлементОтбора = Неопределено Тогда
    ИскЭлементОтбора = ЭтаФорма.Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ИскЭлементОтбора.Представление = "_Контрагент";
КонецЕсли;

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

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

Дело в том, что в управляемом интерфейсе 1С механизмы компоновки данных жестко разделяют настройки на две категории:

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

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

Типичная ошибка: прямое добавление в пользовательские настройки

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


ЭлементыДляОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных")); // Вызовет ошибку!

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

Рассмотрим по шагам правильные и надежные способы реализации этой задачи.

Решение 1: Канонический способ связывания настроек компоновщика

Чтобы программно добавить отбор так, чтобы пользователь видел его, мог изменять или полностью отключать, необходимо выполнить строго определенную последовательность действий:

  1. Создать или найти элемент отбора в основных настройках компоновщика (Список.КомпоновщикНастроек.Настройки.Отбор.Элементы).
  2. Присвоить свойству ИдентификаторПользовательскойНастройки этого элемента уникальный строковый идентификатор. Именно это действие заставляет платформу автоматически сгенерировать зеркальный элемент в коллекции пользовательских настроек.
  3. Установить режим отображения в значение БыстрыйДоступ или Ообычный.
  4. Найти автоматически созданный элемент в коллекции Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы по нашему идентификатору и установить его значение и флаг использования там.

Рассмотрим пример реализации этого алгоритма в коде:


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

Компоновщик = ЭтаФорма.Список.КомпоновщикНастроек;

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

// Если не нашли, создаем новый элемент в основных настройках
Если ЭлементНастройки = Неопределено Тогда
    ЭлементНастройки = Компоновщик.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементНастройки.ЛевоеЗначение = ПолеОтбора;
КонецЕсли;

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

// 2. Связываем элемент с пользовательскими настройками
// Если идентификатор еще не назначен, генерируем его
Если ПустаяСтрока(ЭлементНастройки.ИдентификаторПользовательскойНастройки) Тогда
    ЭлементНастройки.ИдентификаторПользовательскойНастройки = Строка(Новый УникальныйИдентификатор);
КонецЕсли;

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

// 4. Находим связанный элемент в пользовательских настройках и меняем его
ИдентификаторСвязи = ЭлементНастройки.ИдентификаторПользовательскойНастройки;
ЭлементПользователя = Компоновщик.ПользовательскиеНастройки.Элементы.Найти(ИдентификаторСвязи);

Если ЭлементПользователя <> Неопределено Тогда
    ЭлементПользователя.ПравоеЗначение = ЗначениеОтбора;
    ЭлементПользователя.Использование = ЗначениеЗаполнено(ЗначениеОтбора);
КонецЕсли;

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

Решение 2: Вывод отборов на форму без написания кастомных кнопок

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

Проанализируем, как это настроить в конфигураторе:

  1. Откройте нужную управляемую форму в конфигураторе.
  2. В дереве элементов формы создайте новую группу. Для свойства Вид этой группы выберите значение Группа пользовательских настроек или обычная Группа без отображения.
  3. Выделите в дереве элементов таблицу, которая отображает ваш динамический список (например, таблица Список).
  4. В свойствах таблицы найдите параметр ГруппаПользовательскихНастроек.
  5. Укажите в этом параметре созданную ранее группу.

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

Решение 3: Использование готовых механизмов БСП (Библиотека стандартных подсистем)

В современных конфигурациях 1С (таких как УТ, ERP, КА, ЗУП, УНФ, Бухгалтерия предприятия и др.) ручное написание громоздкого кода для работы с компоновщиком настроек считается избыточным. Разработчики БСП уже позаботились об этой рутине и создали готовые программные интерфейсы общего назначения.

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


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

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

Если в какой-то момент вам потребуется программно полностью удалить этот отбор из настроек компоновщика, вы можете воспользоваться другой сопутствующей функцией БСП:


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

Важное предупреждение: когда нельзя использовать фиксированные настройки

Иногда в попытках решить проблему неотключаемых отборов разработчики задействуют коллекцию Список.КомпоновщикНастроек.ФиксированныеНастройки. Посмотрим на эту ситуацию подробнее.

Запомните важное правило: настройки, добавленные в коллекцию ФиксированныеНастройки, пользователь не может отключить или изменить вообще ни при каких условиях. Более того, эти настройки полностью скрыты от стандартного интерфейса изменения формы. Если пользователь попытается установить свой собственный отбор по тому же полю, где уже установлена фиксированная настройка, система выдаст ошибку о пересечении условий отбора или просто проигнорирует пользовательское действие.

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

Резюме

Для реализации качественного и дружелюбного интерфейса при программной установке отборов в динамических списках следуйте простым рекомендациям:

← На главную