Как программно настроить раскраску строк в табличной части документа?

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

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

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

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

Проанализируем фрагмент кода, с которого обычно начинаются попытки раскрасить строки:


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

    УсОф = ЭтаФорма.УсловноеОформление;   
    ЭлОформления = УсОф.Элементы.Добавить();    
    ЭлОтбора = ЭлОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Объект.Товары.Номенклатура.ПринадлежностьФраншизе");
    ЭлОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
    ЭлОтбора.Использование  = Истина;
    ЭлОтбора.ПравоеЗначение = Перечисления.ПринадлежностьФраншизе.Заказной;
    
    Элемен = ЭлОформления.Оформление.Элементы[1];
    Элемен.Использование = Истина;
    Элемен.Значение = Новый Цвет(167, 0, 0);

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

В приведенном коде скрыты сразу три критические проблемы, из-за которых раскраска не работает:

  1. Не указаны оформляемые поля. Правило условного оформления обязательно должно знать, к какой именно визуальной части формы его применять. Если коллекция ЭлОформления.Поля пуста, платформа просто игнорирует созданное правило.
  2. Обращение через точку к реквизитам ссылочных полей. Данные табличной части документа в управляемой форме хранятся в объекте ДанныеФормыКоллекция. Это клиентский кэш данных, а не динамический список с прямым запросом к базе данных. Платформа не умеет «разыменовывать» реквизиты ссылок на лету в условном оформлении. Путь вида Объект.Товары.Номенклатура.ПринадлежностьФраншизе работать не будет.
  3. Установка параметров оформления по числовому индексу. Обращение вида Элементы[1] крайне ненадежно: порядок следования параметров оформления в коллекции платформы не фиксирован и зависит от версии платформы или контекста. Вместо цвета фона можно случайно включить признак шрифта или доступности.

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

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

Разберем по шагам, как это реализовать:

  1. Добавим реквизит ПринадлежностьФраншизе непосредственно в табличную часть документа (или создадим реквизит формы того же типа в ветке Объект.Товары).
  2. В событии элемента формы ТоварыНоменклатураПриИзменении настроим заполнение этого реквизита при выборе номенклатуры.
  3. В процедуре ПриСозданииНаСервере опишем условное оформление с обязательным указанием оформляемых полей.

Посмотрим на пример кода в модуле формы:


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

    // Создаем элемент условного оформления
    ЭлОформления = УсловноеОформление.Элементы.Добавить();

    // 1. Указываем оформляемые поля (всю строку таблицы формы)
    ПолеЭлемента = ЭлОформления.Поля.Элементы.Добавить();
    ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(Элементы.Товары.Имя);

    // 2. Настраиваем отбор по прямому реквизиту табличной части
    ЭлОтбора = ЭлОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Объект.Товары.ПринадлежностьФраншизе");
    ЭлОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
    ЭлОтбора.ПравоеЗначение = Перечисления.ПринадлежностьФраншизе.Заказной;
    ЭлОтбора.Использование  = Истина;

    // 3. Устанавливаем параметры оформления по их имени
    ЭлОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(255, 200, 200));

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

Обратите внимание: чтобы закрасить строку целиком, в ПолеКомпоновкиДанных передается имя элемента таблицы формы (Элементы.Товары.Имя). Если требуется раскрасить только конкретную колонку, в коллекцию Поля добавляется имя поля этой колонки, например Элементы.ТоварыНоменклатура.Имя.

Способ 2. Использование отбора со списком значений

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

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

Посмотрим, как выглядит программная настройка такого оформления:


&НаСервере
Процедура ОбновитьОформлениеТоваровНаСервере()

    // Находим или создаем правило оформления
    ЭлОформления = Неопределено;
    Для Каждого Элемент Из УсловноеОформление.Элементы Цикл
        Если Элемент.Представление = "ОформлениеЗаказныхТоваров" Тогда
            ЭлОформления = Элемент;
            Прервать;
        КонецЕсли;
    КонецЦикла;

    Если ЭлОформления = Неопределено Тогда
        ЭлОформления = УсловноеОформление.Элементы.Добавить();
        ЭлОформления.Представление = "ОформлениеЗаказныхТоваров";

        // Добавляем оформляемое поле
        ПолеТаблицы = ЭлОформления.Поля.Элементы.Добавить();
        ПолеТаблицы.Поле = Новый ПолеКомпоновкиДанных(Элементы.Товары.Имя);

        // Задаем цвет фона
        ЭлОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(200, 255, 200));
        
        // Создаем элемент отбора
        ЭлОтбора = ЭлОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Номенклатура");
        ЭлОтбора.ВидСравнения  = ВидСравненияКомпоновкиДанных.ВСписке;
        ЭлОтбора.Использование = Истина;
    Иначе
        ЭлОтбора = ЭлОформления.Отбор.Элементы[0];
    КонецЕсли;

    // Заполняем список номенклатуры, удовлетворяющей условию
    СЗНоменклатуры = Новый СписокЗначений;
    Для Каждого СтрТЧ Из Объект.Товары Цикл
        Если ЗначениеЗаполнено(СтрТЧ.Номенклатура) 
            И СтрТЧ.Номенклатура.ПринадлежностьФраншизе = Перечисления.ПринадлежностьФраншизе.Заказной Тогда
            СЗНоменклатуры.Добавить(СтрТЧ.Номенклатура);
        КонецЕсли;
    КонецЦикла;

    ЭлОтбора.ПравоеЗначение = СЗНоменклатуры;

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

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ОбновитьОформлениеТоваровНаСервере();
КонецПроцедуры

&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
    ОбновитьОформлениеТоваровНаСервере();
КонецПроцедуры

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

← На главную