Как реализовать градиентную раскраску и сложное условное оформление в СКД?

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

При разработке отчетов на системе компоновки данных (СКД) стандартных возможностей визуализации часто бывает недостаточно. Одной из наиболее интересных и в то же время трудоемких задач является создание «градиентной раскраски» показателей. Заказчики часто хотят видеть наглядный переход цвета от красного (для минимальных значений) к зеленому (для максимальных), либо выделение специфических групп, таких как «Топ-3» или «Худшие 3». В этой статье мы подробно разберем, как реализовать такие механизмы, используя программные методы и математические расчеты.

Постановка задачи и выбор стратегии

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

  1. Программная генерация коллекции условного оформления — создание правил в коде перед выводом отчета.
  2. Математическая интерполяция — расчет цветовых составляющих RGB на основе значения ячейки.
  3. Пост-обработка табличного документа — изменение оформления уже после того, как отчет сформирован.
  4. Использование вычисляемых полей для ранжирования — выделение лидеров и аутсайдеров списка.

Метод 1: Математический расчет градиента (Линейная интерполяция)

Для того чтобы реализовать плавный переход цвета, нам необходимо перевести числовое значение ячейки в цветовую шкалу. Допустим, мы хотим раскрасить значения от 0 до 100 в диапазоне от Красного (255, 0, 0) до Зеленого (0, 255, 0). Для этого используется коэффициент нормализации.

Рассмотрим алгоритм расчета. Сначала вычислим коэффициент k по формуле: (ТекущееЗначение - Минимум) / (Максимум - Минимум). Этот коэффициент будет меняться от 0 до 1. Далее рассчитаем компоненты цвета:

R = R1 + (R2 - R1) * k

G = G1 + (G2 - G1) * k

B = B1 + (B2 - B1) * k

Если нам нужен трехцветный градиент (Красный — Желтый — Зеленый), мы разделим диапазон на две части: от 0 до 0.5 (переход из красного в желтый) и от 0.5 до 1 (из желтого в зеленый).

Метод 2: Программная генерация УО в модуле отчета

Наиболее надежный способ внедрить градиент в СКД — это динамическое создание правил оформления в процедуре ПриКомпоновкеРезультата модуля объекта отчета. Мы не будем создавать правило для каждой ячейки, а создадим, например, 50 «ступенек» цвета. Это создаст визуальный эффект плавного перехода.

Разберем пример кода, который генерирует такие правила:


Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
	
	// Определим количество ступеней градиента
	КоличествоСтупеней = 20;
	МинимальноеЗначение = 0; // В реальности нужно получить из данных
	МаксимальноеЗначение = 1000;
	Шаг = (МаксимальноеЗначение - МинимальноеЗначение) / КоличествоСтупеней;
	
	Для Итератор = 0 По КоличествоСтупеней - 1 Цикл
		
		НижняяГраница = МинимальноеЗначение + Итератор * Шаг;
		ВерхняяГраница = НижняяГраница + Шаг;
		
		// Рассчитываем цвет (упрощенно от красного к зеленому)
		ТекЦвет = Новый Цвет(255 - (255/КоличествоСтупеней * Итератор), 255/КоличествоСтупеней * Итератор, 0);
		
		ЭлементУО = КомпоновщикНастроек.Настройки.УсловноеОформление.Элементы.Добавить();
		ЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветФона", ТекЦвет);
		
		// Условие: Значение >= НижняяГраница И Значение < ВерхняяГраница
		ЭлементУсловия = ЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
		ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СуммаОборот");
		ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.БольшеИлиРавно;
		ЭлементУсловия.ПравоеЗначение = НижняяГраница;
		
		ЭлементУсловия = ЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
		ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СуммаОборот");
		ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.Меньше;
		ЭлементУсловия.ПравоеЗначение = ВерхняяГраница;
		
		// Указываем поле, к которому применяется оформление
		ПолеОформления = ЭлементУО.Поля.Элементы.Добавить();
		ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("СуммаОборот");
		
	КонецЦикла;
	
	// Далее стандартный вывод...
	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
	
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(Результат);
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);
	
