Почему условное оформление динамического списка не работает для реквизитов табличных частей и как это исправить?

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

При разработке интерфейсов на управляемых формах программисты часто сталкиваются с задачей: нужно раскрасить строку в списке документов, если в его табличной части содержится определенное значение. На первый взгляд, решение кажется очевидным — добавить в Условное оформление динамического списка путь к данным через точку, например, Ссылка.Начисления.Сотрудник.НужныйРеквизит. Однако на практике такое оформление ведет себя непредсказуемо: одни строки красятся, другие — нет, а цвет может меняться при простом обновлении списка или перемещении курсора.

В этой статье мы подробно разберем, почему стандартный механизм «через точку» не подходит для коллекций, выясним причины «плавающего» оформления и научимся настраивать динамический список правильно и производительно.

Анализируем причину проблемы: механизм SQL Join

Разберем ситуацию с точки зрения системы управления базами данных (СУБД). Динамический список — это, по сути, визуальное представление результата SQL-запроса. Когда мы обращаемся к реквизиту табличной части через точку (Ссылка.ТабличнаяЧасть.Поле), платформа 1С вынуждена выполнить соединение (обычно LEFT JOIN) основной таблицы документа с таблицей его табличной части.

Проанализируем, что происходит, если в документе 10 строк в табличной части:

  1. Запрос к базе данных возвращает не одну строку для этого документа, а десять.
  2. Динамический список ожидает уникальные ссылки, поэтому он пытается «схлопнуть» эти данные обратно в одну строку для отображения пользователю.
  3. Механизм Условного оформления (УО) при этом получает на вход массив данных. Поскольку для одной строки списка в базе существует несколько разных значений в ТЧ, система выбирает произвольное из них (чаще всего из первой попавшейся физически записи).

Именно поэтому возникает эффект «лотереи»: если первая строка в ТЧ соответствует условию — документ покрасится. Если условию соответствует только пятая строка ТЧ, а первая — нет, то с высокой долей вероятности документ останется бесцветным, так как УО «увидело» только данные первой строки.

Почему отбор работает, а оформление — нет?

Многие разработчики замечают странный нюанс: если установить Отбор по тому же самому полю (Ссылка.Начисления.Сотрудник = Значение), то документ корректно попадает в список. Почему же оформление дает сбой?

Выясним причину в различии логики формирования запросов:

Проблема «плавающей» раскраски и кэширования

Рассмотрим, почему оформление может меняться при прокрутке списка или нажатии кнопки «Обновить». Динамический список работает в режиме выборки данных порциями (chunking). Он подгружает записи пачками по 20–45 штук.

Когда вы листаете список или меняете фокус строки, платформа может пересчитывать данные. Если порядок записей в СУБД (физический порядок на диске) изменился или данные в кэше обновились частично, при очередном соединении таблиц «первой» строкой ТЧ может оказаться другая запись. В результате флаг оформления в памяти клиента пересчитывается, и цвет строки внезапно меняется прямо на глазах у пользователя.

Правильное решение: использование произвольного запроса

Чтобы условное оформление работало стабильно, мы должны избавиться от неопределенности. Нам нужно передать в механизм УО готовое логическое поле (флаг), которое уже содержит однозначный ответ: «Нужно красить этот документ или нет».

Рассмотрим по шагам, как это реализовать:

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

Пример правильного запроса для динамического списка:


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

Альтернативный (более производительный) вариант

Проанализируем ситуацию с точки зрения производительности. Если документов и строк в ТЧ очень много, LEFT JOIN с DISTINCT может замедлить работу списка. В таких случаях лучше использовать оператор В (ВЫБРАТЬ...) непосредственно в поле выборки, если ваша версия платформы и СУБД позволяют эффективно выполнять такие подзапросы, либо вынести флаг в отдельную колонку основной таблицы (денормализация), если это критически важный функционал.

Однако для большинства задач подходит использование ВЫБОР КОГДА Ссылка В (...):


ВЫБРАТЬ
    ДокументПремия.Ссылка,
    ВЫБОР
        КОГДА ДокументПремия.Ссылка В (
            ВЫБРАТЬ ТЧ.Ссылка 
            ИЗ Документ.Премия.Начисления КАК ТЧ 
            ГДЕ ТЧ.Сотрудник.МойРеквизит = &Значение
        ) ТОГДА ИСТИНА
        ИНАЧЕ ЛОЖЬ
    КОНЕЦ КАК ФлагОформления
ИЗ
    Документ.Премия КАК ДокументПремия

Настройка условного оформления на форме

После того как мы подготовили поле ФлагОформления (или НужноКрасить) в запросе, нам остается лишь правильно настроить само оформление в конфигураторе или программно:

Важный момент: Не забудьте включить созданное поле в состав данных динамического списка. Если вы не планируете показывать этот флаг пользователю, снимите галочку Видимость в настройках колонки, но само поле должно присутствовать в выборке запроса.

Выводы и рекомендации

Подведем итоги нашего исследования:

  1. Никогда не используйте обращения к табличным частям через точку в настройках Условного оформления. Это архитектурная ошибка, приводящая к непредсказуемым результатам.
  2. Всегда вычисляйте признак оформления в основном запросе динамического списка. Это гарантирует, что на одну строку списка будет приходиться ровно одно значение флага.
  3. Помните о производительности. Любое обращение к табличным частям в списке — это дополнительная нагрузка на СУБД. Используйте индексированные поля для фильтрации во вложенных запросах.

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

← На главную