Как настроить условное оформление ячейки табличной части по реквизиту справочника в 1С?

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

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

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

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

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

Ошибка 1. Попытка обхода строк табличной части в цикле.

Автор пытается настроить условное оформление, перебирая строки таблицы циклом Для СтрокаТЧ = 1 По Объект.Табель.Количество(). Это в корне неверно. Механизм условного оформления (УО) на управляемой форме работает по принципу декларативного описания правил. Мы задаем правила один раз для всей таблицы (структуры данных), а платформа сама применяет их «на лету» к каждой отрисовываемой на экране строке. Попытка программно генерировать элементы условного оформления под каждую физическую строку не только не сработает из-за невозможности адресации конкретного индекса строки в путях к данным, но и приведет к колоссальному падению производительности интерфейса.

Ошибка 2. Обращение к реквизитам через точку в условиях отбора.

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


Способ 1. Использование вспомогательных реквизитов (Рекомендуемый)

Самый надежный, быстрый и производительный способ обойти ограничение платформы — «приземлить» необходимые данные непосредственно в саму табличную часть. Если платформа не умеет смотреть сквозь ссылку на реквизит справочника, мы должны физически предоставить ей готовое значение в строке таблицы.

Рассмотрим этот метод на практическом примере. Допустим, у нас есть табличная часть Табель с колонками Д1, Д2 ... Д31 (тип СправочникСсылка.ВидыИспользованияРабочегоВремени). Нам нужно раскрашивать эти ячейки в зависимости от числового реквизита СоответствиеЧасов, который хранится внутри этого справочника.

Шаг 1. Создание вспомогательных колонок.

Добавим в табличную часть (или непосредственно в реквизиты формы, если таблица создается программно) вспомогательные скрытые колонки для хранения показателей. Назовем их по шаблону: Д1_СоответствиеЧасов, Д2_СоответствиеЧасов и так далее до 31. Тип данных — Число. На форму выносить эти колонки не обязательно, они будут играть роль буфера данных.

Шаг 2. Заполнение буферных данных при открытии формы.

При открытии формы нам необходимо один раз прочитать показатели из справочников и заполнить наши вспомогательные колонки. Чтобы избежать обращений к базе в цикле (что порождает тяжелые N+1 запросы), мы напишем один оптимальный запрос на сервере.

Разберем пример кода в обработчике события ПриСозданииНаСервере:


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

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


&НаСервере
Процедура ЗаполнитьВспомогательныеДанныеТЧ()
    
    // Собираем все уникальные ссылки из таблицы для быстрого кэширования
    ТаблицаСсылок = Новый ТаблицаЗначений;
    ТаблицаСсылок.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("СправочникСсылка.ВидыИспользованияРабочегоВремени"));
    
    Для Каждого СтрокаТЧ Из Объект.Табель Цикл
        Для День = 1 По 31 Цикл
            ЗначениеЯчейки = СтрокаТЧ["Д" + День];
            Если ЗначениеЗаполнено(ЗначениеЯчейки) Тогда
                НоваяСтрока = ТаблицаСсылок.Добавить();
                НоваяСтрока.Ссылка = ЗначениеЯчейки;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
    ТаблицаСсылок.Свернуть("Ссылка");
    
    Если ТаблицаСсылок.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    // Запросом получаем показатели для всех найденных ссылок
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ВидыВремени.Ссылка КАК Ссылка,
        |   ВидыВремени.СоответствиеЧасов КАК СоответствиеЧасов
        |ИЗ
        |   Справочник.ВидыИспользованияРабочегоВремени КАК ВидыВремени
        |ГДЕ
        |   ВидыВремени.Ссылка В(&МассивСсылок)";
    
    Запрос.УстановитьПараметр("МассивСсылок", ТаблицаСсылок.ВыгрузитьКолонку("Ссылка"));
    РезультатЗапроса = Запрос.Выполнить().Выгрузить();
    
    // Быстро заполняем вспомогательные реквизиты в ТЧ с использованием соответствия
    СоответствиеПоказателей = Новый Соответствие;
    Для Каждого СтрокаРез Из РезультатЗапроса Цикл
        СоответствиеПоказателей.Вставить(СтрокаРез.Ссылка, СтрокаРез.СоответствиеЧасов);
    КонецЦикла;
    
    Для Каждого СтрокаТЧ Из Объект.Табель Цикл
        Для День = 1 По 31 Цикл
            ТекущаяСсылка = СтрокаТЧ["Д" + День];
            Если ЗначениеЗаполнено(ТекущаяСсылка) Тогда
                Показатель = СоответствиеПоказателей.Получить(ТекущаяСсылка);
                СтрокаТЧ["Д" + День + "_СоответствиеЧасов"] = ?(Показатель = Неопределено, 0, Показатель);
            Иначе
                СтрокаТЧ["Д" + День + "_СоответствиеЧасов"] = 0;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
КонецПроцедуры

Шаг 3. Поддержание актуальности при изменении ячейки.

