Разработчики, привыкшие к удобному декларативному механизму условного оформления в управляемых формах 1С:Предприятия 8.3, часто испытывают трудности при возвращении к обычным формам (ОФ). В обычном интерфейсе привычного интерактивного конструктора оформления строк просто не существует. Здесь любые визуальные изменения списков и табличных частей выполняются исключительно программным путем.
В этой статье мы подробно разберем, как реализовать условное оформление (раскраску строк, изменение шрифтов и стилей) в обычных формах. Особое внимание мы уделим тому, как сделать это в типовой конфигурации, находящейся на полной поддержке, без её изменения, а также проанализируем влияние различных методов на производительность системы.
Если перед нами стоит задача кастомизировать список в типовом решении (например, в «1С:Управлении производственным предприятием» или «1С:Управлении торговлей 10.3»), снимать конфигурацию с поддержки крайне нежелательно. Для решения этой задачи у нас есть два надежных пути:
Рассмотрим подробнее пример подключения обработчика событий через расширение конфигурации. Нам потребуется программно привязать наш собственный метод к событию табличного поля. Сделать это лучше всего в событии ПриОткрытии заимствованной формы:
&После("ПриОткрытии")
Процедура Расш_ПриОткрытии()
// Динамически подключаем наш обработчик к событию табличного поля формы "Список"
ЭлементыФормы.Список.УстановитьДействие("ПриПолученииДанных", Новый Действие("Расш_СписокПриПолученииДанных"));
КонецПроцедуры
Для реализации программного оформления строк в табличном поле обычных форм разработчику доступны два основных события. Выясним разницу между ними, так как неправильный выбор может привести к критическому падению скорости работы интерфейса.
Данное событие вызывается системой для каждой отдельной строки в момент её отрисовки на экране монитора. Мы можем использовать его только тогда, когда условие оформления зависит исключительно от данных, которые уже присутствуют в текущей строке.
Проанализируем пример, когда нам нужно покрасить строку в зависимости от статуса проведения документа. Поскольку флаг проведения (Проведен) уже загружен в строку, нам не нужно обращаться к базе данных:
Процедура СписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
Если ДанныеСтроки = Неопределено Тогда
Возврат;
КонецЕсли;
// Если документ не проведен, выделим его светло-красным фоном
Если НЕ ДанныеСтроки.Проведен Тогда
ОформлениеСтроки.ЦветФона = Новый Цвет(255, 230, 230);
Иначе
ОформлениеСтроки.ЦветФона = Новый Цвет(255, 255, 255); // Возвращаем стандартный цвет
КонецЕсли;
КонецПроцедуры
Важное предупреждение (антипаттерн): Внутри события ПриВыводеСтроки категорически запрещается писать запросы к базе данных или обращаться к реквизитам через точку (например, ДанныеСтроки.Договор.ВидДоговора). Если пользователь начнет быстро прокручивать список, система выполнит сотни и тысячи одиночных обращений к базе данных. Это мгновенно приведет к зависанию интерфейса.
Это событие вызывается один раз сразу для всей видимой порции строк (обычно по 20–40 строк, отображаемых на экране). Вместо построчной обработки мы получаем массив оформлений. Это позволяет нам выполнить всего один оптимизированный пакетный запрос к базе данных, получить информацию для всех строк сразу и применить оформление.
Разберем по шагам правильную реализацию этого метода:
Процедура СписокПриПолученииДанных(Элемент, ОформленияСтрок)
// Шаг 1. Собираем ссылки на объекты со всех видимых строк списка
МассивСсылок = Новый Массив;
СоответствиеОформлений = Новый Соответствие;
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
ДанныеСтроки = ОформлениеСтроки.ДанныеСтроки;
Если ДанныеСтроки <> Неопределено Тогда
МассивСсылок.Добавить(ДанныеСтроки.Ссылка);
// Запоминаем связь ссылки с объектом оформления
СоответствиеОформлений.Вставить(ДанныеСтроки.Ссылка, ОформлениеСтроки);
КонецЕсли;
КонецЦикла;
Если МассивСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Шаг 2. Выполняем один единственный запрос по массиву ссылок
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Реализация.Ссылка КАК Ссылка,
| Реализация.ДоговорКонтрагента.ВидДоговора КАК ВидДоговора,
| Реализация.СуммаДокумента КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Ссылка В (&МассивСсылок)";
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
// Шаг 3. Обходим выборку и применяем цвета к строкам
Пока Выборка.Следующий() Цикл
ТекущееОформление = СоответствиеОформлений.Получить(Выборка.Ссылка);
Если ТекущееОформление <> Неопределено Тогда
// Если вид договора - Бартер, красим строку в желтый цвет
Если Выборка.ВидДоговора = Перечисления.ВидыДоговоров.Бартер Тогда
ТекущееОформление.ЦветФона = Новый Цвет(255, 255, 200);
КонецЕсли;
// Если сумма превышает лимит, выделяем текст жирным шрифтом
Если Выборка.Сумма > 500000 Тогда
ТекущееОформление.Шрифт = Новый Шрифт(ТекущееОформление.Шрифт, , , Истина);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
При работе с оформлением строк в обычном интерфейсе 1С крайне важно придерживаться следующих правил архитектуры разработки:
ПриВыводеСтроки и ПриПолученииДанных допускается изменять исключительно визуальные свойства ячеек (ЦветФона, ЦветТекста, Шрифт, ТолькоПросмотр, Текст). Попытка изменить реальное значение данных (например, присвоить значение реквизиту ДанныеСтроки.Сумма = 100) вызовет повторную перерисовку формы, что спровоцирует бесконечный цикл обновления и намертво завесит сеанс пользователя.ПриПолученииДанных так, чтобы они выполнялись максимально быстро по индексированным полям базы данных.Используя предложенные механизмы расширения конфигураций и событие ПриПолученииДанных, мы можем настроить гибкое, быстрое и полностью безопасное условное оформление в любых обычных формах платформы 1С:Предприятие 8.3.