При разработке на обычных формах 1С 8.x программисты часто сталкиваются с ситуацией, когда стандартного набора реквизитов табличной части (ТЧ) недостаточно для отображения всей необходимой информации. Мы добавляем "виртуальные" колонки программно или через редактор формы, заполняем их в событиях ПриВыводеСтроки или ПриПолученииДанных, но обнаруживаем неприятную особенность: стандартная сортировка по таким колонкам не работает. Платформа просто не "видит" данных для упорядочивания, так как их нет в физической структуре таблицы в базе данных.
В этой статье мы подробно разберем, как обойти это ограничение и заставить таблицу сортироваться по любым данным, которые мы выводим пользователю.
Разберем ситуацию: когда мы используем метод ОформлениеСтроки.Ячейки.ИмяКолонки.Значение = ..., мы лишь отрисовываем текст в интерфейсе. Сама коллекция ТабличнаяЧасть документа об этих данных ничего не знает. Стандартные кнопки командной панели при нажатии обращаются к источнику данных (самой ТЧ), пытаются найти там соответствующее поле и, не находя его, ничего не делают. Проанализируем основные пути решения этой задачи.
Самый простой и производительный способ — сделать колонку "реальной". Рассмотрим пошагово:
Маркировка.ТолькоПросмотр.ГрузыГрузПриИзменении:
Процедура ГрузыГрузПриИзменении(Элемент)
СтрокаТЧ = ЭлементыФормы.Грузы.ТекущиеДанные;
Если ЗначениеЗаполнено(СтрокаТЧ.Груз) Тогда
// Предположим, Маркировка — это реквизит справочника Грузы
СтрокаТЧ.Маркировка = СтрокаТЧ.Груз.Маркировка;
КонецЕсли;
КонецПроцедуры
Преимущество: Сортировка будет работать автоматически силами платформы, так как данные теперь физически присутствуют в табличной части.
Если изменять структуру метаданных нельзя, мы можем реализовать ручную сортировку. Суть метода заключается в том, чтобы выгрузить данные из ТЧ в промежуточную таблицу, добавить туда колонку для сортировки, упорядочить и загрузить обратно.
Рассмотрим алгоритм действий:
ТаблицаЗначений.Посмотрим на пример кода, который выполняет сортировку с помощью запроса (это быстрее, если нужно подтягивать данные из других таблиц):
// Пример сортировки через временную таблицу
ТЗИсточник = Грузы.Выгрузить();
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("ТЗИсточник", ТЗИсточник);
Запрос.Текст =
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТПриемник ИЗ &ТЗИсточник КАК ТЗИсточник;
|ВЫБРАТЬ * ИЗ ВТПриемник КАК ВТПриемник
|УПОРЯДОЧИТЬ ПО ВТПриемник.Груз.Маркировка";
Результат = Запрос.Выполнить().Выгрузить();
Грузы.Загрузить(Результат);
Чтобы пользователь мог инициировать сортировку привычным кликом по шапке таблицы, нам нужно обработать событие ПриНажатииНаЗаголовок у элемента управления ТабличноеПоле. Выясним, как это сделать правильно:
Процедура ГрузыПриНажатииНаЗаголовок(Элемент, Колонка)
Если Колонка.Имя = "Маркировка" Тогда
// Вызываем нашу процедуру сортировки
ВыполнитьРучнуюСортировку("Груз.Маркировка");
// Визуально помечаем направление сортировки (стрелочка)
Если Колонка.СостояниеСортировки = НаправлениеСортировки.Возр Тогда
Колонка.СостояниеСортировки = НаправлениеСортировки.Убыв;
Грузы.Сортировать("Маркировка Убыв"); // Если добавили реквизит
Иначе
Колонка.СостояниеСортировки = НаправлениеСортировки.Возр;
Грузы.Сортировать("Маркировка Возр");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Проанализируем несколько критических моментов, о которых часто забывают при реализации ручной сортировки:
1. Потеря фокуса (текущей строки). Когда мы выполняем метод Загрузить(), объект ТЧ полностью обновляется, и курсор пользователя прыгает на первую строку. Чтобы этого избежать, перед сортировкой нужно запомнить текущую строку:
// Запоминаем текущие данные
ТекущийГруз = ЭлементыФормы.Грузы.ТекущиеДанные.Груз;
// ... выполняем выгрузку, сортировку и загрузку ...
// Пытаемся найти строку обратно
ПараметрыОтбора = Новый Структура("Груз", ТекущийГруз);
НайденныеСтроки = Грузы.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
ЭлементыФормы.Грузы.ТекущаяСтрока = НайденныеСтроки[0];
КонецЕсли;
2. Проблема производительности. Если вы используете ПриВыводеСтроки для получения маркировки через точку (ОформлениеСтроки.ДанныеСтроки.Груз.Маркировка), помните, что это порождает отдельный запрос к базе данных для каждой видимой строки. При сортировке больших таблиц (сотни строк) это может привести к заметным "тормозам". Лучше использовать кэширование данных в Соответствие при открытии формы или при первом обращении.
3. Режим управляемых форм. Если конфигурация позволяет, рассмотрите возможность использования управляемых форм внутри обычного приложения. В управляемом интерфейсе работа с вычисляемыми полями и их сортировкой реализована гораздо гибче на уровне платформенных механизмов компоновки данных.
Мы рассмотрели несколько подходов к решению задачи. Если есть возможность изменять метаданные — добавление реального реквизита в ТЧ является "золотым стандартом", так как это избавляет от написания лишнего кода и гарантирует стабильную работу стандартных механизмов 1С. Если же метаданные менять нельзя, используйте выгрузку в ТЗ с программной обработкой события нажатия на заголовок, не забывая при этом восстанавливать положение курсора для удобства пользователя.