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