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