Как программно настроить условное оформление реквизита номенклатуры в табличной части документа в 1С:Бухгалтерии 3.0?

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

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

Рассмотрим типовую задачу, которая возникла у автора темы: у нас есть документ «Реализация товаров и услуг» (или любой другой документ с табличной частью), в табличной части которого отображается список номенклатуры. Мы хотим выделить определенные позиции номенклатуры, например, те, у которых есть некий «бонус», заданный в справочнике «Номенклатура».

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

Начальная попытка программной настройки условного оформления

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

мУстановитьУсловноеОформлениеНоменклатура("Объект.Товары.Номенклатура.мБонус","ТоварыНоменклатура");

И реализация самой процедуры мУстановитьУсловноеОформлениеНоменклатура выглядела следующим образом:


&НаСервере
Процедура мУстановитьУсловноеОформлениеНоменклатура(мПолеКомпановки, мПолеОформления)
    
    ЭлементОформления = УсловноеОформление.Элементы.Добавить();
    ЭлементОформления.Представление = "СозданПрограммно";
    
    //Отбор
    ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных(мПолеКомпановки);
    ЭлементОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Больше;
    ЭлементОтбора.ПравоеЗначение  = 0;
    //Оформление
    ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона",  WebЦвета.Желтый);
    //ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Текст",   "<не задана>");
    //ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветТекста",   WebЦвета.Серый);
    
    //Поле оформления
    ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
    ПолеОформления.Поле = Новый ПолеКомпоновкиДанных(мПолеОформления);
    
КонецПроцедуры

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

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

Мы сталкиваемся с распространенной ситуацией в управляемых формах 1С:Предприятия. Основная причина, по которой конструкция Объект.Товары.Номенклатура.мБонус не работает напрямую для условного оформления, заключается в особенностях загрузки данных на клиенте и в путях к полям компоновки данных. Рассмотрим подробнее:

  1. Отсутствие данных на клиенте: Когда табличная часть документа (например, Объект.Товары) отображается на форме, платформа по умолчанию не загружает все реквизиты *связанных объектов* (например, всего справочника Номенклатура) целиком на клиент. В табличной части хранится лишь ссылка на элемент справочника Номенклатура, но не весь объект со всеми его реквизитами. Соответственно, при попытке обращения Объект.Товары.Номенклатура.мБонус, платформа не может найти этот реквизит, так как полные данные Номенклатуры не были прочитаны или доступны по этому пути для механизма условного оформления. Платформа видит только ссылку на номенклатуру, а не её реквизиты.
  2. Некорректный путь к полю компоновки данных: Путь к полю мПолеКомпановки, который мы передаем в Новый ПолеКомпоновкиДанных(), должен точно соответствовать тому, как данные доступны в источнике данных формы. Если табличная часть основана на динамическом списке или запросе, то путь к реквизиту связанного объекта может отличаться от прямого доступа к реквизиту объекта. Конструкция Объект.Товары.Номенклатура.мБонус подразумевает, что поле Номенклатура в табличной части Товары является *объектом* номенклатуры, а не просто ссылкой, что в большинстве случаев не так. Для доступа к реквизитам связанных объектов обычно требуется их явное включение в запрос динамического списка или вынесение в табличную часть.

Рабочее решение: вынесение реквизита в табличную часть документа

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

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

  1. Добавляем реквизит в табличную часть:

    В режиме конфигуратора откроем документ «Реализация товаров и услуг». Перейдем на закладку «Данные» и найдем табличную часть «Товары». Добавим новый реквизит (например, с именем мБонус) к этой табличной части. Тип этого реквизита должен совпадать с типом оригинального реквизита справочника Номенклатура.мБонус (в нашем случае – Число).

  2. Заполняем реквизит программно:

    Теперь, когда у нас есть место для хранения значения бонуса прямо в строке табличной части, нам нужно обеспечить его заполнение. При создании новой строки табличной части или при изменении номенклатуры в существующей строке, мы должны программно заполнять этот новый реквизит мБонус из соответствующего реквизита справочника Номенклатура. Это можно делать, например, в обработчике события ПриИзменении поля Номенклатура табличной части формы документа.

    
    &НаСервере
    Процедура ТоварыНоменклатураПриИзмененииНаСервере(Элемент)
        СтрокаТабличнойЧасти = Элементы.Товары.ТекущиеДанные;
        Если СтрокаТабличнойЧасти.Номенклатура.Пустая() Тогда
            СтрокаТабличнойЧасти.мБонус = 0;
        Иначе
            // Читаем реквизит "мБонус" из объекта Номенклатура
            // и присваиваем его реквизиту табличной части
            СтрокаТабличнойЧасти.мБонус = СтрокаТабличнойЧасти.Номенклатура.мБонус;
        КонецЕсли;
    КонецПроцедуры
    
  3. Используем реквизит табличной части для оформления:

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

