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

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

При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с ограничением: механизм Условного оформления для табличных частей (ТЧ) на управляемых формах не поддерживает обращение к реквизитам через точку. Если для Динамического списка мы можем легко прописать условие Список.Номенклатура.дор_Выгодно = Истина, то в обычной таблице документа такая конструкция работать не будет. Платформа просто не увидит значение вложенного реквизита, так как данные ТЧ — это коллекция, загруженная в память клиента, и она не подтягивает связанные данные автоматически для отрисовки оформления.

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

Почему стандартный подход не работает?

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


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

Проблема в том, что поле Номенклатура.дор_Выгодно отсутствует в составе данных формы ДанныеФормыКоллекция. Для того чтобы условное оформление сработало, значение, по которому идет отбор, должно физически присутствовать в колонках таблицы на форме.

Решение 1: Программное добавление «технических» реквизитов

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

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


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

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


&НаКлиенте
Процедура ОбновитьРеквизитыРаскраски(Форма, ТаблицаТоваров, ИмяПоляНоменклатуры) Экспорт
    МассивНоменклатуры = Новый Массив;
    Для Каждого СтрокаТЧ Из ТаблицаТоваров Цикл
        МассивНоменклатуры.Добавить(СтрокаТЧ[ИмяПоляНоменклатуры]);
    КонецЦикла;
    
    // Получаем значения реквизитов одним запросом на сервере
    ДанныеНоменклатуры = ПолучитьДанныеНоменклатурыСервер(МассивНоменклатуры);
    
    Для Каждого СтрокаТЧ Из ТаблицаТоваров Цикл
        ТекНоменклатура = СтрокаТЧ[ИмяПоляНоменклатуры];
        Если ДанныеНоменклатуры.Свойство(ТекНоменклатура) Тогда
            СтрокаТЧ.дор_Выгодно = ДанныеНоменклатуры[ТекНоменклатура].дор_Выгодно;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Важно: Не забудьте вызвать процедуру обновления в обработчиках ПриОткрытии, ПриИзменении номенклатуры и после завершения подбора товаров.

Решение 2: Использование отбора «В списке» (Динамический массив)

Если вы не хотите менять структуру реквизитов формы (например, форма слишком сложная или заблокирована расширением), можно использовать другой подход. Вместо проверки конкретного булевого флажка в строке, мы будем проверять, входит ли Номенклатура текущей строки в список «выгодных» товаров.

Рассмотрим логику этого метода:

  1. При создании формы на сервере мы формируем массив ссылок номенклатуры, у которой признак дор_Выгодно равен Истина.
  2. В настройках Условного оформления устанавливаем вид сравнения ВидСравненияКомпоновкиДанных.ВСписке.
  3. В качестве правого значения передаем наш сформированный массив.

Посмотрим на пример реализации:


// На сервере
МассивВыгодных = Справочники.Номенклатура.Выбрать(Новый Структура("дор_Выгодно", Истина)); // Условно

ЭлементОформления = УсловноеОформление.Элементы.Добавить();
// ... настройка оформления (цвет) ...

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

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

Минусы метода: Если в базе десятки тысяч «выгодных» товаров, передача такого массива на клиент при каждом открытии формы может замедлить работу. Также список нужно обновлять, если реквизиты номенклатуры изменились в процессе работы пользователя.

Оптимизация и лучшие практики

Проанализируем советы опытных разработчиков для повышения производительности:

  1. Кэширование: Чтобы постоянно не бегать на сервер за признаками номенклатуры, используйте Соответствие или Структуру в модуле формы для временного хранения признаков.
  2. События обновления: В типовых конфигурациях (например, Розница 3.0) часто существуют общие процедуры пересчета итогов или обновления данных документа. Подключайтесь к ним (через механизмы &После в расширениях), чтобы гарантировать обновление раскраски при любых программных изменениях ТЧ.
  3. Минимизация колонок: Если вам нужно раскрашивать строки по пяти разным признакам, не обязательно добавлять пять колонок Булево. Можно добавить одну колонку ЦветСтроки (тип Число) и заполнять её на сервере кодами (1 — акция, 2 — новинка, 3 — дефицит). В Условном оформлении достаточно будет настроить правила по этой одной колонке.

Выводы

Мы выяснили, что прямого способа использовать Номенклатура.Реквизит в условном оформлении табличных частей не существует из-за особенностей клиент-серверной архитектуры 1С. Оптимальным решением является программное добавление колонки в реквизиты формы с последующим пакетным заполнением данных. Это обеспечивает высокую скорость отрисовки интерфейса и корректную работу фильтров оформления.

← На главную