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

Программист IT и автоматизация бизнеса
← На главную

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

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

Решение для управляемых форм (платформа 1С 8.2 и 8.3)

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

Настроить условное оформление можно двумя способами: интерактивно в конфигураторе или программно в коде.

Способ 1. Интерактивная настройка в конфигураторе

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

  1. Откроем форму нашей обработки или документа в конфигураторе.
  2. В окне свойств формы перейдем на вкладку «Условное оформление» (кнопка «Открыть» напротив одноименного свойства).
  3. Добавим новый элемент оформления и настроим его свойства:
    • Оформление: Выберем свойство ЦветФона и зададим нужный цвет (например, черный).
    • Условие: Зададим логическое выражение. Например, поле таблицы Объект.ТабличнаяЧасть1.Реквизит2 Равно "Х".
    • Оформляемые поля: Укажем конкретные колонки таблицы, которые должны окрашиваться при выполнении условия. Если оставить это поле пустым, будет закрашена вся строка целиком.

Способ 2. Программная настройка на сервере

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // 1. Создаем новый элемент условного оформления
    ЭлементУО = УсловноеОформление.Элементы.Добавить();
    
    // 2. Указываем оформление (задаем черный цвет фона)
    ЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(0, 0, 0));
    
    // 3. Задаем условие: Реквизит2 равен "Х"
    ЭлементОтбора = ЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.ТабличнаяЧасть1.Реквизит2");
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
    ЭлементОтбора.ПравоеЗначение = "Х";
    ЭлементОтбора.Использование = Истина;
    
    // 4. Определяем оформляемое поле (колонку таблицы)
    ПолеОформления = ЭлементУО.Поля.Элементы.Добавить();
    ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ТабличнаяЧасть1Реквизит2");
    ПолеОформления.Использование = Истина;

КонецПроцедуры

Важная рекомендация по оптимизации: Если вы настраиваете раскраску для таблицы, связанной с динамическим списком, не используйте условное оформление всей формы. Гораздо эффективнее применить оформление непосредственно к настройкам динамического списка через свойство Список.КомпоновщикНастроек.ФиксированныеНастройки.УсловноеОформление. Это существенно ускорит отрисовку данных при прокрутке больших списков.

Решение для обычных форм (платформа 1С 8.0, 8.1 и обычные приложения 8.2/8.3)

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

Анализ ошибки из Сообщения №9 на форуме

В процессе обсуждения на форуме был предложен следующий вариант кода:


Процедура ТабПолеПриПолученииДанных(Элемент, ОформленияСтрок)
    сч = 1;
    Для Каждого оф из ОформленияСтрок Цикл
        Если сч % 2 = 0 Тогда
            оф.Ячейки.Реквизит2.ЦветФона = Новый Цвет(0,0,0);
        КонецЕсли;
    КонецЦикла
КонецПроцедуры

Давайте выясним причину, почему данный код не будет работать корректно. Переменная сч инициализирована значением "1" перед началом цикла, однако внутри самого цикла ее значение никак не изменяется (отсутствует инкремент сч = сч + 1;). В результате условие сч % 2 = 0 всегда будет ложным, и закрашивание ячеек в шахматном порядке не произойдет.

Правильный подход к оформлению в обычных формах

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

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

Разберем по шагам правильный алгоритм оптимизированной раскраски ячеек:


Процедура ТабличноеПолеПриПолученииДанных(Элемент, ОформленияСтрок)

    // Шаг 1. Собираем ссылки на номенклатуру из видимых строк в массив
    МассивНоменклатуры = Новый Массив;
    Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
        Если ОформлениеСтроки.ДанныеСтроки <> Неопределено Тогда
            МассивНоменклатуры.Добавить(ОформлениеСтроки.ДанныеСтроки.Номенклатура);
        КонецЕсли;
    КонецЦикла;
    
    // Шаг 2. Выполняем ОДИН запрос для получения остатков по всем собранным товарам
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
        |   ТоварыНаСкладахОстатки.ВНаличииОстаток КАК Остаток
        |ИЗ
        |   РегистрНакопления.ТоварыНаСкладах.Остатки(, Номенклатура В (&МассивНоменклатуры)) КАК ТоварыНаСкладахОстатки";
        
    Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);
    
    ТаблицаОстатков = Запрос.Выполнить().Выгрузить();
    
    // Шаг 3. Заполняем Соответствие для быстрого поиска данных в памяти
    ОстаткиТоваров = Новый Соответствие;
    Для Каждого СтрокаОстатков Из ТаблицаОстатков Цикл
        ОстаткиТоваров.Вставить(СтрокаОстатков.Номенклатура, СтрокаОстатков.Остаток);
    КонецЦикла;
    
    // Шаг 4. Окрашиваем ячейки на основе полученных из Соответствия данных
    Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
        
        ДанныеСтроки = ОформлениеСтроки.ДанныеСтроки;
        Если ДанныеСтроки = Неопределено Тогда
            Продолжить;
        КонецЕсли;
        
        // Получаем остаток товара без обращения к СУБД в цикле
        ТекущийОстаток = ОстаткиТоваров[ДанныеСтроки.Номенклатура];
        
        Если ТекущийОстаток = Неопределено Или ТекущийОстаток <= 0 Тогда
            // Если товара нет на складе, красим фон ячейки количества в красный цвет
            ОформлениеСтроки.Ячейки.Количество.ЦветФона = Новый Цвет(255, 200, 200);
            ОформлениеСтроки.Ячейки.Количество.ЦветТекста = Новый Цвет(150, 0, 0);
        Иначе
            // Обычное оформление для доступного товара
            ОформлениеСтроки.Ячейки.Количество.ЦветФона = Новый Цвет(200, 255, 200); // Светло-зеленый
        КонецЕсли;
        
    КонецЦикла;

КонецПроцедуры

Дополнительные возможности визуального выделения

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

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

← На главную