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