Как раскрасить строки списка справочника на основе цвета из Хранилища значений в 1С 8.3

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

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

Проблема использования Хранилища значений в динамических списках

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

Решение через обработчик ПриПолученииДанныхНаСервере

Начиная с версии платформы 8.3.10, для динамических списков стал доступен мощный инструмент — событие ПриПолученииДанныхНаСервере. Рассмотрим этот механизм подробнее. Этот обработчик вызывается после того, как сервер подготовил порцию данных для отображения на клиенте, но до того, как они были отправлены в форму.

Разберем по шагам реализацию в модуле формы списка:

  1. Выберем в настройках динамического списка (свойство «События») обработчик ПриПолученииДанныхНаСервере.
  2. Проанализируем входящий параметр ОформленияСтрок. Это коллекция, в которой содержатся данные строк, подготовленных к выводу.
  3. Для каждой строки извлечем данные, получим цвет из объекта и установим оформление.

Пример кода для реализации этой логики:


&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
    
    // Перебираем строки, которые платформа подготовила для вывода на экран
    Для Каждого СтрокаСписок Из Строки Цикл
        
        // Получаем ссылку на текущий элемент справочника
        ТекущаяСсылка = СтрокаСписок.Ключ;
        
        // ВНИМАНИЕ: Прямое чтение объекта в цикле снижает производительность.
        // Рекомендуется кэшировать данные или использовать вспомогательные реквизиты.
        ОбъектДанных = ТекущаяСсылка.ПолучитьОбъект();
        
        Если ТипЗнч(ОбъектДанных.Цвет) = Тип("ХранилищеЗначений") Тогда
            ЗначениеЦвета = ОбъектДанных.Цвет.Получить();
            
            Если ТипЗнч(ЗначениеЦвета) = Тип("Цвет") Тогда
                // Устанавливаем цвет фона для всей строки
                СтрокаСписок.Значение.Оформление["Код"].УстановитьЗначениеПараметра("ЦветФона", ЗначениеЦвета);
                // Если нужно раскрасить всю строку, используем цикл по полям или конкретное поле
            КонецЕсли;
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Оптимизация производительности (Важно!)

Метод, описанный выше (с получением объекта через ПолучитьОбъект()), крайне непроизводителен. Выясним причину: при прокрутке списка для каждой строки сервер будет выполнять отдельный запрос к базе данных для десериализации ХранилищаЗначений. Это приведет к «тормозам» интерфейса.

Рассмотрим правильный архитектурный подход:

  1. Добавим в справочник дополнительный реквизит ЦветЧислом (тип Число).
  2. При записи объекта (в событии ПередЗаписью) будем извлекать цвет из хранилища и сохранять его числовое представление (RGB).
  3. В динамическом списке будем считывать уже готовое число.

Посмотрим на пример преобразования цвета в число:


// В модуле объекта
Процедура ПередЗаписью(Отказ)
    Если ТипЗнч(Цвет) = Тип("ХранилищеЗначений") Тогда
        ЗначениеЦвета = Цвет.Получить();
        Если ТипЗнч(ЗначениеЦвета) = Тип("Цвет") Тогда
            // Сохраняем компоненты цвета для быстрого доступа
            ЭтотОбъект.ЦветЧислом = (ЗначениеЦвета.Красный * 65536) + (ЗначениеЦвета.Зеленый * 256) + ЗначениеЦвета.Синий;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Использование маркеров и Условного Оформления

Выясним, как использовать подход с «маркерами», упомянутый опытными разработчиками. Если количество цветов ограничено (например, 10–20 вариантов), лучше использовать Условное Оформление формы.

Проанализируем ситуацию: вместо передачи самого объекта цвета, мы передаем строковый или числовой код. В настройках списка в конфигураторе или программно создаем правила: «Если Поле КодЦвета равно 1, тогда ЦветФона — Красный». Это работает быстрее всего, так как отрисовка ложится на платформенные механизмы, оптимизированные под работу с видеокартой.

Особенности версий 8.3.12 и 8.3.13+ (Выделение строк)

При работе в версии 8.3.12 вы столкнетесь с проблемой: активная (выделенная курсором) строка перекрывает вашу раскраску системным синим цветом. Пользователь не увидит цвет фона, пока не перейдет на другую строку.

Начиная с версии 8.3.13, разработчики 1С добавили свойство ЦветФонаВыделения. Рассмотрим, как это помогает нам: мы можем установить цвет выделения в значение Авто или настроить его так, чтобы он был полупрозрачным, позволяя видеть основной цвет строки. В 8.3.12, как отмечалось в обсуждении, выделенной строке «все равно» на программную раскраску фона, поэтому рекомендуется раскрашивать не всю строку, а конкретную колонку (например, Код или специально созданную колонку-индикатор).

Резюме для реализации

Для достижения наилучшего результата выполним следующие действия:

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

← На главную