При разработке прикладных решений часто возникает задача визуального оформления данных: выделить определенные строки отчета, раскрасить ячейки динамического списка или привязать индивидуальный цвет к конкретному элементу справочника (например, к статусу заказа, проекту или подразделению). Однако разработчики сталкиваются с ограничением платформы: в метаданных «1С:Предприятие» для реквизитов таблиц базы данных (справочников, документов, регистров) тип данных Цвет недоступен. Этот тип поддерживается только для реквизитов управляемых форм и переменных встроенного языка.
Разберем, какими способами можно сохранить выбранный пользователем цвет в реквизитах объекта, выясним подводные камни каждого подхода и рассмотрим примеры программной реализации.
На первый взгляд самым очевидным решением кажется создание трех числовых реквизитов (Красный, Зеленый, Синий) либо упаковка их в одно целое число или строку формата #FFFFFF. Однако при попытке разложить произвольный цвет на составляющие разработчик может столкнуться с неожиданным поведением системы.
Объект Цвет в платформе 1С имеет системное свойство Вид (значение системного перечисления ВидЦвета). Свойства Красный, Зеленый и Синий возвращают корректные числовые значения (от 0 до 255) только тогда, когда цвет является абсолютным (Цвет.Вид = ВидЦвета.Абсолютный). Если пользователь в стандартном диалоге выбрал цвет из палитры веб-цветов, системных стилей оформления или цветов Windows (например, ВидЦвета.WebЦвет или ВидЦвета.WindowsЦвет), свойства каналов вернут значение -1. Любая математическая формула расчета числового кода с такими значениями выдаст ошибку или некорректный результат.
Поэтому выбор способа хранения напрямую зависит от того, разрешено ли пользователю выбирать любые цвета платформы или выбор строго ограничен абсолютными значениями RGB.
Если в системе используются только абсолютные цвета, самым компактным и удобным для выборки в запросах вариантом является хранение цвета в виде одного целого неотрицательного числа (длиной 10 символов, диапазон от 0 до 16 777 215). Это исключает необходимость заводить три отдельных поля в таблице базы данных.
Рассмотрим алгоритм упаковки трех составляющих (Red, Green, Blue) в одно число и обратного восстановления объекта Цвет:
// Преобразование компонент RGB в числовое значение для хранения
Функция ПолучитьЗначениеХраненияЦвета(Красный, Зеленый, Синий) Экспорт
Возврат Синий * 256 * 256 + Зеленый * 256 + Красный;
КонецФункции
// Преобразование числового значения обратно в объект Цвет
Функция ПолучитьЦветПоЗначениюХранения(КодЦвета) Экспорт
Синий = Цел(КодЦвета / (256 * 256));
Зеленый = Цел((КодЦвета - Синий * 256 * 256) / 256);
Красный = КодЦвета - Синий * 256 * 256 - Зеленый * 256;
Возврат Новый Цвет(Красный, Зеленый, Синий);
КонецФункции
Преимущество такого подхода заключается в том, что реквизит имеет простой примитивный тип Число, быстро читается запросами и занимает минимум места в СУБД.
Если пользователю разрешено выбирать системные цвета, веб-цвета или цвета стилей оформления, разложение по формуле формул RGB не сработает. Чтобы не использовать избыточный тип ХранилищеЗначения, наилучшим решением будет использование механизма XDTO-сериализации в строковый реквизит (длиной 100–150 символов).
Платформа «1С:Предприятие» умеет полностью сериализовать объект Цвет в компактную XML-строку, сохраняя информацию о его виде и свойствах. Разберем реализацию функций сериализации и десериализации:
// Преобразует объект Цвет в XML-строку
Функция ЦветВСтрокуXML(Знач ВыбранныйЦвет) Экспорт
Если ВыбранныйЦвет = Неопределено Тогда
Возврат "";
КонецЕсли;
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(Запись, ВыбранныйЦвет);
Возврат Запись.Закрыть();
КонецФункции
// Восстанавливает объект Цвет из XML-строки
Функция ЦветИзСтрокиXML(Знач СтрокаXML) Экспорт
Если ПустаяСтрока(СтрокаXML) Тогда
Возврат Новый Цвет();
КонецЕсли;
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаXML);
Возврат СериализаторXDTO.ПрочитатьXML(Чтение);
КонецФункции
Преимущества сериализации через XDTO:
ХранилищаЗначения, строковые поля не выносятся СУБД в отдельные таблицы для BLOB-данных, не создают накладных расходов на распаковку архива и доступны для анализа.ЗначениеВСтрокуВнутр().Классический подход для хранения сложных объектов — создание реквизита с типом ХранилищеЗначения. В него объект Цвет помещается целиком с помощью конструктора Новый ХранилищеЗначения(ВыбранныйЦвет).
Этот метод гарантирует стопроцентное сохранение структуры объекта, однако обладает существенным недостатком: поле таблицы базы данных невозможно быстро получить через простой запрос вместе с остальными реквизитами без считывания тяжелых данных, а само значение нельзя прочитать без инициализации объекта на сервере методом Получить().
Для реализации удобного интерфейса пользователя настроим управляемую форму элемента справочника по следующим шагам:
ЦветЭлемента и типом Цвет.ПолеВвода. Платформа автоматически сделает его интерактивным: в поле будет отображаться заливка текущего цвета, а при нажатии откроется стандартная палитра выбора.ПриЧтенииСозданииНаСервере выполним инициализацию реквизита формы из реквизита объекта (распакуем число, строку XML или значение из хранилища).ПередЗаписьюНаСервере преобразуем значение из реквизита формы обратно в формат хранения реквизита объекта.
&НаСервере
Процедура ПриЧтенииСозданииНаСервере()
// Восстанавливаем цвет из сохраненной строки XML
ЦветЭлемента = ЦветИзСтрокиXML(Объект.ЦветСтрокаXML);
КонецПроцедуры
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Сохраняем цвет в реквизит объекта
ТекущийОбъект.ЦветСтрокаXML = ЦветВСтрокуXML(ЦветЭлемента);
КонецПроцедуры
Если сохраненный цвет требуется применить в отчете, построенном на системе компоновки данных (СКД), важно учитывать архитектуру платформы: в схеме компоновки нельзя напрямую передать строковое или числовое поле запроса в стандартное условное оформление без дополнительной обработки.
Для динамической раскраски отчета применяют программную настройку в событии ПриКомпоновкеРезультата модуля отчета или формы. Перед выводом отчета считываются ссылки на элементы справочника вместе с их сохраненными цветами, после чего программно заполняется коллекция КомпоновщикНастроек.Настройки.УсловноеОформление, где для каждой ссылки создается элемент оформления с соответствующим объектом Цвет в качестве цвета фона или текста.