Разработчики часто сталкиваются с задачей визуального выделения данных в управляемых формах «1С:Предприятие 8.3». Одним из классических сценариев является раскраска строк в табличной части документа при невыполнении определенного условия. Например, нам необходимо выделить строку красным цветом, если сумма оплаты не совпадает со значением долга.
В этой статье мы подробно разберем, почему стандартный подход «в лоб» через сравнение двух полей компоновки данных в условном оформлении формы не работает, изучим внутренние ограничения платформы и реализуем правильное, отказоустойчивое решение с использованием расчетного реквизита.
Посмотрим на попытку реализации, которую предпринял автор темы в сообщениях 3 и 5. Он попытался программно добавить элемент условного оформления и напрямую сравнить два реквизита одной строки:
НовыйЭлементОтбора.Левоезначение = Новый ПолеКомпоновкиДанных("Объект.ОплатаПоРеализациям.СуммаДокументаРасчетов");
НовыйЭлементОтбора.Правоезначение = Новый ПолеКомпоновкиДанных("Объект.ОплатаПоРеализациям.СуммаДолга");
НовыйЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.НеРавно;
На первый взгляд код выглядит логичным, ведь в Системе компоновки данных (СКД) при построении отчетов такое сравнение работает безотказно. Однако на уровне условного оформления управляемой формы действует жесткое платформенное ограничение:
В условном оформлении формы в качестве правого значения отбора нельзя указывать другое поле компоновки данных.
Правое значение в отборах управляемой формы всегда должно быть константой (литералом): конкретным числом, строкой, датой, булевым значением или предопределенным элементом справочника/перечисления. Попытка сравнить два динамических поля «на лету» силами одного лишь условного оформления платформой просто игнорируется, и оформление не применяется.
Чтобы обойти это ограничение, мы применим стандартный паттерн разработки в среде 1С: добавим в структуру данных вспомогательный расчетный реквизит (флаг), значение которого будем рассчитывать программно, а условное оформление настроим на сравнение этого флага с константой Истина.
Разберем весь процесс реализации этой задачи по шагам.
Прежде всего, нам необходимо добавить в табличную часть нашего документа (или в таблицу значений на форме, если данные заполняются динамически) новую колонку. Назовем её, например, СуммыРазличаются с типом данных Булево.
Выводить эту колонку на экран пользователя не обязательно. Она может оставаться скрытой, но обязательно должна присутствовать в данных табличной части, чтобы условное оформление имело к ней доступ.
Поскольку значение флага СуммыРазличаются зависит от других колонок, нам необходимо своевременно его рассчитывать и обновлять. Делать это нужно в двух случаях: при открытии формы (для уже существующих данных) и при интерактивном изменении сумм пользователем.
Для первоначального заполнения флага при открытии формы создадим на сервере вспомогательную процедуру и вызовем ее в обработчике ПриСозданииНаСервере или ПриЧтенииНаСервере:
&НаСервере
Процедура РасчитатьПризнакРазницыСуммНаСервере()
Для Каждого СтрокаТЧ Из Объект.ОплатаПоРеализациям Цикл
СтрокаТЧ.СуммыРазличаются = (СтрокаТЧ.СуммаДокументаРасчетов <> СтрокаТЧ.СуммаДолга);
КонецЦикла;
КонецПроцедуры
Для того чтобы раскраска мгновенно реагировала на изменения, вносимые пользователем в режиме «1С:Предприятие», мы должны обновлять наш флаг на клиенте в обработчиках событий ПриИзменении для обеих колонок (СуммаДокументаРасчетов и СуммаДолга):
&НаКлиенте
Процедура ОплатаПоРеализациямПриИзмененииРеквизитовСуммы(Элемент)
ТекущаяСтрока = Элементы.ОплатаПоРеализациям.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено Тогда
// Рассчитываем флаг на лету без обращения к серверу
ТекущаяСтрока.СуммыРазличаются = (ТекущаяСтрока.СуммаДокументаРасчетов <> ТекущаяСтрока.СуммаДолга);
КонецЕсли;
КонецПроцедуры
Укажите эту клиентскую процедуру в качестве обработчика события ПриИзменении для обоих элементов управления колонок на форме.
В сообщении 9 автор темы пытался добавить оформляемое поле вручную, указав конкретную колонку. Однако если перед нами стоит задача выделить цветом всю строку целиком, мы столкнемся со следующим нюансом управляемых форм:
Если оставить коллекцию Поля элемента условного оформления пустой или заполнить некорректно, платформа может применить оформление непредсказуемо. Чтобы гарантированно закрасить всю строку, мы должны в цикле добавить в коллекцию оформляемых полей все видимые колонки нашей таблицы.
При этом важно помнить, что в коллекцию Поля условного оформления формы нужно передавать именно имена элементов формы (колонок), а не пути к их данным.
Объединим все наши наработки в одну процедуру, которая будет вызываться один раз при создании формы на сервере. Этот код полностью решает проблему, описанную автором темы:
&НаСервере
Процедура УстановитьУсловноеОформлениеРазницыСумм()
// 1. Добавляем новый элемент условного оформления формы
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
ЭлементОформления.Использование = Истина;
// 2. Определяем свойства оформления (задаем красный цвет фона)
ЦветФона = ЭлементОформления.Оформление.Найти("ЦветФона");
ЦветФона.Значение = WebЦвета.Красный;
ЦветФона.Использование = Истина;
// 3. Указываем, какие именно элементы формы мы будем оформлять.
// Чтобы закрасить всю строку, обходим в цикле все колонки таблицы формы.
Для Каждого ЭлементКолонка Из Элементы.ОплатаПоРеализациям.ПодчиненныеЭлементы Цикл
НовоеПоле = ЭлементОформления.Поля.Элементы.Добавить();
НовоеПоле.Поле = Новый ПолеКомпоновкиДанных(ЭлементКолонка.Имя);
НовоеПоле.Использование = Истина;
КонецЦикла;
// 4. Настраиваем условие отбора: СуммыРазличаются Равно Истина
ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.ОплатаПоРеализациям.СуммыРазличаются");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Истина;
ЭлементОтбора.Использование = Истина;
КонецПроцедуры
Эту процедуру достаточно вызвать один раз в стандартном обработчике управляемой формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Инициализируем расчетные значения для существующих строк
РасчитатьПризнакРазницыСуммНаСервере();
// Настраиваем правила отображения цветов
УстановитьУсловноеОформлениеРазницыСумм();
КонецПроцедуры
Для создания качественного и быстродействующего кода придерживайтесь следующих правил:
СуммыРазличаются при редактировании строк пользователем производите исключительно на клиенте в контексте текущих данных строки. Платформа 1С самостоятельно перерисует цвет строки, как только поменяется значение отслеживаемого реквизита, не требуя повторного обращения к серверу.Использование у вновь создаваемых элементов по умолчанию может быть равно Истина, явное его указание в коде (как для самого элемента оформления, так и для его отборов и полей) страхует от потенциальных сбоев в работе платформы на разных релизах.Применяя данный подход с использованием расчетных булевых реквизитов, вы сможете реализовывать любые, даже самые сложные правила динамической раскраски строк и ячеек табличных частей в управляемых формах 1С.