Как программно установить цвет ячейки из поля выбора в 1С:Предприятие 8

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

При разработке интерфейсов на управляемых формах в 1С часто возникает задача сделать форму максимально интерактивной и интуитивно понятной для пользователя. Одним из таких сценариев является визуализация выбора цвета: когда пользователь выбирает определенный цвет в колонке таблицы, фон этой же ячейки (или всей строки) должен мгновенно окраситься в выбранный цвет.

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

Выясним причину: почему стандартный подход не работает?

Рассмотрим типичный код, который часто пытаются использовать начинающие (и не только) разработчики в попытке привязать цвет оформления к значению в колонке таблицы:


// Этот код НЕ будет работать так, как ожидается:
Элемент_УО = УсловноеОформление.Элементы.Добавить();
Элемент_УО.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый ПолеКомпоновкиДанных("Объект.ТаблицаДанных.Цвет"));

Этот код успешно компилируется, платформа не выдает никаких предупреждений или исключений в процессе работы, однако ячейки таблицы остаются неокрашенными. Почему так происходит?

Дело в архитектурном ограничении механизма компоновки данных и условного оформления 1С. Параметры оформления (такие как ЦветФона, ЦветТекста, Шрифт, ВыделятьЖирным и др.) ожидают на вход конкретное, статическое значение соответствующего типа (в данном случае — объект типа Цвет).

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

Для решения этой задачи нам потребуется применить обходные пути. Ниже мы разберем два наиболее эффективных решения в зависимости от типа таблицы на форме.

Решение 1: Динамическое создание правил условного оформления (для табличных частей и ТЗ)

Если ваша таблица на форме является табличной частью документа/справочника или коллекцией типа ТаблицаЗначений, оптимальным решением будет динамическая генерация правил условного оформления под каждый уникальный цвет, выбранный пользователями.

Суть метода заключается в том, что вместо одного универсального (но неработающего) правила мы будем создавать множество правил — по одному на каждый уникальный цвет, который в данный момент присутствует в нашей таблице. Разберем этот процесс по шагам.

Шаг 1. Создание серверной процедуры обновления оформления

Нам потребуется написать процедуру на сервере, которая будет анализировать данные в таблице, собирать уникальные цвета и генерировать под них правила УО. Чтобы при повторных вызовах процедуры не затереть статичные настройки условного оформления, созданные в конфигураторе, мы будем помечать наши динамические правила специальным уникальным текстом в свойстве Представление.

Рассмотрим подробнее программную реализацию этой процедуры:


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

Шаг 2. Подключение обработчиков событий формы

Чтобы условное оформление работало корректно в процессе взаимодействия пользователя с интерфейсом, нам необходимо вызывать созданную процедуру обновления в двух ключевых точках:

  1. При открытии формы (чтобы раскрасить сохраненные ранее данные).
  2. При интерактивном изменении значения цвета пользователем в таблице.

Посмотрим на пример подключения этих обработчиков событий:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	// Инициализируем оформление при открытии формы
	ОбновитьДинамическоеУсловноеОформлениеНаСервере();
КонецПроцедуры

&НаКлиенте
Процедура ТаблицаДанныхЦветПриИзменении(Элемент)
	// Сразу реагируем на выбор нового цвета пользователем
	ОбновитьДинамическоеУсловноеОформлениеНаСервере();
КонецПроцедуры

Преимущества данного метода: Подход полностью универсален и работает на любых версиях платформы 1С 8.3, поддерживающих управляемые формы. Оформление применяется стандартными механизмами платформы.

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

Решение 2: Использование события "ОбработкаОформленияДанных" (для Динамических списков)

Если ваша таблица на форме является не табличной частью, а Динамическим списком, то начиная с версии платформы 1С:Предприятие 8.3.20 у нас появился гораздо более элегантный, производительный и современный инструмент.

Разработчики платформы добавили для таблиц динамических списков клиентское событие ОбработкаОформленияДанных. Оно срабатывает непосредственно при выводе строк на экран монитора пользователя. Это позволяет обойтись без тяжеловесных серверных вызовов и настраивать цвета «на лету» прямо на стороне клиента.

Проанализируем ситуацию и посмотрим, как выглядит программная реализация этого механизма в модуле управляемой формы:


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

Важное примечание: Обратите внимание, что в событии ОбработкаОформленияДанных мы работаем исключительно на клиенте. Этот метод работает невероятно быстро, поскольку платформа передает в процедуру только видимую часть данных (порцию строк, которая отображается на экране), исключая необходимость перебирать всю базу данных.

Анализ частых ошибок при работе с программным оформлением

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

  1. Неверный путь к данным в ПолеКомпоновкиДанных. Помните, что при настройке отбора (левое значение) путь к полю должен указываться с учетом структуры данных формы (например, "Объект.ТаблицаДанных.Цвет"). В то же время, при указании оформляемого поля в коллекции Поля условного оформления, имя поля должно соответствовать имени колонки в элементе формы таблицы (например, "ТаблицаДанныхЦвет").
  2. Забытое свойство Использование. Каждый создаваемый элемент условного оформления, элементы отбора и оформляемые поля обязательно должны иметь свойство Использование = Истина. Если упустить эту деталь, правило просто не применится.
  3. Полная очистка условного оформления. Использование метода УсловноеОформление.Элементы.Очистить() крайне нежелательно, если на форме уже настроены другие статические правила оформления в конфигураторе. Всегда используйте фильтрацию по свойству Представление, как показано в Решении 1.

Таким образом, мы детально изучили, почему стандартная попытка передать поле компоновки в параметры оформления терпит неудачу, и освоили два мощных профессиональных инструмента для динамической раскраски интерфейсов 1С в зависимости от выбора пользователя.

← На главную