При разработке документации и обработке табличных частей в «1С:Предприятие» часто возникает задача упорядочить не всю таблицу целиком, а только определенную ее группу. Например, в табличной части документа присутствуют разделители или группы товаров, и отсортировать по наименованию требуется только строки с 5-й по 10-ю, не затрагивая остальные позиции.
Стандартный метод Сортировать(), доступный у объекта ТабличнаяЧасть или ТаблицаЗначений, производит сортировку всех записей без исключения. Разберем по шагам, как правильно и оптимально решить эту задачу с помощью программного кода.
Рассмотренный на форуме подход заключается в том, что нужные строки отбираются в отдельный массив, выгружаются во вспомогательную таблицу значений или список значений, где производится сортировка, после чего отсортированные данные возвращаются обратно в исходную табличную часть с помощью функции ЗаполнитьЗначенияСвойств().
Проанализируем пример кода с использованием таблицы значений:
// Указываем номера строк (включая начальную и конечную)
НачС = 5;
КонС = 10;
// Формируем массив ссылок на строки табличной части
Масс = Новый Массив;
Для к = НачС - 1 По КонС - 1 Цикл
Масс.Добавить(Товары.Получить(к));
КонецЦикла;
// Выгружаем выбранные строки во вспомогательную таблицу значений
НьюТЗ = Товары.Выгрузить(Масс);
// Сортируем полученный диапазон по нужной колонке
НьюТЗ.Сортировать("Номенклатура");
// Переносим отсортированные данные обратно в исходную ТЧ
Для к = НачС - 1 По КонС - 1 Цикл
стр = Товары.Получить(к);
ЗаполнитьЗначенияСвойств(стр, НьюТЗ.Получить(к - НачС + 1));
КонецЦикла;
Если требуется отсортировать строки между несколькими разделителями (например, от текущего разделителя до следующего), можно предварительно определить индексы строк программно и отсортировать элементы с помощью списка значений:
ТекРазделитель = ЭлементыФормы.Товары.ТекущаяСтрока;
НачСтрока = ТекРазделитель.НомерСтроки + 1;
КонСтрока = ПолучитьКонечнуюСтрокуПоРазделителю(ТекРазделитель);
Список = Новый СписокЗначений;
Для Н = НачСтрока - 1 По КонСтрока - 1 Цикл
СтрокаТЧ = Товары.Получить(Н);
Список.Добавить(СтрокаТЧ, СтрокаТЧ.Номенклатура.Наименование);
КонецЦикла;
// Сортировка по представлению (по алфавиту)
Список.СортироватьПоПредставлению(НаправлениеСортировки.Возраст);
М = 0;
Для К = НачСтрока - 1 По КонСтрока - 1 Цикл
СтрокаТЧ = Товары.Получить(К);
ЗаполнитьЗначенияСвойств(СтрокаТЧ, Список.Получить(М).Значение);
М = М + 1;
КонецЦикла;
Еще один универсальный подход — выгрузка всей табличной части в таблицу значений с созданием дополнительной числовой колонки для определения порядка строк.
Выгрузить().Порядок с типом Число.Порядок запишем их текущий индекс.Сортировать("Порядок").Загрузить().При использовании описанных алгоритмов необходимо учитывать следующие моменты:
1. Подчиненные табличные части и ключи связи
Использование ЗаполнитьЗначенияСвойств() копирует реквизиты строк, но сохраняет исходные физические объекты строк и их идентификаторы. Если к табличной части привязаны подчиненные таблицы (например, серии или комплектующие по полю КлючСвязи), простое копирование данных между строками может привести к рассинхронизации подчиненных строк.
2. Сортировка ссылочных типов по умолчанию
При вызове метода Сортировать() по колонке с ссылочным типом (например, СправочникСсылка.Номенклатура), платформа производит сортировку по внутреннему уникальному идентификатору (GUID), а не по алфавитному названию. Для правильной сортировки по наименованию выгружайте представление в отдельную колонку или используйте СписокЗначений.СортироватьПоПредставлению().
3. Различия между обычными и управляемыми формами
В управляемых формах на клиенте коллекция строк имеет тип ДанныеФормыКоллекция. Для выполнения скоординированной сортировки больших массивов выносите выгрузку и обработку табличной части на сервер в контексте объекта Объект.Товары.