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