При разработке интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача визуального выделения данных. Динамические списки — это мощный инструмент, но иногда стандартных настроек в конфигураторе недостаточно, особенно если логика раскраски строк или ячеек зависит от сложных расчетов времени (часы, минуты) или текущей даты сеанса. В таких случаях мы прибегаем к программному управлению условным оформлением.
Рассмотрим ситуацию: нам нужно красить поле с датой в разные цвета в зависимости от того, сколько времени осталось до наступления события. Например, если до даты более 5 дней — красим в зеленый, если менее 3 часов — в оранжевый, а если дата уже прошла — в красный. Разберем, как правильно реализовать эту логику и каких ошибок стоит избегать.
Типичная ошибка начинающего разработчика заключается в попытке добавить все отборы и все варианты оформления в один и тот же объект ЭлементУсловногоОформления. Проанализируем, почему это не работает. Когда мы создаем один элемент оформления и последовательно назначаем ему разные цвета фона и разные условия отбора, система просто перезаписывает предыдущие значения. В итоге «выигрывает» то условие, которое было прописано в коде последним.
Запомним главное правило: для каждого уникального варианта оформления (своего набора цветов, шрифтов или текста) необходимо создавать отдельный экземпляр ЭлементУсловногоОформления через метод Добавить() коллекции УсловноеОформление.Элементы.
Разберем правильный подход. Мы должны создать три отдельных правила оформления. Каждое правило будет иметь свой отбор (условие), свой цвет и свою область применения (конкретное поле списка).
Рассмотрим пример кода, который решает поставленную задачу:
// 1. Очищаем старые правила, если код вызывается повторно
УсловноеОформление.Элементы.Очистить();
// ПРАВИЛО №1: Просрочено (Красный цвет)
Элемент = УсловноеОформление.Элементы.Добавить();
// Устанавливаем оформление: Цвет текста или фона
ЭлементЦвета = Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.Красный);
// Настраиваем условие (отбор): Дата <= ТекущаяДата
КомпоновкаОтбора = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
КомпоновкаОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Дата");
КомпоновкаОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.МеньшеИлиРавно;
КомпоновкаОтбора.ПравоеЗначение = ТекущаяДатаСеанса();
КомпоновкаОтбора.Использование = Истина;
// Указываем, какое поле красить
ПолеОформления = Элемент.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("Дата");
ПолеОформления.Использование = Истина;
// ПРАВИЛО №2: Осталось менее 3 часов (Оранжевый цвет)
Элемент = УсловноеОформление.Элементы.Добавить();
Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.Оранжевый);
// Здесь важно правильно настроить интервал, чтобы условия не конфликтовали
ГруппаОтбора = Элемент.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаОтбора.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИ;
Отбор1 = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор1.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Дата");
Отбор1.ВидСравнения = ВидСравненияКомпоновкиДанных.Больше;
Отбор1.ПравоеЗначение = ТекущаяДатаСеанса();
Отбор2 = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор2.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Дата");
Отбор2.ВидСравнения = ВидСравненияКомпоновкиДанных.МеньшеИлиРавно;
Отбор2.ПравоеЗначение = ТекущаяДатаСеанса() + 3 * 3600; // + 3 часа
ПолеОформления = Элемент.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("Дата");
Выясним важный нюанс: в Системе Компоновки Данных (СКД), на которой работают динамические списки, правила оформления применяются в порядке их расположения в списке. Если для одной строки срабатывают сразу два правила, то итоговый вид ячейки будет определяться тем правилом, которое находится ниже в списке элементов оформления (применяется последним).
Чтобы избежать хаоса, мы можем использовать два подхода:
Если условий становится слишком много, программный код управления оформлением превращается в «простыню», которую сложно поддерживать. Профессиональным подходом считается перенос части логики в текст запроса динамического списка.
Проанализируем ситуацию: мы можем создать в запросе вычисляемое поле, например, СостояниеСрока. Рассмотрим пример текста запроса:
ВЫБРАТЬ
Документ.Ссылка,
Документ.Дата,
ВЫБОР
КОГДА Документ.Дата < &ТекущаяДата ТОГДА 2 // Просрочено
КОГДА РАЗНОСТЬДАТ(&ТекущаяДата, Документ.Дата, ЧАС) <= 3 ТОГДА 1 // Скоро срок
ИНАЧЕ 0 // В норме
КОНЕЦ КАК СостояниеСрока
ИЗ
Документ.ЗаказПокупателя КАК Документ
В этом случае в программном коде оформления нам достаточно будет проверять простое числовое значение поля СостояниеСрока. Это значительно ускоряет работу интерфейса, так как расчеты производятся базой данных, а не механизмом оформления на лету.
Если вы работаете в расширении конфигурации, важно помнить, что вызов кода оформления в процедуре ПриСозданииНаСервере (с аннотацией &После) дополнит уже существующие правила основной конфигурации. Чтобы ваши правила были главными, используйте метод Вставить(0, ...), чтобы поместить правило в самое начало или конец коллекции, в зависимости от логики перекрытия.
Рекомендации по производительности:
ПолеКомпоновкиДанных для указания путей к данным.ТекущаяДатаСеанса(), чтобы избежать проблем с разными часовыми поясами сервера и клиента.Использование. Если программно созданный элемент оформления не активен, проверьте, установлено ли это свойство в Истина для самого элемента, его отборов и полей.Используя эти методы, мы можем создавать гибкие, понятные и быстродействующие интерфейсы, которые помогают пользователю мгновенно ориентироваться в приоритетах своих задач.