Мы часто сталкиваемся с задачей динамической раскраски ячеек табличной части (ТЧ) управляемой формы 1С. Такая необходимость возникает, когда требуется визуально выделить строки или конкретные ячейки в зависимости от их статуса, приоритета, категории или других параметров, хранящихся в связанных справочниках. В данной статье мы рассмотрим, как реализовать подобное решение, используя механизм условного оформления 1С, когда требуемый цвет хранится в реквизите справочника с типом «ХранилищеЗначения».
В управляемых формах 1С стандартный и наиболее рекомендуемый способ динамической раскраски элементов формы — это использование Условного оформления. В отличие от обычных форм, где разработчики могли работать с событием ПриПолученииДанных табличных частей для непосредственного изменения свойств ячеек, в управляемых формах мы оперируем коллекцией УсловноеОформление.Элементы, которую можно настраивать как интерактивно в конфигураторе, так и программно.
Программное формирование условного оформления обычно выполняется в обработчике события формы ПриСозданииНаСервере. Это гарантирует, что оформление будет применено при первом открытии формы и загрузке данных. Этот метод позволяет нам динамически создавать правила оформления, исходя из данных, которые недоступны на этапе конфигурирования (например, цвета, хранящиеся в базе данных).
Давайте разберем по шагам, как мы будем настраивать условное оформление для раскраски ячеек табличной части в зависимости от статуса задачи и цвета, полученного из справочника.
Получение данных о статусах и цветах из справочника.
Первым делом нам необходимо получить из справочника все статусы, которые могут быть назначены задачам, и соответствующие им цвета. Для этого мы выполним запрос к справочнику, например, `Справочник.СтатусыЗадач`.
Мы используем обработчик события формы ПриСозданииНаСервере, чтобы выполнить этот запрос при инициализации формы. Это серверный обработчик, что позволяет нам без проблем обращаться к данным базы.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Очищаем существующие элементы условного оформления, чтобы избежать дублирования
// при повторном открытии формы. Это особенно важно, если форма может
// открываться несколько раз в течение сеанса и не перезагружаться полностью.
// Если элементы условного оформления всегда статичны и добавляются только один раз,
// эту строку можно закомментировать.
// УсловноеОформление.Элементы.Очистить();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СтатусыЗадач.Ссылка КАК Ссылка,
| СтатусыЗадач.Цвет КАК Цвет
|ИЗ
| Справочник.СтатусыЗадач КАК СтатусыЗадач
|ГДЕ
| НЕ СтатусыЗадач.ПометкаУдаления";
Выборка = Запрос.Выполнить().Выбрать();
// ... далее продолжим работу с выборкой ...
КонецПроцедуры
В этом запросе мы выбираем `Ссылка` на каждый статус и его реквизит `Цвет`. Обратите внимание, что реквизит `Цвет` в нашем случае имеет тип `ХранилищеЗначения`. Это важный аспект, к которому мы вернемся при установке цвета в оформлении.
Динамическое создание элементов условного оформления.
Для каждого статуса, полученного из запроса, мы будем создавать отдельный элемент условного оформления. Каждый такой элемент будет содержать свое уникальное условие (отбор по конкретному статусу) и правило оформления (например, цвет фона для соответствующей ячейки).
// ... продолжение процедуры ПриСозданииНаСервере
Пока Выборка.Следующий() Цикл
// 1. Создаем новый элемент условного оформления
// Мы добавляем новый элемент в коллекцию УсловноеОформление.Элементы,
// которая является реквизитом формы и управляет всеми правилами оформления.
ЭлементУсловногоОформления = УсловноеОформление.Элементы.Добавить();
// 2. Указываем поля, которые будут оформляться
// Мы хотим раскрасить конкретную ячейку в табличной части,
// соответствующую полю СтатусЗадачи. Для этого мы создаем ПолеЭлемента
// и привязываем его к имени поля данных, которое отображается в колонке табличной части.
ПолеЭлемента = ЭлементУсловногоОформления.Поля.Элементы.Добавить();
// Важно: здесь указывается имя поля данных, которое является источником для колонки.
// Например, если в вашей табличной части есть колонка, отображающая поле "СтатусЗадачи",
// то указываем "СтатусЗадачи". Это имя поля из источника данных табличной части.
ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных("СтатусЗадачи"); // Имя поля данных в ТЧ
ПолеЭлемента.Использование = Истина; // Обязательно устанавливаем Истина для использования поля
// Если бы вы хотели раскрасить всю строку табличной части,
// тогда ПолеЭлемента.Поле следовало бы указать как:
// ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(Элементы.ИмяВашейТабличнойЧасти.Имя);
// Например, если имя элемента табличной части на форме - "ТаблицаЗадач".
// В нашем случае, так как задача — раскрасить КОНКРЕТНУЮ ЯЧЕЙКУ,
// мы используем имя поля данных, привязанного к этой ячейке.
// 3. Задаем условие отбора для текущего элемента оформления
// Оформление будет применяться только в том случае, если значение поля "СтатусЗадачи"
// в текущей строке табличной части равно ссылке на текущий статус из нашей выборки.
ОтборЭлемента = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СтатусЗадачи"); // Поле ТЧ, по которому идет отбор
ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно; // Указываем, что сравнение будет на равенство
ОтборЭлемента.ПравоеЗначение = Выборка.Ссылка; // Значение, с которым сравниваем (ссылка на статус)
ОтборЭлемента.Использование = Истина; // Обязательно устанавливаем Истина для использования отбора
// 4. Устанавливаем параметры оформления
// Здесь мы применяем цвет фона к ячейке. Поскольку реквизит "Цвет"
// имеет тип "ХранилищеЗначения", нам необходимо извлечь фактическое значение цвета
// из хранилища с помощью метода Получить().
ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", Выборка.Цвет.Получить());
КонецЦикла;
// ... конец процедуры ПриСозданииНаСервере
Давайте более подробно рассмотрим объекты и методы, которые мы используем для настройки условного оформления:
УсловноеОформление.Элементы.Добавить():
Этот метод коллекции УсловноеОформление.Элементы создает новый объект ЭлементУсловногоОформления. Каждый такой объект представляет собой отдельное правило оформления, включающее в себя условия и параметры внешнего вида. Коллекция УсловноеОформление.Элементы доступна через реквизит формы УсловноеОформление.
ПолеКомпоновкиДанных("СтатусЗадачи"):
Мы указываем, что оформление будет применяться к полю данных `СтатусЗадачи`. Крайне важно, чтобы это имя соответствовало имени поля в источнике данных табличной части, к которому привязана колонка, или непосредственно имени самой колонки, если оно совпадает с именем поля. Если вы хотите оформить всю строку табличной части, то вместо имени поля данных укажите Новый ПолеКомпоновкиДанных(Элементы.ИмяВашейТабличнойЧасти.Имя), где ИмяВашейТабличнойЧасти - это имя элемента табличной части на вашей форме (например, `Элементы.ТаблицаЗадач.Имя`).
ЭлементОтбораКомпоновкиДанных:
Этот объект используется для определения условия, при котором сработает наше оформление. Мы создаем элемент отбора, который сравнивает `ЛевоеЗначение` (поле `СтатусЗадачи` в каждой строке табличной части) с `ПравоеЗначение` (ссылка на текущий статус из нашей выборки). Таким образом, оформление будет применено только к тем строкам (или ячейкам), где статус совпадает с текущим статусом из справочника.
ВидСравненияКомпоновкиДанных.Равно:
Мы указываем, что для сравнения `ЛевогоЗначения` и `ПравогоЗначения` используется точное совпадение (равенство).
Выборка.Цвет.Получить():
Это критически важный момент в нашем решении. Поскольку реквизит `Цвет` имеет тип `ХранилищеЗначения`, он хранит не сам объект цвета, а "указатель" на него или сериализованное представление. Чтобы получить фактическое значение цвета (обычно это объект типа `Цвет` или `СтандартныйЦвет`), которое может быть использовано механизмом условного оформления, необходимо вызвать метод Получить(). Без этого метода вы пытались бы передать в оформление объект типа `ХранилищеЗначения`, что привело бы к ошибке, так как система ожидает именно объект `Цвет`.
Применяя все вышесказанное, полный код для процедуры ПриСозданииНаСервере вашей формы будет выглядеть так:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Если необходимо полностью переопределять оформление при каждом открытии формы,
// раскомментируйте следующую строку. Это гарантирует, что старые правила
// оформления не будут накапливаться или конфликтовать с новыми.
// Если элементы условного оформления статичны и добавляются только один раз
// при первом открытии формы в сеансе, эта строка может быть необязательна.
// УсловноеОформление.Элементы.Очистить();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СтатусыЗадач.Ссылка КАК Ссылка,
| СтатусыЗадач.Цвет КАК Цвет
|ИЗ
| Справочник.СтатусыЗадач КАК СтатусыЗадач
|ГДЕ
| НЕ СтатусыЗадач.ПометкаУдаления";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Создаем новый элемент условного оформления для каждого статуса
ЭлементУсловногоОформления = УсловноеОформление.Элементы.Добавить();
// Указываем, какое поле в табличной части будет оформляться.
// Здесь мы ориентируемся на имя поля данных "СтатусЗадачи",
// которое, как предполагается, отображается в одной из колонок вашей ТЧ.
ПолеЭлемента = ЭлементУсловногоОформления.Поля.Элементы.Добавить();
ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных("СтатусЗадачи"); // Имя поля данных
ПолеЭлемента.Использование = Истина;
// Задаем условие отбора: оформление применяется, если значение поля "СтатусЗадачи"
// в строке ТЧ совпадает с текущей ссылкой на статус из выборки.
ОтборЭлемента = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СтатусЗадачи");
ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ОтборЭлемента.ПравоеЗначение = Выборка.Ссылка;
ОтборЭлемента.Использование = Истина;
// Применяем цвет фона к указанному полю.
// Обязательно используем Получить() для извлечения объекта цвета из ХранилищаЗначения.
ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", Выборка.Цвет.Получить());
КонецЦикла;
КонецПроцедуры
При реализации такого решения мы рекомендуем учитывать несколько важных моментов, чтобы обеспечить его надежность и оптимальную производительность:
Очистка условного оформления:
Если ваша форма может открываться несколько раз в течение одного сеанса пользователя, или если правила условного оформления могут динамически изменяться (что реже для данного сценария), то перед добавлением новых элементов оформления рекомендуется очищать существующие. Используйте метод УсловноеОформление.Элементы.Очистить(). Это предотвратит дублирование правил оформления и потенциальные конфликты между ними. Если же `ПриСозданииНаСервере` вызывается единожды для инициализации, а форма остается открытой, очистка может быть не нужна.
Производительность:
Для большинства типовых задач, где количество статусов не превышает нескольких десятков или сотен, создание отдельных элементов условного оформления для каждого статуса является вполне приемлемым с точки зрения производительности. Загрузка формы может незначительно увеличиться при большом количестве правил, но в большинстве случаев это не критично. Если же у вас тысячи уникальных статусов с уникальными цветами (что крайне редко), возможно, потребуется рассмотреть более сложные, но менее типовые методы, такие как использование динамически генерируемых картинок 1x1 пиксель, если это позволяет контекст (например, в полях типа "Картинка") или применение специализированных механизмов в отчетах на СКД. Однако для типовой задачи, предложенный метод остается наиболее подходящим и простым в реализации.
Оформление всей строки vs. конкретной ячейки:
Мы сосредоточились на раскраске конкретной ячейки. Если же вам требуется раскрасить всю строку табличной части, а не только одну ячейку, то в строке, где мы указываем оформляемое поле:
ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных("СтатусЗадачи");
вам следует указать имя элемента табличной части на форме, а не имя поля данных. Например, если ваша табличная часть называется ТаблицаЗадач, то код будет таким:
ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(Элементы.ТаблицаЗадач.Имя);
В этом случае при совпадении статуса будет окрашена вся строка, связанная с этим статусом.
Используя программное условное оформление в 1С, мы можем гибко и эффективно раскрашивать ячейки табличных частей управляемых форм, опираясь на данные из связанных справочников. Мы выяснили, что ключ к успеху лежит в правильном формировании элементов условного оформления: определении поля для оформления, задании точного условия отбора и, что особенно важно при работе с типом `ХранилищеЗначения`, корректном извлечении значения цвета с помощью метода Получить(). Этот подход является стандартным, достаточно производительным и хорошо поддерживаемым платформой 1С:Предприятие 8.3.