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