Как раскрасить строки табличной части документа в 1С по условию?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В процессе разработки в среде 1С часто возникает задача визуального выделения определенных позиций в табличной части документа. Это может быть связано с необходимостью подсветить товары определенного бренда, позиции с особыми свойствами или номенклатуру, требующую внимания пользователя. В данной статье мы подробно разберем, как реализовать этот функционал для обычных форм (на примере «Управление торговлей 10.3»), избегая типичных ошибок новичков и проблем с производительностью.

Постановка задачи и выбор подхода

Рассмотрим ситуацию: нам нужно выделить цветом строки в документе, содержащие определенную номенклатуру. Первое побуждение начинающего программиста — написать условие непосредственно по коду или артикулу:


Если ОформлениеСтроки.ДанныеСтроки.Номенклатура.Код = "0000123" Тогда
    ОформлениеСтроки.Ячейки.Номенклатура.ЦветФона = WebЦвета.Зеленый;
КонецЕсли;

Проанализируем этот подход. Если таких позиций 30 или 100, код превратится в «простыню» из условий Если...ИначеЕсли. Кроме того, любое изменение списка номенклатуры потребует вмешательства программиста. Поэтому мы выберем более гибкий путь: будем хранить признак цвета в свойствах номенклатуры (через штатный механизм дополнительных реквизитов) и использовать его для раскраски.

Шаг 1: Подготовка данных в пользовательском режиме

Прежде чем писать код, необходимо создать аналитику. В типовых конфигурациях на обычных формах (УТ 10, УПП 1.3) уже есть регистр сведений ЗначенияСвойствОбъектов. Разберем порядок действий:

  1. Откроем справочник «Номенклатура» и перейдем в настройки свойств.
  2. Создадим новое свойство, например, «ЦветСтроки» с типом значения «Дополнительное значение».
  3. В значениях этого свойства добавим элемент, например, «ВесеннеЗеленый».
  4. Для нужных позиций номенклатуры установим это значение.

Теперь наша задача — научить программу «видеть» этот признак при отрисовке таблицы.

Шаг 2: Реализация через событие ПриВыводеСтроки

Событие ПриВыводеСтроки вызывается для каждой строки табличного поля в момент её отображения. Это самый простой способ, подходящий для небольших документов.

Рассмотрим пример кода, который мы разместим в модуле формы документа:


Процедура ТоварыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    
    // Подготовим запрос для получения свойства конкретной номенклатуры
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЗначенияСвойствОбъектов.Значение КАК ЗначениеСвойства
    |ИЗ
    |	РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов
    |ГДЕ
    |	ЗначенияСвойствОбъектов.Объект = &Номенклатура
    |	И ЗначенияСвойствОбъектов.Свойство.Наименование = ""ЦветСтроки""";
    
    Запрос.УстановитьПараметр("Номенклатура", ДанныеСтроки.Номенклатура);
    
    Результат = Запрос.Выполнить();
    Если Не Результат.Пустой() Тогда
        Выборка = Результат.Выбрать();
        Выборка.Следующий();
        
        // Если значение свойства соответствует нашему эталону, красим ячейку
        Если Выборка.ЗначениеСвойства.Наименование = "ВесеннеЗеленый" Тогда
            ОформлениеСтроки.Ячейки.Номенклатура.ЦветФона = WebЦвета.ВесеннеЗеленый;
        КонецЕсли;
    КонецЕсли;

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

Важное предостережение: выполнение запроса внутри события ПриВыводеСтроки — это «плохой тон» в программировании 1С. Если в документе будет много строк, при прокрутке списка 1С будет выполнять запрос для каждой новой строки на экране, что вызовет заметные тормоза интерфейса.

Шаг 3: Оптимизация запроса (Проблема «Точек»)

Выясним причину, почему запросы к свойствам могут работать медленно. В регистре ЗначенияСвойствОбъектов измерение Объект имеет составной тип данных (это может быть и Номенклатура, и Контрагент, и Документ). Когда мы пишем в запросе ЗначенияСвойствОбъектов.Объект.Наименование, платформа выполняет соединение (JOIN) со всеми возможными таблицами, входящими в составной тип. Это критически замедляет работу.

Правильный подход к написанию запроса:

  1. Использовать параметры для отбора ссылок (передавать конкретную ссылку на свойство, полученную заранее).
  2. Избегать разыменования полей через точки у полей составного типа.
  3. Если необходимо ограничить поиск только номенклатурой, использовать оператор ССЫЛКА.

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


ГДЕ
    ЗначенияСвойствОбъектов.Объект = &Номенклатура
    И ЗначенияСвойствОбъектов.Свойство = &НужноеСвойство

Шаг 4: Профессиональный подход через ПриПолученииДанных

Чтобы интерфейс работал «летаючи», используем событие ПриПолученииДанных. Оно отличается тем, что вызывается сразу для всей пачки строк (коллекции ОформленияСтрок), которые система планирует отрисовать в данный момент. Это позволяет нам выполнить всего один запрос вместо десятков.

Рассмотрим алгоритм реализации:


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

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

Дополнительные советы по кэшированию

Для достижения максимальной производительности в высоконагруженных системах (например, если в справочнике миллионы позиций), мы рекомендуем использовать **кэширование списка раскраски**. Рассмотрим, как это сделать:

  1. В модуле формы создадим переменную СписокОсобойНоменклатуры (тип Соответствие).
  2. В событии ПередОткрытием или ПриОткрытии один раз выполним запрос ко всему регистру свойств, отобрав номенклатуру с нужным цветом.
  3. Заполним наше Соответствие, где ключом будет ссылка на номенклатуру, а значением — Истина.
  4. В процедуре ПриВыводеСтроки будем делать просто:
    
    Если СписокОсобойНоменклатуры.Получить(ДанныеСтроки.Номенклатура) <> Неопределено Тогда
        ОформлениеСтроки.Ячейки.Номенклатура.ЦветФона = WebЦвета.Зеленый;
    КонецЕсли;
    

Этот метод полностью исключает запросы к базе данных во время отрисовки интерфейса, так как данные уже лежат в оперативной памяти компьютера пользователя.

Резюме

Проанализировав ситуацию, мы выяснили, что наиболее эффективный способ раскраски ТЧ в обычных формах 1С — это использование события ПриПолученииДанных с пакетным запросом или кэширование списка во внутреннем соответствии формы. Это обеспечивает отличную отзывчивость программы даже при работе с большими документами и обширными базами данных. Помните о «проблеме точек» в запросах к составным типам и всегда старайтесь выносить поиск параметров (свойств, значений) за пределы циклов отрисовки.

← На главную