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