К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как отсортировать таблицу значений в 1С

Как отсортировать таблицу значений в 1С: метод Сортировать, сортировка по нескольким колонкам, по убыванию, через запрос и построитель. Примеры кода и ошибки.

Таблица значений — один из самых используемых объектов встроенного языка 1С. Она хранит промежуточные данные отчетов, результаты обработок, выгрузки из запросов. Почти в любой нетривиальной задаче рано или поздно возникает потребность упорядочить строки: по дате документа, по сумме, по наименованию контрагента или сразу по нескольким колонкам.

В 1С есть несколько способов сортировки таблицы значений: штатный метод Сортировать(), запрос с конструкцией УПОРЯДОЧИТЬ ПО, построитель отчета и ручные алгоритмы. У каждого подхода есть свои условия применения, ограничения по производительности и типичные ошибки, которые приводят к неверному порядку строк или к падению производительности на больших объемах.

Ниже разобраны рабочие варианты с примерами кода, правилами выбора направления сортировки, особенностями сравнения разных типов данных и способами проверить, что результат получился именно таким, как ожидалось.

Метод Сортировать(): базовый синтаксис

Метод Сортировать() вызывается у объекта таблицы значений и принимает строку со списком колонок и направлений. Направление указывается словом Возр (по возрастанию) или Убыв (по убыванию). Если направление не указано, применяется сортировка по возрастанию.

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Номенклатура");

ТЗ.Колонки.Добавить("Сумма");

// ... заполнение таблицы ...

// Сортировка по одной колонке по возрастанию

ТЗ.Сортировать("Сумма");

// Сортировка по убыванию

ТЗ.Сортировать("Сумма Убыв");

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

Имена колонок в строке параметра должны точно совпадать с именами колонок таблицы, включая регистр букв в соответствии с тем, как колонка была создана. Опечатка в имени приведет к ошибке выполнения «Колонка не обнаружена», которая прервет выполнение процедуры.

bsl
ТЗ.Сортировать("Дата Возр, Сумма Убыв");

Сортировка по нескольким колонкам

Часто одного критерия недостаточно: нужно сначала упорядочить по контрагенту, а внутри каждого контрагента — по дате документа. Для этого колонки перечисляются через запятую в порядке приоритета. Сначала строки сравниваются по первой колонке, при равенстве значений — по второй и так далее.

// Сначала по контрагенту (А–Я), внутри — по дате от новых к старым

ТЗ.Сортировать("Контрагент Возр, Дата Убыв");

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

Как типы данных влияют на порядок строк

Сортировка выполняется по правилам сравнения значений платформы, и тип данных колонки напрямую определяет результат. Строки сравниваются посимвольно с учетом регистра и алфавита, числа — по величине, даты — по хронологии, ссылки — по внутреннему представлению, которое не совпадает с алфавитным порядком наименований.

Главная ловушка — колонка составного типа или колонка без явного типа, куда попали значения разных типов. Например, если в колонке «Сумма» часть значений — числа, а часть — строки вида «1 200,50», сортировка не даст ожидаемого числового порядка: платформа сначала упорядочит значения одного типа, затем другого.

Перед сортировкой убедитесь, что колонка имеет корректный тип. При создании колонки задавайте тип явно через Новый ОписаниеТипов("Число") или приводите значения при заполнении. Если таблица получена выгрузкой из запроса, типы обычно уже корректны, но при ручном заполнении через Добавить() тип определяется первым помещенным значением.

Типичные ошибки
01
Сортировка колонки со смешанными типами: числа и строки упорядочиваются отдельными группами, итоговый порядок выглядит случайным
02
Сортировка ссылочной колонки в ожидании алфавитного порядка по наименованию — ссылки сравниваются не по представлению
03
Опечатка в имени колонки: метод падает с ошибкой и прерывает обработку
04
Изменение исходной таблицы методом Сортировать там, где исходный порядок нужен дальше — делайте копию

Сортировка через запрос: когда она лучше

Если данные для таблицы значений получаются запросом, сортировать лучше на уровне запроса с помощью конструкции УПОРЯДОЧИТЬ ПО. Запрос выполняется на сервере СУБД, где сортировка оптимизирована и использует индексы, поэтому на больших объемах это заметно быстрее, чем выгрузка и последующий вызов Сортировать().

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Продажи.Номенклатура КАК Номенклатура,

| СУММА(Продажи.СуммаОборот) КАК Сумма

|ИЗ

| РегистрНакопления.Продажи.Обороты КАК Продажи

|СГРУППИРОВАТЬ ПО

| Продажи.Номенклатура

|УПОРЯДОЧИТЬ ПО

| Сумма УБЫВ";

ТЗ = Запрос.Выполнить().Выгрузить();

Дополнительное преимущество запроса — возможность упорядочить по полю через точку, например УПОРЯДОЧИТЬ ПО Номенклатура.Наименование. В таблице значений такой возможности нет: метод Сортировать() работает только с колонками самой таблицы, и для сортировки ссылок по наименованию пришлось бы добавлять отдельную колонку с наименованием.

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

Сравнение способов сортировки

Метод Сортировать()

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

УПОРЯДОЧИТЬ ПО в запросе

Оптимально при получении данных запросом и для больших объемов. Поддерживает поля через точку и АВТОУПОРЯДОЧИВАНИЕ

