Почему не срабатывает программный отбор в СКД на управляемых формах?

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

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

Разбор типичной ситуации

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


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

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

Приоритет пользовательских настроек

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

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

Чтобы проверить это в отладчике, необходимо использовать метод ПолучитьНастройки():


ИтоговыеНастройки = Отчет.КомпоновщикНастроек.ПолучитьНастройки();
// Проверьте коллекцию ИтоговыеНастройки.Отбор.Элементы — именно она идет в запрос

Решение проблемы через режим отображения

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


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

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

Правильный подход к программной установке отбора

Для того чтобы ваш код был надежным и работал во всех случаях, рекомендуется следовать определенному алгоритму. Разберем его по шагам:

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

Использование методов БСП

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

Пример использования функции БСП:


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

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

Резюме и рекомендации

Подведем итог. Если программный отбор в СКД не срабатывает:

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

← На главную