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