КонецПроцедуры

Метод 3: Использование «прозрачного» поля для Топ-3

Для задачи выделения первых и последних трех значений (Топ-3 / Худшие-3) мы можем использовать функции языка выражений СКД. Выясним, как это сделать без написания сложного кода в модулях. Нам поможет функция ВычислитьВыражение с использованием агрегатов.

Проанализируем шаги настройки:

  1. Добавим в схему вычисляемое поле РангПоказателя.
  2. В выражении поля пропишем формулу, которая вернет порядковый номер строки в текущей группировке, отсортированный по значению показателя. Пример: ВычислитьВыражение("Количество()", , , "Первая", "Текущая") при условии, что в настройках установлена сортировка по ресурсу.
  3. В настройках условного оформления добавим два правила:
    • Если РангПоказателя <= 3, тогда ЦветФона = Зеленый (Топ-3).
    • Если РангПоказателя > (КоличествоВсего - 3), тогда ЦветФона = Красный (Худшие-3).

Этот метод хорош тем, что он сохраняет высокую производительность отчета и работает в рамках стандартного механизма компоновки.

Метод 4: Пост-обработка сформированного Табличного Документа

Рассмотрим ситуацию, когда нам нужно максимально гибкое дизайнерское оформление, которое сложно описать правилами СКД. В этом случае мы можем выполнить обход уже готового ТабличногоДокумента.

Выясним причину, почему этот метод иногда предпочтительнее: СКД не всегда корректно передает объект типа Цвет, сформированный в функции общего модуля, в оформление ячейки. Прямая установка свойства ЦветФона у области ячеек снимает это ограничение.

Пример алгоритма обхода:


// После вывода отчета в ТабличныйДокумент
Для СтрокаЦ = 1 По ТабличныйДокумент.ВысотаТаблицы Цикл
	Для КолонкаЦ = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл
		ТекущаяОбласть = ТабличныйДокумент.Область(СтрокаЦ, КолонкаЦ);
		// Проверяем, что в ячейке число и оно относится к нужному нам показателю
		Если ТипЗнч(ТекущаяОбласть.Текст) = Тип("Число") Тогда
			Коэффициент = (ТекущаяОбласть.Текст - Мин) / (Макс - Мин);
			ТекущаяОбласть.ЦветФона = ПолучитьЦветИзГрадиента(Коэффициент);
		КонецЕсли;
	КонецЦикла;
КонецЦикла;

Важно помнить, что при использовании этого метода необходимо заранее знать координаты (колонки) ресурсов, чтобы не раскрашивать лишние данные, такие как номера строк или даты.

Оптимизация: Дискретный градиент

Проанализируем проблему производительности. Если в отчете 10 000 строк и для каждой ячейки СКД будет пытаться рассчитать сложную функцию, формирование может затянуться. Чтобы этого избежать, используем дискретный градиент.

Создадим в запросе или в вычисляемом поле выражение, которое приводит значение к индексу от 1 до 10. Например: Целое( (Значение - Мин) / (Макс - Мин) * 10 ). После этого в схеме компоновки данных создаем всего 10 фиксированных правил условного оформления. Это обеспечит мгновенную отрисовку даже на огромных объемах данных, так как расчет индекса происходит на уровне SQL-запроса или примитивной арифметики СКД.

Резюме

Мы рассмотрели различные подходы к созданию сложного оформления. Подведем итог: если вам нужен настоящий плавный градиент, используйте программную генерацию 20-50 правил в ПриКомпоновкеРезультата. Если задача стоит в выделении лидеров продаж (Топ-N), лучше всего подойдут вычисляемые поля с оконными функциями СКД. Для максимальной гибкости используйте постобработку табличного документа, а для высокой скорости на больших отчетах — дискретную шкалу из фиксированных правил оформления.

← На главную