Как программно установить отбор в отчете на базе СКД

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

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

Разбираем причину проблемы: почему отбор не устанавливается

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

  1. Настройки (Settings): Основная структура отчета, определенная в схеме (варианте).
  2. Пользовательские настройки (User Settings): Те параметры, которые выведены непосредственно на форму отчета для редактирования пользователем.
  3. Фиксированные настройки (Fixed Settings): Отборы, которые накладываются жестко и не могут быть изменены пользователем в интерфейсе.

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

Способ 1. Установка отбора через пользовательские настройки

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

Выполним следующие шаги в коде:


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

Способ 2. Программное создание пользовательского отбора "с нуля"

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


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

КонецПроцедуры

Способ 3. Использование фиксированных настроек

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

Рассмотрим пример установки такого отбора:


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

Способ 4. Передача отбора через параметры формы (БСП)

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

Проанализируем этот компактный код:


&НаКлиенте
Процедура ОткрытьОтчетСПараметрами(ВыбраннаяНоменклатура)
    
    ПараметрыФормы = Новый Структура;
    
    // Формируем структуру отбора: Ключ - имя поля в СКД, Значение - то, что ищем
    Отбор = Новый Структура;
    Отбор.Вставить("Номенклатура", ВыбраннаяНоменклатура);
    
    ПараметрыФормы.Вставить("Отбор", Отбор);
    ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
    ПараметрыФормы.Вставить("КлючВарианта", "Основной");
    
    ОткрытьФорму("Отчет.МойОтчетЗаказы.Форма", ПараметрыФормы);
    
КонецПроцедуры

Важные нюансы и типичные ошибки

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

  1. Виды сравнения и типы данных: Если вы передаете в качестве значения СписокЗначений, обязательно устанавливайте ВидСравнения в значение ВидСравненияКомпоновкиДанных.ВСписке. Если оставить стандартное Равно, СКД не сможет сопоставить типы и выдаст пустой результат.
  2. Клиент и сервер: Хотя объект КомпоновщикНастроек доступен на клиенте, обращение к некоторым его свойствам (например, ДоступныеПоляОтбора) может потребовать серверного вызова. Если ваш код на клиенте "не видит" поля, попробуйте перенести логику установки в серверную процедуру ПриСозданииНаСервере самой формы отчета.
  3. Метод ПолучитьНастройки(): В некоторых случаях (особенно в старых версиях платформы) прямое изменение свойства Настройки не приводит к обновлению компоновщика. В таких ситуациях рекомендуется использовать метод КомпоновщикНастроек.ПолучитьНастройки(), модифицировать полученный объект, а затем загружать его обратно через ЗагрузитьНастройки().
  4. Стандартные функции БСП: Всегда проверяйте наличие общего модуля ОбщегоНазначенияКлиентСервер. Функция УстановитьЭлементОтбора() из этого модуля — это "золотой стандарт". Она автоматически проверяет существование поля, корректно обрабатывает использование и типы сравнения, избавляя вас от написания десятков строк кода вручную.

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

← На главную