При работе с динамическими списками в 1С часто возникает задача применить условное оформление (например, изменить цвет фона или текста) к определенным строкам или ячейкам, основываясь на значении реквизита. Однако, если этот реквизит является вложенным элементом ссылочного типа (например, Список.Ссылка.Мой_Реквизит), стандартные средства условного оформления могут не справиться с этой задачей, выдавая ошибку "Поле не найдено" или просто не отображая нужный реквизит в списке доступных полей.
Рассмотрим подробнее эту проблему и выясним, почему она возникает, а затем предложим несколько эффективных способов ее решения.
Динамические списки в 1С функционируют на базе Системы Компоновки Данных (СКД). СКД генерирует запрос к базе данных, который извлекает необходимую информацию для отображения на форме. Когда вы пытаетесь применить условное оформление к полю, которое является вложенным реквизитом ссылки (например, Ссылка.Статус, где Статус — это реквизит объекта, на который ссылается поле Ссылка), СКД по умолчанию может не включать это вложенное поле в свой набор данных. Она 'видит' только саму ссылку, но не 'заглядывает' внутрь нее, чтобы получить значение нужного реквизита для целей условного оформления. Следовательно, для СКД это поле просто не существует в текущем контексте набора данных, что приводит к ошибке "Поле не найдено".
Дополнительно, для таких вложенных реквизитов часто недоступен флажок "Использовать всегда" в свойствах колонки динамического списка. Этот флажок обычно применяется к полям, которые должны быть гарантированно получены из базы данных, но он не предназначен для автоматического извлечения реквизитов по ссылке, если они не включены в основной запрос.
Наиболее эффективным и часто используемым способом решения этой проблемы является изменение запроса динамического списка таким образом, чтобы нужный вложенный реквизит был явно выбран и стал доступен как отдельное поле верхнего уровня. Это позволяет СКД 'увидеть' и использовать его для условного оформления.
Установим флажок "Произвольный запрос":
Для начала, перейдем в конфигураторе к форме списка, где расположен ваш динамический список. В свойствах элемента формы, который представляет собой динамический список (обычно это элемент типа 'Таблица' с источником 'Список'), найдем свойство "Произвольный запрос" и установим для него значение Истина.
Отредактируем текст запроса:
После установки флажка "Произвольный запрос" станет доступно поле "Текст запроса". Откроем его для редактирования. Нам необходимо дополнить существующий запрос таким образом, чтобы он явно выбирал нужный вложенный реквизит. Если динамический список основан на документе, в котором есть реквизит Статус (булево), а сам список отображает поле Ссылка этого документа, то мы можем получить Статус следующим образом:
ВЫБРАТЬ
ДокументОтпуск.Ссылка,
ДокументОтпуск.Дата,
ДокументОтпуск.Номер,
ДокументОтпуск.Ссылка.Статус КАК СтатусДокумента
ИЗ
Документ.Отпуск КАК ДокументОтпуск
В этом примере мы добавили строку ДокументОтпуск.Ссылка.Статус КАК СтатусДокумента. Здесь СтатусДокумента — это псевдоним, который мы присваиваем нашему вложенному реквизиту. Именно этот псевдоним будет восприниматься СКД как новое, самостоятельное поле верхнего уровня в наборе данных динамического списка.
Если реквизит находится в другом объекте, связанном с основным полем списка, можем использовать ЛЕВОЕ СОЕДИНЕНИЕ. Например, если Статус находится в регистре сведений, связанном со Ссылкой:
ВЫБРАТЬ
ДокументОтпуск.Ссылка,
ДокументОтпуск.Дата,
ДокументОтпуск.Номер,
РегистрСоСтатусами.Статус КАК СтатусДокумента
ИЗ
Документ.Отпуск КАК ДокументОтпуск
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтатусыДокументов КАК РегистрСоСтатусами
ПО ДокументОтпуск.Ссылка = РегистрСоСтатусами.Документ
Используем новое поле в условном оформлении:
После того как вы сохранили измененный запрос, поле СтатусДокумента (или как вы его назвали) станет доступно для условного оформления. Теперь вы можете:
Настроить условное оформление через конфигуратор: Откройте свойства формы, перейдите на вкладку "Условное оформление", добавьте новый элемент. В условиях отбора выберите поле СтатусДокумента и укажите нужное условие (например, "Равно Ложь"). В оформляемых полях укажите ту колонку формы, которую хотите изменить (например, всю строку или конкретную колонку).
Настроить условное оформление программно: Об этом способе мы поговорим чуть ниже, он также потребует обращения к новому полю СтатусДокумента.
Особенности производительности:
Использование произвольного запроса не всегда приводит к замедлению работы динамического списка. Динамические списки в любом случае выполняют запросы к базе данных при каждом обновлении. Произвольный запрос лишь дает нам полный контроль над тем, какие данные и как будут извлечены. Если запрос оптимизирован (используются индексы, избегаются избыточные соединения), производительность останется на приемлемом уровне. Платформа 1С оптимизирует работу динамических списков, получая данные порциями, что позволяет эффективно работать с большими объемами информации.
Скрытие вспомогательной колонки:
Если поле СтатусДокумента нам нужно только для условного оформления и не должно отображаться пользователю, мы можем добавить его как отдельную колонку в динамический список на форме, но затем скрыть эту колонку. Для этого в свойствах колонки на форме установим свойство "Видимость" в Ложь или уберем ее из "Изменения состава колонок" для пользователя. Это позволит использовать значение поля для оформления, не перегружая интерфейс.
Даже если вы модифицировали запрос динамического списка, иногда удобнее или необходимо настроить условное оформление программно. Это дает большую гибкость и позволяет реализовать более сложные сценарии.
Рассмотрим пример кода, который применяет условное оформление, окрашивая строку в красный цвет, если значение поля СтатусДокумента равно Ложь. Предположим, что вы уже выполнили Шаг 1 (модифицировали запрос).
Обычно такой код размещается в процедуре формы, выполняющейся при создании формы на сервере, например, в обработчике события ПриСозданииНаСервере или ПриОткрытии.
Прежде чем приводить скорректированный пример, давайте проанализируем попытку из оригинального обсуждения и поймем, что было упущено. В сообщении 13 автор пытался сделать следующее:
&НаСервере
Процедура ш_ПриОткрытииПередНаСервере()
УО = Список.КомпоновщикНастроек.Настройки.УсловноеОформление.Элементы;
Если УО.Количество() > 0 Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Условное оформление уже задано. Команда не выполнена.";
Сообщение.Сообщить();
Возврат;
КонецЕсли;
ЭлементУО = УО.Добавить();
ЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветФона", WebЦвета.Красный);
ЭлементУсловия = ЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Статус");
ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементУсловия.ПравоеЗначение = Ложь;
Список.КомпоновщикНастроек.ЗагрузитьНастройки(Список.КомпоновщикНастроек.Настройки);
КонецПроцедуры
Ключевая проблема здесь, как верно заметили в сообщении 14, заключалась в том, что не были указаны оформляемые поля. То есть, условие для отбора было задано, но не было сказано, к каким элементам формы (колонкам или всей строке) следует применять это оформление. Также, в данном случае, поле "Статус", возможно, еще не было доступно в наборе данных списка.
Правильный подход, использующий новое поле СтатусДокумента из произвольного запроса, будет выглядеть так:
&НаСервере
Процедура УстановитьУсловноеОформлениеСписка()
// Очищаем текущие элементы условного оформления, чтобы не дублировать
Список.КомпоновщикНастроек.Настройки.УсловноеОформление.Элементы.Очистить();
// Создаем новый элемент условного оформления
ЭлементУО = Список.КомпоновщикНастроек.Настройки.УсловноеОформление.Элементы.Добавить();
// --- Настраиваем оформление ---
// Устанавливаем цвет фона (например, красный)
ЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветФона", WebЦвета.Красный);
// --- Настраиваем условие отбора ---
// Добавляем элемент отбора
ЭлементОтбора = ЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// Указываем левое значение (поле из нашего запроса)
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СтатусДокумента");
// Указываем вид сравнения
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
// Указываем правое значение (условие: если СтатусДокумента = Ложь)
ЭлементОтбора.ПравоеЗначение = Ложь;
// Включаем использование элемента отбора
ЭлементОтбора.Использование = Истина;
// --- Настраиваем оформляемые поля ---
// Это критически важный шаг! Указываем, какие поля формы будут оформляться.
// Если нужно оформить всю строку, указываем поле "Ссылка" (или главное поле списка)
ОформляемоеПоле = ЭлементУО.Поля.Элементы.Добавить();
// Мы хотим, чтобы оформлялась колонка "Ссылка" (она же вся строка)
ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("Ссылка");
// Если нужно оформить конкретную колонку, указываем имя этой колонки, например, "Дата"
// ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("Дата");
// Загружаем обновленные настройки компоновщика данных списка
Список.КомпоновщикНастроек.ЗагрузитьНастройки(Список.КомпоновщикНастроек.Настройки);
КонецПроцедуры
В этом коде мы используем объект ПолеКомпоновкиДанных для указания как поля отбора ("СтатусДокумента"), так и оформляемого поля ("Ссылка"). Указание оформляемых полей (ЭлементУО.Поля) говорит системе, какие элементы формы должны изменить свое оформление при выполнении условия отбора.
В некоторых случаях, когда необходимо применить очень сложное оформление, или когда возможностей условного оформления СКД недостаточно, или когда вы хотите избежать изменения произвольного запроса, можно использовать обработчик ПриПолученииДанныхНаСервере динамического списка.
Этот обработчик позволяет программно изменять данные и применять оформление к строкам динамического списка *после* того, как они были получены из базы данных и оформлены согласно основным настройкам списка.
Назначение:
Обработчик ПриПолученииДанныхНаСервере вызывается для каждой порции данных, загруженных динамическим списком. В нем мы можем получить доступ к уже загруженным данным и их оформлению.
Возможности:
В этом обработчике вы можете:
Статус по ссылке).ЦветФона, ЦветТекста, Шрифт, Видимость).Когда использовать:
Этот подход полезен, когда:
Пример использования обработчика ПриПолученииДанныхНаСервере для нашего случая с реквизитом Статус:
&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Данные, Отказ)
// Создадим запрос для получения статусов документов
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДокументОтпуск.Ссылка КАК Ссылка,
| ДокументОтпуск.Статус КАК Статус
|ИЗ
| Документ.Отпуск КАК ДокументОтпуск
|ГДЕ
| ДокументОтпуск.Ссылка В(&СписокСсылок)";
// Собираем ссылки на текущие строки, которые были получены в списке
СписокСсылок = Новый Массив;
Для Каждого СтрокаДанных Из Данные.Строки Цикл
СписокСсылок.Добавить(СтрокаДанных.Ссылка);
КонецЦикла;
Если СписокСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Запрос.УстановитьПараметр("СписокСсылок", СписокСсылок);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
// Создаем соответствие для быстрого поиска статуса по ссылке
СоответствиеСтатусов = Новый Соответствие;
Для Каждого СтрокаРезультата Из РезультатЗапроса Цикл
СоответствиеСтатусов.Вставить(СтрокаРезультата.Ссылка, СтрокаРезультата.Статус);
КонецЦикла;
// Применяем оформление
Для Каждого СтрокаДанных Из Данные.Строки Цикл
Статус = СоответствиеСтатусов.Получить(СтрокаДанных.Ссылка);
Если Статус = Ложь Тогда
СтрокаДанных.Оформление.УстановитьЦветФона(WebЦвета.Красный);
// Можно установить цвет текста, шрифт и другие параметры
// СтрокаДанных.Оформление.УстановитьЦветТекста(WebЦвета.Белый);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Ограничения: В этом обработчике недоступен контекст формы, и напрямую изменить настройки динамического списка нельзя. Мы можем оперировать только уже полученными строками и их оформлением.
Индексирование полей: При использовании сложных запросов, соединений или условий отбора в динамических списках всегда убедитесь, что поля, участвующие в этих операциях, проиндексированы в базе данных. Это существенно повысит производительность.
Избегайте полного скрытия строк: Хотя технически возможно полностью скрыть строки с помощью условного оформления (устанавливая Видимость = Ложь), это может привести к некорректному поведению и серьезному замедлению работы, особенно в веб-клиенте. Если нужно скрывать строки, используйте отбор самого динамического списка.
Предпочтение условному оформлению динамического списка: Если задача может быть решена как условным оформлением формы в целом, так и условным оформлением непосредственно элемента "Динамический список", то всегда выбирайте второй вариант. Условное оформление, настроенное для динамического списка, обрабатывается СКД более эффективно и может ускорить открытие формы и ее работу.
Таким образом, для решения проблемы 'Поле не найдено' при условном оформлении вложенных реквизитов, модификация произвольного запроса динамического списка является ключевым шагом, после которого вы сможете успешно применять как конфигураторное, так и программное условное оформление.