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