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