При разработке расширений для типовых конфигураций, таких как УТ 11, ERP или КА, часто возникает задача визуального выделения строк в табличной части. Например, нужно подсветить товары, цена которых в заказе отклоняется от установленного прайс-листа. В этой статье мы подробно разберем, как правильно реализовать такой механизм, избежав типичных ошибок производительности и проблем с программным интерфейсом платформы 1С:Предприятие 8.3.
Представим ситуацию: в документе «Заказ клиента» необходимо окрашивать строки в светло-зеленый цвет, если текущая цена в строке ниже, чем цена, зафиксированная в регистре сведений ЦеныНоменклатуры. Для реализации мы используем расширение, в которое добавим вспомогательный реквизит табличной части и настроим условное оформление формы.
Рассмотрим по шагам, как это сделать правильно, проанализируем ошибки и найдем оптимальное решение.
Первая и самая важная ошибка, которую часто совершают начинающие разработчики, — выполнение запроса в цикле при обходе табличной части. Если в заказе будет 100 или 200 строк, система сделает 100–200 обращений к базе данных, что существенно замедлит работу формы. Проанализируем, как сделать это правильно: сначала соберем все данные одним запросом, а затем распределим их по строкам.
Создадим процедуру на сервере, которая будет заполнять наш вспомогательный реквизит Расш1_ЦенаНижеПрайса:
&НаСервере
Процедура Расш1_ОбновитьПризнакЦеныНижеПрайса()
// 1. Собираем номенклатуру и виды цен из документа, чтобы получить цены одним махом
ТаблицаТоваров = Объект.Товары.Выгрузить();
МассивНоменклатуры = ТаблицаТоваров.ВыгрузитьКолонку("Номенклатура");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
| ЦеныНоменклатурыСрезПоследних.ВидЦены КАК ВидЦены,
| ЦеныНоменклатурыСрезПоследних.Цена КАК ЦенаПрайса
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, Номенклатура В (&МассивНоменклатуры)) КАК ЦеныНоменклатурыСрезПоследних";
Запрос.УстановитьПараметр("Период", Объект.Дата);
Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
// 2. Обходим товары и сравниваем цены в памяти
Для Каждого ТекСтрока Из Объект.Товары Цикл
ПараметрыОтбора = Новый Структура("Номенклатура, ВидЦены", ТекСтрока.Номенклатура, ТекСтрока.ВидЦены);
НайденныеСтроки = РезультатЗапроса.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
ТекСтрока.Расш1_ЦенаНижеПрайса = (ТекСтрока.Цена < НайденныеСтроки[0].ЦенаПрайса);
Иначе
ТекСтрока.Расш1_ЦенаНижеПрайса = Ложь;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Эту процедуру следует вызывать в обработчике ПриСозданииНаСервере, а также при изменении номенклатуры или цены в табличной части, чтобы оформление обновлялось динамически.
Теперь перейдем к самому условному оформлению. Рассмотрим критически важный момент: различие между путем к данным и именем элемента формы. Многие разработчики путают их, из-за чего оформление просто «не взлетает».
Выясним правила работы с объектом УсловноеОформление:
Объект.Товары.ИмяРеквизита.Посмотрим на исправленный пример кода в обработчике ПриСозданииНаСервере:
&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Сначала заполним данные
Расш1_ОбновитьПризнакЦеныНижеПрайса();
// Настраиваем условное оформление
// ВАЖНО: В типовых конфигурациях Очистить() может удалить стандартные раскраски (ошибки, дефицит).
// Рекомендуется либо добавлять свое, либо искать и удалять только свои старые настройки.
ЭлементУО = УсловноеОформление.Элементы.Добавить();
// 1. Устанавливаем цвет фона
ЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветФона", WebЦвета.СветлоЗеленый);
// 2. Добавляем условие (фильтр)
ЭлементУсловия = ЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// Указываем ПУТЬ К ДАННЫМ
ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Расш1_ЦенаНижеПрайса");
ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементУсловия.ПравоеЗначение = Истина;
// 3. Указываем, ЧТО именно красить (оформляемые поля)
// Если нужно покрасить всю строку, добавляем имя самого элемента "Таблица" (обычно "Товары")
ОформляемоеПоле = ЭлементУО.Поля.Элементы.Добавить();
ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("Товары");
КонецПроцедуры
Проанализируем ситуацию, когда код написан верно, но оформление все равно не работает. В работе с расширениями есть несколько «подводных камней»:
1. Свойство «Использовать всегда».
Если вы добавили реквизит Расш1_ЦенаНижеПрайса в расширение и используете его только в программном коде условного оформления (не выводя колонку на форму), платформа может «оптимизировать» запрос и не подтягивать это поле с сервера. Чтобы этого избежать, найдите этот реквизит в расширении (в составе табличной части формы) и в свойствах установите флажок «Использовать всегда» в значение Истина.
2. Очистка коллекции оформления.
Метод УсловноеОформление.Элементы.Очистить() — это радикальный шаг. В УТ 11 программно задается множество стандартных правил оформления (например, выделение строк с незаполненными счетами учета или просроченными датами отгрузки). Если вы вызовете Очистить(), вся эта логика пропадет. Вместо этого лучше просто добавлять свои элементы или проверять, не были ли они добавлены ранее.
3. Порядок выполнения (После или Вместо).
Используйте аннотацию &НаСервере Процедура Расш1_ПриСозданииНаСервереПосле. Это гарантирует, что типовая конфигурация уже выполнила свои настройки, и вы просто дополняете их своими правилами. Если использовать &Вместо, вы рискуете нарушить инициализацию формы, предусмотренную разработчиками 1С.
Для успешного раскрашивания строк в расширении мы должны:
ЛевоеЗначение отбора передавать путь через Объект.Товары....ОформляемоеПоле передавать имя элемента таблицы на форме.Соблюдение этих правил обеспечит стабильную работу интерфейса и высокую производительность системы даже в документах с большим количеством строк. Если требуется готовое решение для визуального выделения позиций, можно использовать расширение для окрашивания строк в заказе и реализации по группам товаров.