Пример кода для рабочего решения

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

мУстановитьУсловноеОформлениеНоменклатура("Объект.Товары.мБонус","ТоварыНоменклатура");

Обратите внимание, что путь к полю для отбора теперь указывает непосредственно на реквизит табличной части: Объект.Товары.мБонус. Второе поле ТоварыНоменклатура указывает на элемент формы, который мы хотим оформить – это может быть колонка табличной части, отображающая номенклатуру.

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


&НаСервере
Процедура мУстановитьУсловноеОформлениеНоменклатура(мПолеКомпановки, мПолеОформления)
    
    // Создаем новый элемент условного оформления
    ЭлементОформления = УсловноеОформление.Элементы.Добавить();
    ЭлементОформления.Представление = "ОформлениеПоБонусуНоменклатуры"; // Удобное имя для отладки
    
    // *** Настройка отбора (условия, при которых оформление будет применяться) ***
    // Создаем элемент отбора для поля компоновки данных
    ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    
    // Указываем левое значение для сравнения - наш реквизит табличной части
    // мПолеКомпановки будет содержать строку "Объект.Товары.мБонус"
    ЭлементОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных(мПолеКомпановки); 
    
    // Устанавливаем вид сравнения: "Больше"
    ЭлементОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Больше;
    
    // Указываем правое значение для сравнения - 0 (то есть, если бонус больше 0)
    ЭлементОтбора.ПравоеЗначение  = 0;
    
    // Обязательно устанавливаем использование отбора
    ЭлементОтбора.Использование = Истина;

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

    // *** Активация элемента условного оформления ***
    // Важно: установить использование самого элемента условного оформления
    ЭлементОформления.Использование = Истина;
    
КонецПроцедуры

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

Пример вызова в ПриСозданииНаСервере формы (если нет специальной процедуры):


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // ... другой код инициализации формы
    
    // Перед добавлением новых элементов, рекомендуется очистить старые, чтобы избежать дублирования
    // УсловноеОформление.Элементы.Очистить(); // Раскомментировать, если это единственная процедура УО или требуется полная очистка
    
    // Вызываем нашу процедуру для установки условного оформления
    мУстановитьУсловноеОформлениеНоменклатура("Объект.Товары.мБонус","ТоварыНоменклатура");
    
КонецПроцедуры

Альтернативные подходы и важные нюансы

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

  1. Использование невидимой колонки:

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

  2. Программное условное оформление — это правильно:

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

  3. Очистка существующих настроек:

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

  4. Настройка отбора и полей:

    Всегда внимательно проверяйте пути, указанные в Новый ПолеКомпоновкиДанных(ПутьКПолю), как для отбора (ЛевоеЗначение), так и для полей, к которым применяется оформление (ПолеОформленияЭлемент.Поле). Они должны точно соответствовать доступным полям в источнике данных формы. Ошибки в путях — одна из самых частых причин, по которой условное оформление не работает.

  5. Динамические списки:

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

  6. Использование свойства Использование:

    Не забывайте устанавливать свойство Использование = Истина для самого элемента условного оформления, для его отбора и для каждого поля оформления. Если это свойство не установлено, элемент оформления не будет активен.

Заключение

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

Надеемся, что это подробное руководство поможет вам эффективно настраивать условное оформление в ваших решениях на 1С:Предприятии 8.3!

← На главную