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