При разработке интерфейсов на управляемых формах программисты часто сталкиваются с задачей: нужно раскрасить строку в списке документов, если в его табличной части содержится определенное значение. На первый взгляд, решение кажется очевидным — добавить в Условное оформление динамического списка путь к данным через точку, например, Ссылка.Начисления.Сотрудник.НужныйРеквизит. Однако на практике такое оформление ведет себя непредсказуемо: одни строки красятся, другие — нет, а цвет может меняться при простом обновлении списка или перемещении курсора.
В этой статье мы подробно разберем, почему стандартный механизм «через точку» не подходит для коллекций, выясним причины «плавающего» оформления и научимся настраивать динамический список правильно и производительно.
Разберем ситуацию с точки зрения системы управления базами данных (СУБД). Динамический список — это, по сути, визуальное представление результата SQL-запроса. Когда мы обращаемся к реквизиту табличной части через точку (Ссылка.ТабличнаяЧасть.Поле), платформа 1С вынуждена выполнить соединение (обычно LEFT JOIN) основной таблицы документа с таблицей его табличной части.
Проанализируем, что происходит, если в документе 10 строк в табличной части:
Именно поэтому возникает эффект «лотереи»: если первая строка в ТЧ соответствует условию — документ покрасится. Если условию соответствует только пятая строка ТЧ, а первая — нет, то с высокой долей вероятности документ останется бесцветным, так как УО «увидело» только данные первой строки.
Многие разработчики замечают странный нюанс: если установить Отбор по тому же самому полю (Ссылка.Начисления.Сотрудник = Значение), то документ корректно попадает в список. Почему же оформление дает сбой?
Выясним причину в различии логики формирования запросов:
WHERE EXISTS или WHERE Ссылка IN (SELECT...). С точки зрения логики это звучит так: «Покажи документ, если в его ТЧ есть ХОТЯ БЫ ОДНА строка, подходящая под условие». Это работает стабильно.Рассмотрим, почему оформление может меняться при прокрутке списка или нажатии кнопки «Обновить». Динамический список работает в режиме выборки данных порциями (chunking). Он подгружает записи пачками по 20–45 штук.
Когда вы листаете список или меняете фокус строки, платформа может пересчитывать данные. Если порядок записей в СУБД (физический порядок на диске) изменился или данные в кэше обновились частично, при очередном соединении таблиц «первой» строкой ТЧ может оказаться другая запись. В результате флаг оформления в памяти клиента пересчитывается, и цвет строки внезапно меняется прямо на глазах у пользователя.
Чтобы условное оформление работало стабильно, мы должны избавиться от неопределенности. Нам нужно передать в механизм УО готовое логическое поле (флаг), которое уже содержит однозначный ответ: «Нужно красить этот документ или нет».
Рассмотрим по шагам, как это реализовать:
Пример правильного запроса для динамического списка:
ВЫБРАТЬ
ДокументПремия.Ссылка КАК Ссылка,
ДокументПремия.Дата КАК Дата,
ДокументПремия.Номер КАК Номер,
ВЫБОР
КОГДА ЕСТЬNULL(ПодзапросТЧ.ЕстьНужныйСотрудник, ЛОЖЬ) ТОГДА
ИСТИНА
ИНАЧЕ
ЛОЖЬ
КОНЕЦ КАК НужноКрасить
ИЗ
Документ.Премия КАК ДокументПремия
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ РАЗЛИЧНЫЕ
ТЧ.Ссылка КАК Ссылка,
ИСТИНА КАК ЕстьНужныйСотрудник
ИЗ
Документ.Премия.Начисления КАК ТЧ
ГДЕ
ТЧ.Сотрудник.МойРеквизит В (&СписокЗначений)
) КАК ПодзапросТЧ ПО ДокументПремия.Ссылка = ПодзапросТЧ.Ссылка
Проанализируем ситуацию с точки зрения производительности. Если документов и строк в ТЧ очень много, LEFT JOIN с DISTINCT может замедлить работу списка. В таких случаях лучше использовать оператор В (ВЫБРАТЬ...) непосредственно в поле выборки, если ваша версия платформы и СУБД позволяют эффективно выполнять такие подзапросы, либо вынести флаг в отдельную колонку основной таблицы (денормализация), если это критически важный функционал.
Однако для большинства задач подходит использование ВЫБОР КОГДА Ссылка В (...):
ВЫБРАТЬ
ДокументПремия.Ссылка,
ВЫБОР
КОГДА ДокументПремия.Ссылка В (
ВЫБРАТЬ ТЧ.Ссылка
ИЗ Документ.Премия.Начисления КАК ТЧ
ГДЕ ТЧ.Сотрудник.МойРеквизит = &Значение
) ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК ФлагОформления
ИЗ
Документ.Премия КАК ДокументПремия
После того как мы подготовили поле ФлагОформления (или НужноКрасить) в запросе, нам остается лишь правильно настроить само оформление в конфигураторе или программно:
ФлагОформления.Важный момент: Не забудьте включить созданное поле в состав данных динамического списка. Если вы не планируете показывать этот флаг пользователю, снимите галочку Видимость в настройках колонки, но само поле должно присутствовать в выборке запроса.
Подведем итоги нашего исследования:
Следуя этим правилам, вы обеспечите стабильную и быструю работу интерфейса, а ваши пользователи будут видеть актуальную и корректную цветовую индикацию данных.