Построитель отчета

Удобен, когда порядок должен задавать пользователь в настройках отчета. Избыточен для внутренних служебных таблиц

Ручной алгоритм (пузырек и т.п.)

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

Сортировка по представлению ссылки и нестандартные правила

Типичная задача: таблица содержит колонку со ссылками на номенклатуру, и нужно вывести строки в алфавитном порядке наименований. Метод Сортировать("Номенклатура") упорядочит ссылки по внутренним идентификаторам, а не по алфавиту. Есть два рабочих решения.

Первое — добавить в таблицу служебную колонку, заполнить её наименованиями в цикле и сортировать по ней. После сортировки колонку можно удалить через ТЗ.Колонки.Удалить(). Второе — прогнать таблицу через запрос, поместив её во временную таблицу, и упорядочить по полю Наименование.

ТЗ.Колонки.Добавить("НаименованиеДляСортировки",

Новый ОписаниеТипов("Строка"));

Для Каждого СтрокаТЗ Из ТЗ Цикл

СтрокаТЗ.НаименованиеДляСортировки =

СтрокаТЗ.Номенклатура.Наименование;

КонецЦикла;

ТЗ.Сортировать("НаименованиеДляСортировки Возр");

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

Порядок действий при нестандартной сортировке
  1. 1
    Определите правило порядка и проверьте, выражается ли оно существующими колонками
  2. 2
    Если нет — добавьте служебную колонку с явным типом (число или строка)
  3. 3
    Заполните служебную колонку в цикле по строкам таблицы
  4. 4
    Вызовите Сортировать() по служебной колонке, при необходимости добавив основные колонки вторым приоритетом
  5. 5
    Проверьте первые и последние строки результата, затем удалите служебную колонку

Производительность и ограничения

Метод Сортировать() выполняется в памяти на сервере (или на клиенте в тонком клиенте для таблиц, созданных на клиенте). На таблицах в десятки тысяч строк он работает быстро, но на сотнях тысяч строк время и потребление памяти растут заметно. В таких случаях переносите сортировку в запрос или пересматривайте саму необходимость держать весь объем в таблице значений.

Отдельное ограничение — сортировка на клиенте в управляемых формах. Если таблица значений является реквизитом формы, пользователь может сортировать её интерактивно по щелчку на заголовок колонки, и для этого программный вызов не нужен. Программная сортировка реквизита формы выполняется тем же методом Сортировать(), но вызывать её следует на сервере, если таблица большая, чтобы не гонять данные между клиентом и сервером.

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

Проверка результата сортировки

После сортировки полезно убедиться, что порядок соответствует ожиданиям, особенно при работе со смешанными типами и служебными колонками. Простейший способ — вывести первые и последние строки в сообщения или посмотреть таблицу в отладчике через «Вычислить выражение».

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

Контрольные точки

Как проверить результат

Первые и последние строки таблицы
Норма

Значения ключа соответствуют выбранному направлению (минимум в начале при Возр)

Тревожный признак

Порядок выглядит случайным или сгруппирован по типам

Сравнение соседних строк в цикле
Норма

Каждое следующее значение не меньше предыдущего при Возр

Тревожный признак

Встречаются нарушения порядка — признак смешанных типов

Порядок внутри групп равных значений
Норма

Срабатывает вторая колонка сортировки

Тревожный признак

Строки внутри группы идут хаотично — второй ключ не указан или не работает

Часто задаваемые вопросы

Как отсортировать таблицу значений по убыванию?

Передайте в метод Сортировать() имя колонки с ключевым словом Убыв: ТЗ.Сортировать("Сумма Убыв"). Направление можно задавать для каждой колонки отдельно при сортировке по нескольким полям.

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

Ссылки сравниваются по внутренним идентификаторам, а не по наименованию. Добавьте служебную колонку с наименованием и сортируйте по ней либо выполните сортировку запросом с упорядочиванием по полю Наименование.

Можно ли отсортировать таблицу, не изменяя исходную?

Да. Создайте копию методом ТЗ.Скопировать() и вызовите Сортировать() у копии. Исходная таблица сохранит первоначальный порядок строк.

Что быстрее: Сортировать() или УПОРЯДОЧИТЬ ПО в запросе?

На больших объемах быстрее запрос, так как сортировку выполняет СУБД с использованием индексов. Для небольших таблиц, уже собранных в памяти, разница незначительна, и проще использовать Сортировать().

Как отсортировать по нескольким колонкам с разным направлением?

Перечислите колонки через запятую, указав направление для каждой: ТЗ.Сортировать("Контрагент Возр, Дата Убыв"). Приоритет определяется порядком перечисления.

Почему числа сортируются как строки (1, 10, 2, 25)?

Колонка имеет строковый тип либо в неё попали строковые значения. Задайте колонке тип Число через ОписаниеТипов при создании или преобразуйте значения функцией Число() при заполнении, затем повторите сортировку.

Итог

Что важно запомнить

Базовый инструмент — метод Сортировать() со строкой вида "Колонка Возр, Колонка2 Убыв". Контролируйте типы колонок, для сортировки по представлению ссылок добавляйте служебную колонку, а большие объемы упорядочивайте запросом. Перед сортировкой делайте копию, если исходный порядок еще нужен.