Как программно установить отбор СКД из формы отчета, чтобы он отображался у пользователя?

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

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

Почему обычная установка отбора не всегда работает?

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

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

Разбор уровней настроек СКД

Прежде чем переходить к коду, важно понять, с какими объектами мы работаем в КомпоновщикеНастроек:

  1. Настройки (свойство Настройки): Это «каркас» настроек. Здесь определяются все возможные поля, группировки и отборы, которые заложены разработчиком изначально.
  2. Пользовательские настройки (свойство ПользовательскиеНастройки): Именно эти данные отображаются на форме. Если пользователь нажал «Сформировать», система берет основные настройки и «накладывает» на них пользовательские.
  3. Фиксированные настройки (свойство ФиксированныеНастройки): Эти настройки нельзя изменить программно в коде формы (только при инициализации) или вручную в интерфейсе. Они жестко ограничивают выборку данных.

Решение проблемы: связка через Идентификатор

Чтобы программно установленный отбор отобразился на форме, необходимо убедиться, что у элемента отбора заполнен ИдентификаторПользовательскойНастройки. Если этого идентификатора нет, отбор будет работать «за кулисами», и пользователь даже не будет знать о его существовании.

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


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

Особенности использования вида сравнения «В списке»

В исходном обсуждении упоминалась задача установки отбора с видом сравнения ВидСравненияКомпоновкиДанных.ВСписке. Здесь кроется еще одна распространенная ошибка. Многие пытаются передать в качестве значения массив (результат метода ВыгрузитьКолонку()) или таблицу значений.

Проанализируем ситуацию: СКД строго требует, чтобы для вида сравнения ВСписке в качестве ПравоеЗначение выступал объект типа СписокЗначений. Если вы передадите массив, отчет может не сформироваться или выдать ошибку.

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


// Предположим, у нас есть МассивНоменклатуры
СписокДляОтбора = Новый СписокЗначений;
СписокДляОтбора.ЗагрузитьЗначения(МассивНоменклатуры);

// Вызываем нашу процедуру
УстановитьОтборСКД("Номенклатура", ВидСравненияКомпоновкиДанных.ВСписке, СписокДляОтбора);

Как гарантированно обновить настройки в «Пользовательских настройках»

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

Разберем алгоритм более надежного способа:

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

Пример реализации этого подхода:


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

Использование функций БСП

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

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


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

Важно помнить, что после использования методов БСП для изменения основных настроек, необходимо вызвать метод КомпоновщикНастроек.ЗагрузитьПользовательскиеНастройки() или синхронизировать их вручную, чтобы форма увидела изменения.

Итоги и рекомендации

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

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

← На главную