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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

В данной статье мы разберем, как правильно реализовать такое оформление, проанализируем типичные ошибки производительности и рассмотрим оптимальные программные способы решения задачи.

Почему стандартное оформление через метаданные не всегда подходит?

Стандартный механизм условного оформления динамического списка работает быстро, так как платформа сама добавляет необходимые поля в SQL-запрос. Но если условие требует анализа табличных частей или сложных связей, которых нет в Произвольном запросе списка, нам приходится прибегать к программным методам. Рассмотрим, как это сделать правильно.

Способ 1. Изменение текста запроса динамического списка (Рекомендуемый)

Прежде чем писать программный код в обработчиках, проанализируем возможность изменения самого запроса динамического списка. Это самый производительный метод. Мы можем добавить ЛЕВОЕ СОЕДИНЕНИЕ или вложенный запрос с использованием оператора ГДЕ Ссылка В (...).

Например, добавим в запрос вычисляемое поле ЕстьБезНДС:


ВЫБРАТЬ
    Док.Ссылка КАК Ссылка,
    Док.Дата КАК Дата,
    Док.Номер КАК Номер,
    ВЫБОР
        КОГДА ТаблицаБезНДС.Ссылка ЕСТЬ НЕ NULL ТОГДА ИСТИНА
        ИНАЧЕ ЛОЖЬ
    КОНЕЦ КАК ЕстьБезНДС
ИЗ
    Документ.ПриобретениеТоваровУслуг КАК Док
ЛЕВОЕ СОЕДИНЕНИЕ (
    ВЫБРАТЬ РАЗЛИЧНЫЕ
        Товары.Ссылка КАК Ссылка
    ИЗ
        Документ.ПриобретениеТоваровУслуг.Товары КАК Товары
    ГДЕ
        Товары.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.БезНДС)
) КАК ТаблицаБезНДС ПО Док.Ссылка = ТаблицаБезНДС.Ссылка

После этого в настройках динамического списка (вкладка «Условное оформление») достаточно добавить условие: Если ЕстьБезНДС Равно Истина Тогда ЦветФона = WebЦвета.СветлоЗеленый. Платформа сама оптимизирует этот запрос.

Способ 2. Программное оформление в событии ПриПолученииДанныхНаСервере

Если по каким-то причинам (например, работа в расширении с закрытым запросом или слишком сложная логика) изменить запрос нельзя, воспользуемся расширением формы и обработчиком события ПриПолученииДанныхНаСервере. Рассмотрим правильную реализацию этого метода.

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

Проанализируем правильный алгоритм работы в процедуре ПриПолученииДанныхНаСервере:

  1. Сначала мы получаем массив ключей (идентификаторов строк), которые платформа подготовила для отображения на экране.
  2. Одним запросом получаем все необходимые дополнительные данные для этих ключей.
  3. Обходим коллекцию Строки и устанавливаем параметры оформления.

Рассмотрим пример кода для списка документов:


&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
    
    // 1. Получаем список ссылок, которые сейчас отображаются на экране
    МассивКлючей = Строки.ПолучитьКлючи();
    МассивСсылок = Новый Массив;
    Для Каждого Ключ Из МассивКлючей Цикл
        // Предполагаем, что ключом является ссылка на документ
        МассивСсылок.Добавить(Ключ);
    КонецЦикла;
    
    Если МассивСсылок.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;

    // 2. Одним запросом выбираем документы, подходящие под условие
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	Товары.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.ПриобретениеТоваровУслуг.Товары КАК Товары
    |ГДЕ
    |	Товары.Ссылка В (&МассивСсылок)
    |	И Товары.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.БезНДС)";
    
    Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
    
    // Выгружаем результат в соответствие для быстрого поиска
    РезультатЗапроса = Запрос.Выполнить().Выгрузить();
    СоответствиеНужныхДокументов = Новый Соответствие;
    Для Каждого Стр Из РезультатЗапроса Цикл
        СоответствиеНужныхДокументов.Вставить(Стр.Ссылка, Истина);
    КонецЦикла;

    // 3. Устанавливаем оформление
    Для Каждого Ключ Из МассивКлючей Цикл
        Если СоответствиеНужныхДокументов[Ключ] <> Неопределено Тогда
            СтрокаСписка = Строки[Ключ];
            // Оформляем все ячейки строки
            Для Каждого ОформлениеЯчейки Из СтрокаСписка.Оформление Цикл
                ОформлениеЯчейки.Значение.УстановитьЗначениеПараметра("ЦветФона", WebЦвета.БледноЗеленый);
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Особенности работы с «Реестром документов» (ERP, КА, УТ)

В современных конфигурациях, таких как 1С:ERP или Комплексная автоматизация, списки документов часто строятся не по таблицам документов, а по регистру сведений РеестрДокументов. В этом случае ключом строки динамического списка является не ДокументСсылка, а объект РегистрСведенийКлючЗаписи.РеестрДокументов.

Выясним, как адаптировать код для такой ситуации. Нам нужно извлечь ссылку на документ из ключа записи регистра. Обычно это поле называется Ссылка или Объект.

Рассмотрим модифицированный фрагмент кода:


// В цикле получения ссылок для реестра:
Для Каждого Ключ Из МассивКлючей Цикл
    // Ключ - это РегистрСведенийКлючЗаписи
    // Извлекаем ссылку на сам документ для запроса
    МассивСсылок.Добавить(Ключ.Ссылка); 
КонецЦикла;

// В финальном цикле оформления:
Для Каждого КлючИзСписка Из МассивКлючей Цикл
    // Ищем в результате запроса по ссылке, хранящейся в ключе
    Если СоответствиеНужныхДокументов[КлючИзСписка.Ссылка] <> Неопределено Тогда
        СтрокаСписка = Строки[КлючИзСписка];
        СтрокаСписка.Оформление.ЦветФона.Установить(WebЦвета.Красный);
    КонецЕсли;
КонецЦикла;

Типичные ошибки и советы по оптимизации

Проанализируем основные моменты, которые помогут сделать ваш код надежнее:

Подведем итог: наиболее правильный путь — это вынесение логики в запрос динамического списка. Если это невозможно, используйте ПриПолученииДанныхНаСервере, но строго соблюдайте принцип пакетной обработки данных: один запрос на весь массив видимых строк. Это обеспечит плавную работу интерфейса даже при больших объемах данных.

← На главную