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

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

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

Почему стандартный отбор не работает для вычисляемых колонок?

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

Когда вы добавляете на форму новую колонку, не связанную с реквизитом объекта или табличной части, и заполняете её в событии ПриВыводеСтроки (например, задавая ОформлениеСтроки.ЦветФона или ОформлениеСтроки.Ячейки.Цвет.Значение), эти данные существуют исключительно в оперативной памяти клиента. В самой базе данных этих значений нет. Так как стандартный отбор 1С формирует условия на уровне СУБД, платформа физически не может применить фильтр к данным, которых не существует в таблицах базы данных.

Вариант 1. Программный отбор по массиву ссылок

Если вносить изменения в структуру метаданных нежелательно, можно организовать программный отбор. Для этого создадим на форме отдельную кнопку (или меню), по нажатию на которую будет выполняться запрос с логикой проверки условий, а результат будет передаваться в элемент отбора по полю Ссылка с видом сравнения ВСписке.

Рассмотрим пример реализации обработчика нажатия кнопки:


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

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

Важное ограничение метода: Если в результат запроса попадает несколько тысяч документов, условие ВСписке приведет к формированию громоздкого SQL-запроса с оператором IN (...). Это может существенно снизить производительность СУБД и вызвать задержки при обновлении списка.

Вариант 2. Добавление реквизита в объект или перечисления

Более надежным и быстродействующим решением является хранение вычисленного состояния прямо в базе данных. Посмотрим, как это реализовать по шагам:

  1. Создаем новое ПеречислениеМенеджер (например, СостоянияДокумента со значениями Красный, Желтый, Зеленый).
  2. Добавляем реквизит с типом этого перечисления в нужный документ.
  3. Заполняем значение реквизита при проведении или записи документа.
  4. Для существующих в базе документов выгружаем и перезаписываем значения групповой обработкой.

После добавления реквизита колонка появится в настройках «Установить отбор» формы списка, и отбор будет работать штатно на уровне базы данных с высокой скоростью.

Вариант 3. Использование независимого регистра сведений (Рекомендуемый подход)

Если перезаписывать сами документы нежелательно (чтобы не менять версию данных и не создавать блокировки), лучше всего использовать независимый регистр сведений.

Схема реализации выглядит следующим образом:

  1. Создаем независимый регистр сведений (например, СостоянияДокументов). Измерение — Документ (ссылка), ресурс — ЦветСостояния (перечисление или строка).
  2. В подписке на событие ПриЗаписи или ОбработкаПроведения связанных документов обновляем запись в регистре сведений.
  3. В форме списка документов устанавливаем отбор, связывая критерии с данными регистра сведений, либо выводим список на основе данных регистра.

Оптимизация производительности: ПриПолученииДанных

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

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

← На главную