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