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