Как настроить условное оформление динамического списка по сложному условию или данным строки

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

При переходе с обычных форм на управляемые разработчики часто сталкиваются с изменением принципов визуального оформления списков. В обычном интерфейсе для этого использовались события ПриВыводеСтроки и ПриПолученииДанных, где через свойство ОформлениеСтроки.ДанныеСтроки можно было получить любые значения текущей строки (включая объекты прикладного типа) и программно раскрасить ячейки. В управляемом интерфейсе динамический список функционирует иначе: оформление выполняется декларативно на уровне платформы через компоновщик настроек.

Разберем, как в динамическом списке сравнивать значения с полями текущей строки, почему возникают сложности с реквизитами типа ХранилищеЗначения и какими способами можно решить эту задачу.

Вариант 1. Сравнение значения с другим полем строки в условном оформлении

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

Рассмотрим по шагам настройку в конфигураторе:

  1. Открываем свойства формы и переходим в раздел Условное оформление (или открываем свойства динамического списка).
  2. Добавляем новый элемент условного оформления и настраиваем оформляемые поля и параметры (например, цвет фона или цвет текста).
  3. На вкладке Условие добавляем новый элемент отбора, выбираем левое поле (например, Список.СуммаОплаты) и вид сравнения (например, Меньше).
  4. В колонке правого значения по умолчанию предлагается ввести фиксированное значение. Чтобы выбрать поле строки, нажимаем меню Еще (или контекстное меню) и выбираем пункт Использовать в качестве значения поле.
  5. Выбираем нужное поле компоновки данных (например, Список.СуммаДокумента).

Посмотрим на программный пример добавления такого условия через встроенный язык:


ЭлементОформления = УсловноеОформление.Элементы.Добавить();

// Настройка оформления
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", WebЦвета.СветлоРозовый);

// Оформляемые поля
ОформляемоеПоле = ЭлементОформления.Поля.Элементы.Добавить();
ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("СуммаОплаты");

// Настройка отбора: ЛевоеПоле < ПравоеПоле
ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Список.СуммаОплаты");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Меньше;
ЭлементОтбора.ПравоеЗначение = Новый ПолеКомпоновкиДанных("Список.СуммаДокумента");
ЭлементОтбора.Использование = Истина;

Ограничение: почему нельзя оформить строку по данным из ХранилищаЗначения

Проанализируем частую архитектурную проблему: в документе хранится реквизит с типом ХранилищеЗначения, внутри которого сериализована таблица или структура, и требуется раскрашивать строки динамического списка в зависимости от содержимого этого хранилища.

Динамический список формирует данные порционно через SQL-запрос к СУБД. База данных не может распаковать бинарные данные и извлечь структуру объекта 1С на лету во время выполнения запроса. Метод Получить() объекта ХранилищеЗначения работает исключительно в серверном коде 1С, поэтому использовать его внутри запроса или в формулах схемы компоновки данных невозможно.

Вариант 2. Программное получение данных списка в таблицу значений

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

Посмотрим на пример серверной функции для получения таблицы значений:


&НаСервере
Функция СписокВТЗнаСервере()
    Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
    Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных();
    МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    ТаблицаРезультат = ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    Возврат ТаблицаРезультат;
КонецФункции

Важно: этот способ не подходит для оформления динамического списка в реальном времени при больших объемах данных, так как при каждом обновлении списка будет происходить полная выгрузка всей выборки, что вызовет существенные задержки интерфейса.

Вариант 3. Вынос признака оформления в отдельный реквизит или регистр сведений

Для сохранения высокой производительности динамического списка правильным решением является денормализация данных:

  1. Добавление реквизита в объект: добавляем в документ явный реквизит-признак (например, Булево или перечисление). В модуле объекта в обработчике ПередЗаписью распаковываем ХранилищеЗначения, вычисляем необходимый признак и сохраняем его в реквизит. Этот реквизит сразу становится доступен в запросе динамического списка и условном оформлении.
  2. Использование служебного регистра сведений: если менять структуру самого документа нельзя, создаем непериодический регистр сведений, где ведущим измерением является ссылка на документ, а ресурсом — вычисленный статус. Заполнение регистра выполняется по подписке на событие ПриЗаписи, а в динамическом списке настраивается левое соединение с этим регистром.

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

← На главную