Почему не сохраняется цвет в Хранилище Значений 1С и как это исправить

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

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

Разбор архитектуры хранения цвета

Для начала проанализируем, почему мы не можем просто создать реквизит объекта с типом Цвет. Платформа 1С не поддерживает тип Цвет как примитивный тип данных для полей таблиц базы данных. Поэтому мы используем «контейнер» — реквизит с типом ХранилищеЗначения. В этот контейнер можно поместить практически любой объект 1С, который поддерживает сериализацию.

Типичная схема работы выглядит следующим образом:

  1. На форме создается вспомогательный реквизит РеквизитФормыЦвет с типом Цвет.
  2. В базе данных (в объекте) создается реквизит РеквизитЦвет с типом ХранилищеЗначения.
  3. При открытии формы данные извлекаются из хранилища и помещаются в реквизит формы.
  4. При записи данные из реквизита формы упаковываются в новое хранилище и записываются в объект базы данных.

Шаг 1. Правильное чтение данных при открытии формы

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

Выясним причину, почему стандартный код может не сработать. Если мы используем РеквизитФормыВЗначение("Объект"), мы получаем копию данных объекта. Проанализируем пример кода для извлечения цвета:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    // Извлекаем данные из ХранилищаЗначения
    // Если в хранилище пусто, Получить() вернет Неопределено
    СохраненныйЦвет = ТекущийОбъект.РеквизитЦвет.Получить();
    
    Если СохраненныйЦвет <> Неопределено Тогда
        РеквизитФормыЦвет = СохраненныйЦвет;
    Иначе
        // Можно задать цвет по умолчанию, например, белый
        РеквизитФормыЦвет = ЦветаСтиля.ЦветФонаФормы;
    КонецЕсли;
КонецПроцедуры

Важный момент: в процедуре ПриЧтенииНаСервере параметр ТекущийОбъект уже содержит данные из базы, поэтому нам не нужно дополнительно вызывать РеквизитФормыВЗначение.

Шаг 2. Запись цвета в Хранилище Значения

Для сохранения данных мы используем обработчик ПередЗаписьюНаСервере. Здесь нам необходимо выполнить обратную операцию: взять значение из реквизита формы и поместить его в объект, который будет записан в базу данных.

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


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    // Перед записью упаковываем цвет из реквизита формы в ХранилищеЗначения
    ТекущийОбъект.РеквизитЦвет = Новый ХранилищеЗначения(РеквизитФормыЦвет);
КонецПроцедуры

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

Шаг 3. Решение проблемы с Диалогом выбора цвета

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

Рассмотрим пример правильной обработки выбора цвета на клиенте:


&НаКлиенте
Процедура ВыбратьЦвет(Команда)
    Диалог = Новый ДиалогВыбораЦвета;
    // Предварительно установим в диалог текущий цвет
    Диалог.Цвет = РеквизитФормыЦвет;
    
    // Оповещение о завершении выбора (для асинхронной работы в веб-клиенте)
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораЦвета", ЭтотОбъект);
    Диалог.Показать(Оповещение);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораЦвета(ВыбранныйЦвет, ДополнительныеПараметры) Экспорт
    Если ВыбранныйЦвет <> Неопределено Тогда
        // Присваиваем значение реквизиту формы, который потом будет сохранен
        РеквизитФормыЦвет = ВыбранныйЦвет;
        ЭтаФорма.Модифицированность = Истина;
    КонецЕсли;
КонецПроцедуры

Почему может возвращаться (0,0,0)?

Если вы видите, что цвет всегда сбрасывается в черный (RGB 0,0,0), проанализируем следующие причины:

  1. Тип цвета: 1С поддерживает абсолютные цвета, цвета стиля и системные цвета Windows. Если вы сохраняете цвет стиля (например, «Цвет текста кнопки»), а затем открываете этот объект в другой конфигурации или в другом сеансе, где этот стиль недоступен, система может интерпретировать его как пустой (черный). Для стабильности рекомендуется сохранять именно абсолютные цвета.
  2. Инициализация: Если реквизит РеквизитФормыЦвет не инициализирован при создании, он по умолчанию может иметь значение Новый Цвет(), что соответствует черному.
  3. Кэширование: При работе с ХранилищеЗначения помните, что метод .Получить() возвращает копию объекта. Если вы измените полученный объект цвета, в хранилище он не изменится, пока вы не создадите новое ХранилищеЗначения и не присвоите его реквизиту объекта.

Альтернативный метод: Хранение в виде строки (HEX) или числа

Для тех, кто хочет избежать работы с ХранилищеЗначения (например, для упрощения построения отчетов или интеграции), рассмотрим метод хранения цвета в виде обычного числа. Любой абсолютный цвет можно представить как формулу: Красный + Зеленый * 256 + Синий * 65536.

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


// Преобразование Цвета в Число
ЧисловойЦвет = ВыбранныйЦвет.Красный + ВыбранныйЦвет.Зеленый * 256 + ВыбранныйЦвет.Синий * 65536;

// Восстановление Цвета из Числа
Красный = ЧисловойЦвет % 256;
Зеленый = Цел(ЧисловойЦвет / 256) % 256;
Синий = Цел(ЧисловойЦвет / 65536);
ВосстановленныйЦвет = Новый Цвет(Красный, Зеленый, Синий);

Такой подход позволяет хранить цвет в обычном реквизите типа Число(10), что значительно ускоряет работу базы данных и упрощает выборку цветов в запросах, так как не требуется обращение к таблицам двоичных данных, где хранятся значения ХранилищаЗначения.

Итоги

Мы проанализировали основные этапы работы с цветом в 1С. Главное правило — использовать ПриЧтенииНаСервере для загрузки данных и ПередЗаписьюНаСервере для их упаковки в ХранилищеЗначения. Также важно следить за тем, чтобы данные, выбираемые через диалоги, корректно попадали в реквизиты формы. Используя эти рекомендации, вы сможете избежать проблем с «пропаданием» цвета и обеспечите стабильную работу вашего интерфейса.

← На главную