Как подсветить строки в динамическом списке, выбранные в таблицу значений?

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

В практике разработки на платформе 1С:Предприятие 8 часто встречается задача: на управляемой форме расположен динамический список (например, номенклатуры, документов или стилей) и таблица значений, в которую пользователь отбирает определенные позиции. Чтобы интерфейс оставался наглядным и удобным, необходимо визуально выделять (подсвечивать фоном или менять цвет текста) те строки динамического списка, ссылки которых уже присутствуют в таблице значений.

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

Ограничение платформы: почему нельзя передать таблицу значений как временную таблицу в динамический список

При поиске решения разработчики нередко предполагают передать таблицу значений в запрос динамического списка в качестве временной таблицы через менеджер временных таблиц, соединить ее с основной таблицей и вывести признак наличия. Однако в платформе 1С динамический список не поддерживает работу с внешним объектом МенеджерВременныхТаблиц. Пакетные запросы в динамических списках могут работать только с теми временными таблицами, которые сформированы внутри самого запроса из физических таблиц базы данных. Поэтому передать локальную таблицу значений формы напрямую в запрос списка как временную таблицу невозможно.

Способ 1. Использование условного оформления динамического списка

Условное оформление — это штатный декларативный механизм платформы, который позволяет форматировать строки по заданным условиям. Реализовать подсветку через условное оформление можно двумя путями.

Вариант А: Оформление по полю «Ссылка» без изменения запроса списка.

Для реализации этого варианта нет необходимости модифицировать текст запроса динамического списка. Достаточно добавить элемент в коллекцию УсловноеОформление формы или самого динамического списка, указав вид сравнения ВСписке.

Разберем по шагам алгоритм настройки:

  1. При создании формы или в момент инициализации создаем элемент условного оформления.
  2. В отборе элемента указываем левое значение — поле компоновки Ссылка (или поле ссылки динамического списка).
  3. Вид сравнения устанавливаем в ВидСравненияКомпоновкиДанных.ВСписке.
  4. В качестве правого значения передаем массив ссылок, выгруженный из таблицы значений.
  5. Задаем оформление (например, цвет фона или цвет текста).
  6. При добавлении или удалении строк в таблице значений обновляем правое значение в отборе условного оформления.

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


// Создание или обновление элемента условного оформления
ЭлементОформления = УсловноеОформление.Элементы.Добавить();

// Настройка оформляемых полей
ОформляемоеПоле = ЭлементОформления.Поля.Элементы.Добавить();
ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("Список");

// Настройка оформления (например, серый цвет фона)
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", WebЦвета.СветлоСерый);

// Настройка условия отбора
ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ссылка");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
ЭлементОтбора.ПравоеЗначение = ТаблицаВыбранного.ВыгрузитьКолонку("Ссылка");
ЭлементОтбора.Использование = Истина;

Вариант Б: Модификация текста запроса списка с добавлением признака.

В тексте запроса динамического списка можно явно объявить вычисляемое булево поле, проверяющее вхождение ссылки в массив параметров:


ВЫБРАТЬ
    СправочникНоменклатура.Ссылка КАК Ссылка,
    СправочникНоменклатура.Наименование КАК Наименование,
    СправочникНоменклатура.Ссылка В (&МассивВыбранных) КАК УжеВыбрано
ИЗ
    Справочник.Номенклатура КАК СправочникНоменклатура

Для старых версий платформы использовалась синтаксическая конструкция с оператором ВЫБОР:


ВЫБОР
    КОГДА СправочникНоменклатура.Ссылка В (&МассивВыбранных)
        ТОГДА ИСТИНА
    ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК УжеВыбрано

Далее в условном оформлении настраивается простое условие: поле УжеВыбрано Равно Истина. При изменении строк в таблице значений массив ссылок передается в параметры списка:


Список.Параметры.УстановитьЗначениеПараметра("МассивВыбранных", ТаблицаВыбранного.ВыгрузитьКолонку("Ссылка"));

Особенности и ограничения условного оформления:

  1. Сброс кэша: Любая программная модификация параметров динамического списка или значений отбора условного оформления приводит к сбросу внутреннего кэша динамического списка и повторному считыванию текущей порции данных с сервера.
  2. Ограничения СУБД: Если таблица значений содержит сотни или тысячи элементов, условие IN (...) в итоговом SQL-запросе создает существенную нагрузку на оптимизатор СУБД или может превысить лимит на допустимое число параметров в одном запросе.

Способ 2. Событие «ПриПолученииДанныхНаСервере»

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

В обработчик передается параметр ОформленияСтрок, содержащий только те строки, которые в данный момент реально считываются с сервера и выводятся на экран клиента (порция отображения).

Проанализируем ключевой момент оптимизации: поиск ссылки из строки динамического списка в таблице значений. Если использовать метод ТаблицаЗначений.Найти() или Массив.Найти(), платформа будет выполнять линейный перебор для каждой строки видимой страницы. Чтобы оформление работало максимально быстро при прокрутке списка, ссылки следует поместить в объект Соответствие, где проверка наличия ключа выполняется за константное время $O(1)$.

Посмотрим на пример реализации в модуле формы:


&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(Элемент, ОформленияСтрок)

    // Формируем соответствие выбранных ссылок для быстрого поиска O(1)
    ВыбранныеСсылки = Новый Соответствие;
    Для Каждого СтрТЗ Из ТаблицаВыбранныхТоваров Цикл
        ВыбранныеСсылки.Вставить(СтрТЗ.Ссылка, Истина);
    КонецЦикла;

    // Оформляем только те строки, которые переданы в текущей порции отображения
    Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
        Если ВыбранныеСсылки[ОформлениеСтроки.Данные.Ссылка] <> Неопределено Тогда
            ОформлениеСтроки.Оформление.ЦветФона.Значение = WebЦвета.СветлоЗеленый;
            ОформлениеСтроки.Оформление.ЦветТекста.Значение = WebЦвета.ТемноЗеленый;
        КонецЕсли;
    КонецЦикла;

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

Важная деталь обновления: При интерактивном добавлении или удалении элементов в таблице значений динамический список сам по себе не узнает об изменениях данных формы. Чтобы обработчик ПриПолученииДанныхНаСервере отработал повторно для видимых на экране строк, необходимо принудительно обновить список на клиенте:


&НаКлиенте
Процедура ПослеДобавленияВТаблицу()
    // Вызываем обновление отображения списка
    Элементы.Список.Обновить();
КонецПроцедуры

Как выбрать оптимальный подход

Подведем итог и выделим рекомендации для различных сценариев:

  1. Если версия платформы 8.3.10 и выше, а оформление динамическое и часто меняется в процессе работы с формой — предпочтительнее использовать ПриПолученииДанныхНаСервере в связке с Соответствием. Это исключает перегрузку SQL-запроса условиями IN (...) и обеспечивает высокую скорость прокрутки.
  2. Если количество выбранных элементов гарантированно невелико (до нескольких десятков) или требуется декларативная настройка — оптимально использовать условное оформление с отбором ВидСравненияКомпоновкиДанных.ВСписке без изменения текста запроса списка.
  3. Если объем выбранных позиций измеряется тысячами элементов, хранить их только в оперативной памяти формы нерационально. В таких случаях данные целесообразно временно записывать в физическую таблицу базы данных (например, в служебный регистр сведений с разделением по сеансу пользователя) и связывать ее в запросе динамического списка через левое соединение.
← На главную