Когда пользователь интерактивно меняет значение в ячейке, нам нужно оперативно обновлять буферную колонку. Для этого для каждой колонки таблицы Д1 ... Д31 назначим один общий обработчик события ПриИзменении. Выясним имя изменившейся колонки программно и перезапишем показатель:


&НаКлиенте
Процедура ТабельДеньПриИзменении(Элемент)
    
    СтрокаТЧ = Элементы.Табель.ТекущиеДанные;
    Если СтрокаТЧ = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Определяем имя колонки, которую изменил пользователь (например, "ТабельД1")
    ИмяЭлемента = Элемент.Имя;
    ИмяКолонкиДанных = Сред(ИмяЭлемента, 7); // Получаем "Д1"
    
    ТекущееЗначение = СтрокаТЧ[ИмяКолонкиДанных];
    
    // Получаем показатель из базы данных на сервере и пишем во вспомогательный реквизит
    Если ЗначениеЗаполнено(ТекущееЗначение) Тогда
        Показатель = ПолучитьПоказательСправочника(ТекущееЗначение);
        СтрокаТЧ[ИмяКолонкиДанных + "_СоответствиеЧасов"] = Показатель;
    Else
        СтрокаТЧ[ИмяКолонкиДанных + "_СоответствиеЧасов"] = 0;
    КонецЕсли;
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьПоказательСправочника(Ссылка)
    Возврат Ссылка.СоответствиеЧасов;
КонецФункции

Шаг 4. Настройка Условного Оформления.

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


&НаСервере
Процедура НастроитьУсловноеОформлениеФормы()
    
    // Очищаем старое оформление во избежание дублирования
    УсловноеОформление.Элементы.Очистить();
    
    Для ДеньОформления = 1 По 31 Цикл
        
        НовыйЭлементУО = УсловноеОформление.Элементы.Добавить();
        
        // 1. Указываем оформляемое поле (визуальный элемент на форме)
        ОформляемоеПоле = НовыйЭлементУО.Поля.Элементы.Добавить();
        ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("ТабельД" + ДеньОформления);
        ОформляемоеПоле.Использование = Истина;
        
        // 2. Настраиваем отбор по вспомогательному реквизиту нашей ТЧ
        ЭлементОтбора = НовыйЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Табель.Д" + ДеньОформления + "_СоответствиеЧасов");
        ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Больше;
        ЭлементОтбора.ПравоеЗначение = 0;
        ЭлементОтбора.Использование = Истина;
        
        // 3. Задаем параметры оформления (например, приятный зеленый цвет фона)
        НовыйЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(155, 255, 63));
        
    КонецЦикла;
    
КонецПроцедуры

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


Способ 2. Использование отбора «В Списке» (Без изменения структуры ТЧ)

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

Суть метода заключается в том, чтобы выбрать из базы данных все элементы справочника, которые соответствуют нашему условию (например, у которых СоответствиеЧасов > 0), поместить их в массив или список значений, а затем настроить условное оформление с видом сравнения В Списке.

Рассмотрим реализацию этого метода на сервере:


&НаСервере
Процедура НастроитьОформлениеЧерезСписок()
    
    УсловноеОформление.Элементы.Очистить();
    
    // 1. Запросом выбираем подходящие элементы из базы данных
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ВидыВремени.Ссылка КАК Ссылка
        |ИЗ
        |   Справочник.ВидыИспользованияРабочегоВремени КАК ВидыВремени
        |ГДЕ
        |   ВидыВремени.СоответствиеЧасов > 0";
    
    СписокПодходящихСсылок = Новый СписокЗначений;
    СписокПодходящихСсылок.ЗагрузитьЗначения(Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка"));
    
    // Если подходящих элементов нет, оформление настраивать бессмысленно
    Если СписокПодходящихСсылок.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    // 2. Настраиваем условное оформление для каждого дня
    Для ДеньОформления = 1 По 31 Цикл
        
        НовыйЭлементУО = УсловноеОформление.Элементы.Добавить();
        
        // Задаем оформляемое поле
        ОформляемоеПоле = НовыйЭлементУО.Поля.Элементы.Добавить();
        ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("ТабельД" + ДеньОформления);
        ОформляемоеПоле.Использование = Истина;
        
        // Настраиваем отбор: значение в ячейке должно быть в списке выбранных нами ссылок
        ЭлементОтбора = НовыйЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Табель.Д" + ДеньОформления);
        ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
        ЭлементОтбора.ПравоеЗначение = СписокПодходящихСсылок;
        ЭлементОтбора.Использование = Истина;
        
        // Устанавливаем цвет оформления
        НовыйЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(255, 200, 200)); // Нежно-красный
        
    КонецЦикла;
    
КонецПроцедуры

Особенности и ограничения второго способа:

Несмотря на то, что данный способ избавляет от необходимости менять метаданные, у него есть два существенных недостатка, о которых важно помнить:

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

Резюмируем ключевые правила

При решении задач динамического окрашивания таблиц в 1С всегда придерживайтесь следующих правил:

← На главную