Как реализовать раскраску строк динамического списка в 1С при изменении номенклатуры

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

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

Проблема "предыдущей строки" в динамических списках

Разберем ситуацию: на первый взгляд кажется логичным при выводе строки проверять, совпадает ли Номенклатура в текущей строке с Номенклатурой в предыдущей. Однако динамический список — это не статичная таблица. Он считывает данные порциями (обычно по 20–45 строк) по мере прокрутки. Проанализируем, к чему это приводит:

  1. Разрыв порций данных: Если одна и та же номенклатура попадает на границу двух порций данных, сервер "забывает", какой цвет был у последней строки предыдущей порции.
  2. Смена порядка: Динамический список позволяет пользователю менять сортировку. При изменении порядка строк "предыдущая" строка всегда будет разной, что приведет к непредсказуемой чехарде цветов.
  3. Отсутствие контекста: Механизм УсловноеОформление работает на клиенте или сервере для каждой строки независимо, основываясь только на данных самой этой строки.

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

Метод 1: Использование вычисляемого поля и остатка от деления (Modulo)

Проанализируем самый стабильный способ: добавление в запрос динамического списка специального поля, которое будет определять "четность" или "индекс" группы номенклатуры. Мы можем использовать уникальный идентификатор ссылки (GUID) для получения стабильного признака цвета.

Рассмотрим пример настройки запроса в динамическом списке. Мы можем получить последний символ уникального идентификатора и на его основе вычислить числовой индекс:


ВЫБРАТЬ
    ДокументПродажи.Ссылка КАК Ссылка,
    ДокументПродажи.Дата КАК Дата,
    ДокументПродажи.Номенклатура КАК Номенклатура,
    ДокументПродажи.Количество КАК Количество,
    ВЫБОР
        КОГДА ПОДСТРОКА(ВЫРАЗИТЬ(ДокументПродажи.Номенклатура.УникальныйИдентификатор КАК СТРОКА(36)), 36, 1) В ("0", "2", "4", "6", "8", "a", "c", "e")
            ТОГДА 0
        ИНАЧЕ 1
    КОНЕЦ КАК ИндексЦвета
ИЗ
    Документ.Продажи КАК ДокументПродажи

В данном примере мы используем функцию ПОДСТРОКА, чтобы извлечь последний символ GUID. Поскольку GUID распределены квазиравномерно, примерно половина товаров получит ИндексЦвета равный 0, а другая половина — 1. Важно понимать, что этот метод "приклеивает" цвет к номенклатуре: конкретный товар всегда будет иметь один и тот же цвет, независимо от сортировки.

Метод 2: Чередование цветов через вложенный запрос

Если нам нужно строгое чередование (первая группа товаров — цвет А, вторая группа — цвет Б, третья — снова цвет А), нам придется вычислить порядковый номер номенклатуры в общем списке. Выясним причину, почему это сложнее: нам нужно посчитать количество уникальных элементов, которые "меньше" текущего по алфавиту.

Рассмотрим структуру такого запроса:


ВЫБРАТЬ
    Т1.Ссылка КАК Ссылка,
    Т1.Номенклатура КАК Номенклатура,
    (ВЫБРАТЬ
        КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Т2.Ссылка)
    ИЗ
        Справочник.Номенклатура КАК Т2
    ГДЕ
        Т2.Наименование < Т1.Номенклатура.Наименование) % 2 КАК ЧетностьГруппы
ИЗ
    РегистрНакопления.Продажи КАК Т1

Важный момент: использование вложенных запросов с агрегатными функциями (КОЛИЧЕСТВО) внутри динамического списка может существенно замедлить работу при больших объемах данных. Проанализируем ситуацию: если в справочнике 100 000 элементов, такой запрос будет выполняться долго. Этот метод рекомендуется только для списков с небольшим количеством уникальных значений номенклатуры.

Метод 3: Использование оконных функций (Платформа 8.3.20+)

В современных версиях платформы 1С появилась поддержка расширенных возможностей языка запросов СКД. Мы можем использовать функции нумерации строк. Рассмотрим, как это упрощает задачу. Хотя прямое использование оконных функций в динамическом списке ограничено, мы можем использовать механизмы компоновки данных для расчета порядковых номеров групп.

Для этого в настройках динамического списка на закладке "Запрос" можно активировать использование основной таблицы и в поле выбора добавить расчет через ПОРЯДКОВЫЙ_НОМЕР(), если конфигурация позволяет редактировать схему компоновки данных динамического списка.

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

После того как мы получили поле ИндексЦвета или ЧетностьГруппы в нашем динамическом списке, перейдем к визуальной настройке. Пройдем по шагам:

  1. Откроем форму, на которой размещен динамический список.
  2. Перейдем в свойства таблицы (списка) и найдем пункт Условное оформление.
  3. Нажмем "Добавить" и создадим новое правило.
  4. Оформление: Выберем ЦветФона. Укажем приятный пастельный цвет.
  5. Условие: Выберем наше поле ИндексЦвета, вид сравнения "Равно", значение "1".
  6. Оформляемые поля: Выберем все поля списка (Дата, Номенклатура, Количество) или всю строку целиком.

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

Метод 4: Обработка события ПриПолученииДанныхНаСервере

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


&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
    
    // Переменная для хранения состояния цвета последней номенклатуры
    // Внимание: этот метод может иметь проблемы при прокрутке вверх!
    Для Каждого СтрокаСписок Из Строки Цикл
        ДанныеСтроки = СтрокаСписок.Значение;
        // Здесь можно реализовать логику сравнения, 
        // но помните о границах порций данных.
    КонецЦикла;

КонецПроцедуры

Проанализируем этот подход: как отмечали участники форума, в сообщении (13) и (17), использование этого события для чередования цветов опасно. Верхняя строка новой порции данных всегда будет считаться "первой", и её цвет может не совпасть с цветом последней строки предыдущей порции. Поэтому рекомендуется отдавать предпочтение расчету признака цвета в запросе (Методы 1 и 2).

Заключение и рекомендации

Мы выяснили, что наиболее надежным способом реализации раскраски является вычисление числового признака (0 или 1) прямо в тексте запроса. Проанализировав все варианты, можно сделать следующие выводы:

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

← На главную