В процессе разработки интерфейсов на платформе 1С программисты часто сталкиваются с необходимостью визуально выделить данные, которые не соответствуют определенному критерию. Типичный пример — подкрашивание ячеек с дробными числами (например, если количество товара должно быть целым, а в поле введено 1.5). Однако стандартный механизм условного оформления имеет свои архитектурные особенности. В этой статье мы разберем, почему попытки «написать формулу» в условии оформления не работают, и рассмотрим правильные методы реализации этой задачи.
Разберем типичную ошибку начинающего разработчика. Мы привыкли, что во встроенном языке можно написать условие типа Если Значение <> Цел(Значение) Тогда. По аналогии возникает желание вставить подобное выражение прямо в ЛевоеЗначение или ПравоеЗначение элемента отбора компоновки данных. Рассмотрим пример кода, который не будет работать:
// ОШИБОЧНЫЙ ПРИМЕР
ЭлементУсловия = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Количество");
// Попытка использовать выражение в поле приведет к ошибке, так как система ищет поле с таким ИМЕНЕМ
ЭлементУсловия.ПравоеЗначение = Новый ПолеКомпоновкиДанных("ВЫРАЗИТЬ(Количество КАК ЧИСЛО(15,0))");
ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.неРавно;
Проанализируем причину неудачи. Объект ПолеКомпоновкиДанных — это не интерпретатор кода, а просто строковая ссылка на путь к данным в источнике. Система ожидает найти в наборе данных колонку, имя которой буквально совпадает со строкой "ВЫРАЗИТЬ(...)". Поскольку такой колонки нет, условие игнорируется. Платформа 1С на данный момент не умеет вычислять произвольные выражения внутри механизма условного оформления «на лету».
Теперь рассмотрим рабочие стратегии решения этой задачи для различных сценариев.
Если ваша задача реализуется в рамках отчета на Системе Компоновки Данных (СКД), это самый элегантный и правильный метод. Мы переносим логику вычисления «дробности» из оформления в саму схему данных.
Разберем по шагам:
ЭтоДробноеЧисло и типом Булево.
Выбор
Когда МоеЧисловоеПоле = Выразить(МоеЧисловоеПоле, "Число(15, 0)")
Тогда Ложь
Иначе Истина
Конец
ЭтоДробноеЧисло Равно Истина.Этот метод хорош тем, что мы не создаем лишних данных в базе данных (SQL), расчет происходит в памяти в момент формирования отчета.
Если вам нужно выделить строки в списке документов или справочников (динамический список), лучше всего добавить признак проверки прямо в текст запроса. Рассмотрим, как это сделать:
Проанализируем запрос динамического списка:
ВЫБРАТЬ
ДокументРеализация.Ссылка КАК Ссылка,
ДокументРеализация.Номер КАК Номер,
ДокументРеализация.СуммаДокумента КАК СуммаДокумента,
// Вычисляем признак наличия дробной части
ВЫБОР
КОГДА ДокументРеализация.СуммаДокумента = ВЫРАЗИТЬ(ДокументРеализация.СуммаДокумента КАК ЧИСЛО(15, 0))
ТОГДА ЛОЖЬ
ИНАЧЕ ИСТИНА
КОНЕЦ КАК ЭтоДробнаяСумма
ИЗ
Документ.РеализацияТоваровУслуг КАК ДокументРеализация
После добавления этого поля в запрос, оно станет доступно в настройках условного оформления формы. Вы можете даже не выводить колонку ЭтоДробнаяСумма в таблицу (сняв флаг видимости), но использовать её в отборе оформления. Это стандартная практика для управляемых форм.
Если речь идет о табличной части документа (например, проверка количества при вводе пользователем), вычисляемые поля СКД недоступны. Автор темы на форуме опасался «засорения данных», но здесь важно различать реквизиты объекта (которые хранятся в базе) и реквизиты формы (которые живут только в памяти клиента во время работы с окном).
Рассмотрим алгоритм действий:
Объект.Товары) и добавим в неё новый реквизит ОшибкаЦелогоЧисла (тип Булево). Это поле не будет сохраняться в БД.ПриЧтенииНаСервере или ПриСозданииНаСервере заполним это поле для существующих строк:
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
СтрокаТЧ.ОшибкаЦелогоЧисла = (СтрокаТЧ.Количество <> Цел(СтрокаТЧ.Количество));
КонецЦикла;
ПриИзменении для поля Количество, чтобы актуализировать флаг при вводе данных пользователем:
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено Тогда
ТекущаяСтрока.ОшибкаЦелогоЧисла = (ТекущаяСтрока.Количество <> Цел(ТекущаяСтрока.Количество));
КонецЕсли;
КонецПроцедуры
Объект.Товары.ОшибкаЦелогоЧисла Равно Истина.Если вы все же решили создавать оформление программно (например, в универсальной обработке), важно соблюдать правильный синтаксис. Рассмотрим корректный пример из обсуждения, дополненный необходимыми параметрами:
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
ЭлементОформления.Использование = Истина;
// Указываем, ЧТО менять (например, цвет фона)
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(250, 191, 143));
// Указываем УСЛОВИЕ (сравнение поля с заранее подготовленным флагом)
ЭлементУсловия = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.ОшибкаЦелогоЧисла");
ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементУсловия.ПравоеЗначение = Истина;
ЭлементУсловия.Использование = Истина;
// Указываем, КАКОЕ ПОЛЕ оформлять
ОформляемоеПоле = ЭлементОформления.Поля.Элементы.Добавить();
ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("ТоварыКоличество");
ОформляемоеПоле.Использование = Истина;
Важный нюанс: не забывайте устанавливать свойство Использование = Истина не только для самого элемента оформления, но и для полей и условий, если вы создаете их динамически.
Механизм условного оформления в 1С спроектирован для работы с готовыми значениями. Попытки внедрить расчетную логику непосредственно в объект Отбор противоречат архитектуре платформы. Для решения задачи подкрашивания нецелых чисел всегда используйте промежуточный признак (флаг типа Булево), который рассчитывается либо в запросе, либо в вычисляемом поле СКД, либо в реквизите формы. Это обеспечит высокую производительность интерфейса и чистоту вашего кода.