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