Работа с визуальными характеристиками интерфейса, такими как цвет, часто требует сохранения этих настроек в базе данных. В 1С:Предприятии для хранения сложных типов данных, которые не могут быть представлены в виде простых строк или чисел, используется объект ХранилищеЗначения. Однако начинающие разработчики часто сталкиваются с ситуацией, когда после записи объекта цвет «сбрасывается» в черный (0,0,0) или вовсе не считывается. В данной статье мы подробно разберем, как правильно организовать жизненный цикл данных типа Цвет на управляемой форме.
Для начала проанализируем, почему мы не можем просто создать реквизит объекта с типом Цвет. Платформа 1С не поддерживает тип Цвет как примитивный тип данных для полей таблиц базы данных. Поэтому мы используем «контейнер» — реквизит с типом ХранилищеЗначения. В этот контейнер можно поместить практически любой объект 1С, который поддерживает сериализацию.
Типичная схема работы выглядит следующим образом:
РеквизитФормыЦвет с типом Цвет.РеквизитЦвет с типом ХранилищеЗначения.Рассмотрим ситуацию, когда разработчик пытается прочитать данные в процедуре ПриСозданииНаСервере. Хотя это допустимо для новых объектов, для существующих записей более правильным и надежным методом является использование обработчика ПриЧтенииНаСервере. Этот обработчик вызывается платформой каждый раз, когда данные объекта считываются из базы, в том числе при перечитывании данных.
Выясним причину, почему стандартный код может не сработать. Если мы используем РеквизитФормыВЗначение("Объект"), мы получаем копию данных объекта. Проанализируем пример кода для извлечения цвета:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
// Извлекаем данные из ХранилищаЗначения
// Если в хранилище пусто, Получить() вернет Неопределено
СохраненныйЦвет = ТекущийОбъект.РеквизитЦвет.Получить();
Если СохраненныйЦвет <> Неопределено Тогда
РеквизитФормыЦвет = СохраненныйЦвет;
Иначе
// Можно задать цвет по умолчанию, например, белый
РеквизитФормыЦвет = ЦветаСтиля.ЦветФонаФормы;
КонецЕсли;
КонецПроцедуры
Важный момент: в процедуре ПриЧтенииНаСервере параметр ТекущийОбъект уже содержит данные из базы, поэтому нам не нужно дополнительно вызывать РеквизитФормыВЗначение.
Для сохранения данных мы используем обработчик ПередЗаписьюНаСервере. Здесь нам необходимо выполнить обратную операцию: взять значение из реквизита формы и поместить его в объект, который будет записан в базу данных.
Проанализируем ситуацию: объект ХранилищеЗначения нельзя модифицировать. Чтобы изменить его содержимое, нужно создать новый экземпляр Новый ХранилищеЗначения(Данные). Рассмотрим пример:
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Перед записью упаковываем цвет из реквизита формы в ХранилищеЗначения
ТекущийОбъект.РеквизитЦвет = Новый ХранилищеЗначения(РеквизитФормыЦвет);
КонецПроцедуры
Важно: Обратите внимание, что мы работаем напрямую с параметром ТекущийОбъект. Все изменения, внесенные в этот параметр внутри данной процедуры, будут автоматически зафиксированы в базе данных после успешного завершения транзакции записи.
Одной из часто встречающихся ошибок является неправильная работа с объектом ДиалогВыбораЦвета. Если вы вызываете диалог программно, необходимо убедиться, что выбранное значение действительно передается в реквизит формы, который связан с элементами интерфейса.
Рассмотрим пример правильной обработки выбора цвета на клиенте:
&НаКлиенте
Процедура ВыбратьЦвет(Команда)
Диалог = Новый ДиалогВыбораЦвета;
// Предварительно установим в диалог текущий цвет
Диалог.Цвет = РеквизитФормыЦвет;
// Оповещение о завершении выбора (для асинхронной работы в веб-клиенте)
Оповещение = Новый ОписаниеОповещения("ПослеВыбораЦвета", ЭтотОбъект);
Диалог.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораЦвета(ВыбранныйЦвет, ДополнительныеПараметры) Экспорт
Если ВыбранныйЦвет <> Неопределено Тогда
// Присваиваем значение реквизиту формы, который потом будет сохранен
РеквизитФормыЦвет = ВыбранныйЦвет;
ЭтаФорма.Модифицированность = Истина;
КонецЕсли;
КонецПроцедуры
Если вы видите, что цвет всегда сбрасывается в черный (RGB 0,0,0), проанализируем следующие причины:
РеквизитФормыЦвет не инициализирован при создании, он по умолчанию может иметь значение Новый Цвет(), что соответствует черному.ХранилищеЗначения помните, что метод .Получить() возвращает копию объекта. Если вы измените полученный объект цвета, в хранилище он не изменится, пока вы не создадите новое ХранилищеЗначения и не присвоите его реквизиту объекта.Для тех, кто хочет избежать работы с ХранилищеЗначения (например, для упрощения построения отчетов или интеграции), рассмотрим метод хранения цвета в виде обычного числа. Любой абсолютный цвет можно представить как формулу: Красный + Зеленый * 256 + Синий * 65536.
Посмотрим на пример функций преобразования:
// Преобразование Цвета в Число
ЧисловойЦвет = ВыбранныйЦвет.Красный + ВыбранныйЦвет.Зеленый * 256 + ВыбранныйЦвет.Синий * 65536;
// Восстановление Цвета из Числа
Красный = ЧисловойЦвет % 256;
Зеленый = Цел(ЧисловойЦвет / 256) % 256;
Синий = Цел(ЧисловойЦвет / 65536);
ВосстановленныйЦвет = Новый Цвет(Красный, Зеленый, Синий);
Такой подход позволяет хранить цвет в обычном реквизите типа Число(10), что значительно ускоряет работу базы данных и упрощает выборку цветов в запросах, так как не требуется обращение к таблицам двоичных данных, где хранятся значения ХранилищаЗначения.
Мы проанализировали основные этапы работы с цветом в 1С. Главное правило — использовать ПриЧтенииНаСервере для загрузки данных и ПередЗаписьюНаСервере для их упаковки в ХранилищеЗначения. Также важно следить за тем, чтобы данные, выбираемые через диалоги, корректно попадали в реквизиты формы. Используя эти рекомендации, вы сможете избежать проблем с «пропаданием» цвета и обеспечите стабильную работу вашего интерфейса.