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

· 9 мин

Содержание

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

Частое заблуждение — что сортировку ускоряет индекс. Нет: ТЗ.Индексы.Добавить() ускоряет поиск строк, а порядок строк не меняет вообще. Ниже — все рабочие способы: от кнопки в пользовательском режиме до сортировки по вычисляемому ключу и через запрос.

Что нужно знать о таблице значений перед сортировкой

Таблица значений (ТаблицаЗначений) — универсальная коллекция в памяти: строки, колонки, у каждой колонки может быть описание типов. Она живёт только на сервере и в толстом клиенте. В тонком клиенте и веб-клиенте этого типа нет — на управляемой форме вы работаете с её «отражением», коллекцией данных формы.

Что влияет на результат сортировки:

  • 🔤 Тип значений в колонке. Числа сравниваются как числа, строки — как строки, даты — хронологически.
  • 🔗 Ссылки. Справочники и документы по умолчанию сравниваются не по наименованию, а по внутреннему представлению ссылки. Отсюда «случайный» порядок, если сортировать по Номенклатура.
  • 🧩 Смешанные типы. Если в колонке без описания типов лежат и числа, и строки, значения разных типов группируются по типу, и порядок внутри получается неочевидным.
  • 📌 Порядок строк хранится. После сортировки индекс строки (ТЗ.Индекс(Строка)) меняется. Если вы запомнили номера строк до сортировки, после неё они указывают на другие строки.

Сортировка таблиц в пользовательском режиме, без кода

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

Табличная часть документа или таблица на форме

  1. Выделите любую ячейку в нужной колонке.
  2. Откройте меню Ещё в командной панели таблицы.
  3. Выберите Сортировать по возрастанию или Сортировать по убыванию.

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

В проведённом документе сортировка табличной части меняет номера строк. Если на номера строк ссылается другая табличная часть (например, серии или коды маркировки по номеру строки), сначала проверьте, как это устроено в вашей конфигурации.

Списки справочников и документов

В динамическом списке щёлкните по заголовку колонки — список упорядочится по ней, повторный щелчок меняет направление. Для сортировки по нескольким полям откройте настройки списка через меню Ещё и задайте порядок полей на вкладке сортировки.

Отчёты на СКД

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

Метод Сортировать(): программная сортировка таблицы значений

Синтаксис:

ТаблицаЗначений.Сортировать(<Колонки>, <ОбъектСравнения>);
  • Колонки — строка с именами колонок через запятую. После имени через пробел указывается направление: Возр (по умолчанию) или Убыв. Английские варианты — Asc и Desc.
  • ОбъектСравнения — необязательный параметр, объект СравнениеЗначений. Нужен, когда в колонках ссылки и сортировать их надо по представлению.

Пример 1: одна колонка

ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));

Строка = ТЗ.Добавить(); Строка.Товар = "Бумага А4"; Строка.Сумма = 1200;
Строка = ТЗ.Добавить(); Строка.Товар = "Скрепки";   Строка.Сумма = 150;
Строка = ТЗ.Добавить(); Строка.Товар = "Тонер";     Строка.Сумма = 4300;

ТЗ.Сортировать("Сумма Убыв");
// Порядок: Тонер 4300, Бумага А4 1200, Скрепки 150

Пример 2: несколько колонок

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

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

Пример 3: ссылки по наименованию

ТЗ.Сортировать("Номенклатура", Новый СравнениеЗначений);

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

💡 Если нужен алфавитный порядок только по одной ссылочной колонке, а остальные — числа и даты, СравнениеЗначений всё равно можно передавать: на примитивные типы он не влияет, просто работает чуть медленнее.

Сортировка на управляемой форме

Если таблица — реквизит формы, на клиенте у вас коллекция данных формы. У неё тоже есть метод Сортировать() с той же строкой колонок:

&НаКлиенте
Процедура УпорядочитьПоСумме(Команда)
    Объект.Товары.Сортировать("Сумма Убыв");
КонецПроцедуры

Если нужен СравнениеЗначений или сложная логика, преобразуйте реквизит в таблицу значений на сервере:

&НаСервере
Процедура УпорядочитьНаСервере()
    ТЗ = РеквизитФормыВЗначение("ТаблицаДанных");
    ТЗ.Сортировать("Номенклатура, Сумма Убыв", Новый СравнениеЗначений);
    ЗначениеВРеквизитФормы(ТЗ, "ТаблицаДанных");
КонецПроцедуры

Табличная часть объекта

Надёжный путь для табличной части в коде объекта — выгрузить, отсортировать, загрузить обратно:

ТЗ = ДокументОбъект.Товары.Выгрузить();
ТЗ.Сортировать("Номенклатура", Новый СравнениеЗначений);
ДокументОбъект.Товары.Загрузить(ТЗ);

Ручной порядок: переместить одну строку

Иногда нужна не сортировка, а перестановка конкретной строки: поднять итоговую позицию наверх или опустить служебную вниз. Для этого есть метод Сдвинуть(), он принимает строку и смещение (отрицательное — вверх):

Строка = ТЗ.Найти("Итого", "Товар");
Если Строка <> Неопределено Тогда
    ТЗ.Сдвинуть(Строка, -ТЗ.Индекс(Строка)); // в самое начало
КонецЕсли;

Так удобно доводить порядок после Сортировать(), если одна-две строки должны стоять вне общего правила. Положительное смещение двигает строку вниз: ТЗ.Сдвинуть(Строка, 1) опускает её на одну позицию. Выход за границы таблицы вызовет ошибку, поэтому смещение считайте от текущего индекса.

Соседняя коллекция: список значений

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

Список.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
Список.СортироватьПоПредставлению(НаправлениеСортировки.Возр);

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

Индексы таблицы значений: что они дают и чего не делают

Индекс в таблице значений создают так:

ТЗ.Индексы.Добавить("Контрагент, Договор");

Он ускоряет Найти() и НайтиСтроки() по этим колонкам на больших таблицах. На порядок строк индекс не влияет: после его создания строки стоят там же, где стояли.

Когда индекс полезен в связке с сортировкой:

ЗадачаЧто делать
Вывести строки в нужном порядкеСортировать()
Много раз искать строки по ключуИндексы.Добавить() + НайтиСтроки()
Найти и упорядочить найденноеНайтиСтроки() возвращает массив, его в таблицу не сортируют — сначала Сортировать() всю таблицу, потом ищите

💡 Удобный приём: отсортируйте таблицу, затем вызовите НайтиСтроки(). Строки в возвращаемом массиве идут в том порядке, в каком стоят в таблице, — то есть уже упорядоченными.

Как отсортировать дерево значений с иерархией

У дерева значений метод Сортировать() есть у коллекции строк — у корневой и у каждого узла:

Дерево.Строки.Сортировать("Наименование", Истина);

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

Отсортировать только одну ветку:

Ветка = Дерево.Строки[0];
Ветка.Строки.Сортировать("Сумма Убыв", Истина);

Типичная задача — «папки сверху, элементы ниже, внутри по алфавиту». Решается через служебную колонку:

Дерево.Колонки.Добавить("ЭтоГруппаЧисло", Новый ОписаниеТипов("Число"));
// при заполнении: Строка.ЭтоГруппаЧисло = ?(Строка.ЭтоГруппа, 0, 1);
Дерево.Строки.Сортировать("ЭтоГруппаЧисло, Наименование", Истина);

Булево тоже сортируется (Ложь раньше Истина), но через число порядок задаётся явно и читается проще.

Сортировка по вычисляемым полям и нестандартным критериям

Сортировать() принимает только имена существующих колонок. Выражения вроде "Количество * Цена" не работают. Решение одно — временная колонка с ключом.

По вычисляемому значению

ТЗ.Колонки.Добавить("Ключ", Новый ОписаниеТипов("Число"));
Для Каждого Строка Из ТЗ Цикл
    Строка.Ключ = Строка.Количество * Строка.Цена;
КонецЦикла;
ТЗ.Сортировать("Ключ Убыв");
ТЗ.Колонки.Удалить("Ключ");

Колонку удаляют после сортировки — порядок строк при этом сохраняется.

По своему порядку значений

Например, статусы должны идти так: «Срочно», «В работе», «Ожидает», остальные — в конце.

Ранги = Новый Соответствие;
Ранги.Вставить("Срочно", 1);
Ранги.Вставить("В работе", 2);
Ранги.Вставить("Ожидает", 3);

ТЗ.Колонки.Добавить("Ранг", Новый ОписаниеТипов("Число"));
Для Каждого Строка Из ТЗ Цикл
    Ранг = Ранги.Получить(Строка.Статус);
    Строка.Ранг = ?(Ранг = Неопределено, 99, Ранг);
КонецЦикла;
ТЗ.Сортировать("Ранг, Дата");
ТЗ.Колонки.Удалить("Ранг");

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

Нужно упорядочить по артикулу номенклатуры, а в таблице лежит только ссылка. Обращение Строка.Номенклатура.Артикул в цикле — это отдельное чтение из базы на каждую строку. Лучше одним запросом:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|    Т.Номенклатура КАК Номенклатура,
|    Т.Количество КАК Количество
|ПОМЕСТИТЬ ВТ
|ИЗ
|    &ТЗ КАК Т
|;
|ВЫБРАТЬ
|    ВТ.Номенклатура КАК Номенклатура,
|    ВТ.Количество КАК Количество
|ИЗ
|    ВТ КАК ВТ
|УПОРЯДОЧИТЬ ПО
|    ВТ.Номенклатура.Артикул,
|    ВТ.Количество УБЫВ";
Запрос.УстановитьПараметр("ТЗ", ТЗ);
ТЗ = Запрос.Выполнить().Выгрузить();

Таблица, передаваемая в запрос, должна иметь колонки с описанием типов. Колонка, созданная без ОписаниеТипов, вызовет ошибку при выполнении запроса.

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

СпособКогда подходитОграничения
Сортировать("Колонка")Примитивные типы, готовые колонкиТолько существующие колонки
+ СравнениеЗначенийСсылки по представлениюМедленнее на больших объёмах
Временная колонкаФормулы, свой порядок значенийНужен цикл заполнения
Запрос с УПОРЯДОЧИТЬ ПОРеквизиты ссылок, сложные условияТолько сервер, типизированные колонки

Сортировка больших таблиц: как не тормозить

На таблицах в десятки и сотни тысяч строк заметны мелочи.

  • 🗄️ Сортируйте в источнике. Если таблица получена запросом, добавьте УПОРЯДОЧИТЬ ПО в сам запрос. СУБД упорядочит данные до выгрузки, и Сортировать() не понадобится.
  • 🔁 Один раз, а не в цикле. Ошибка, которую часто видно в обработках: Сортировать() внутри цикла добавления строк. Добавьте все строки, затем отсортируйте один раз.
  • 🏷️ Не передавайте СравнениеЗначений без нужды. Сравнение по представлению требует получить текст каждой ссылки.
  • ✂️ Нужны первые N строк — берите ВЫБРАТЬ ПЕРВЫЕ N ... УПОРЯДОЧИТЬ ПО в запросе, а не сортируйте и обрезайте всю таблицу.
  • 🖥️ Работайте на сервере. Передача большой таблицы между клиентом и сервером ради сортировки обходится дороже самой сортировки.
  • 🧮 Сократите колонки. Метод Скопировать() с перечнем колонок даёт облегчённую таблицу, если для вывода нужна только часть полей.
Короткая = ТЗ.Скопировать(, "Контрагент, Сумма");
Короткая.Свернуть("Контрагент", "Сумма");
Короткая.Сортировать("Сумма Убыв");

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

Ошибки при сортировке и как их исправить

Диагностика: выберите симптом

Частые вопросы

Как отсортировать массив в 1С?
У массива нет метода сортировки. Загрузите его в СписокЗначений через ЗагрузитьЗначения, вызовите СортироватьПоЗначению(НаправлениеСортировки.Возр) и выгрузите обратно через ВыгрузитьЗначения.
Сохраняется ли порядок строк с одинаковым ключом?
Гарантию сохранения исходного порядка равных строк лучше не закладывать. Если порядок важен, добавьте в строку сортировки вторую колонку, например номер строки или дату.
Можно ли отсортировать таблицу значений без учёта регистра букв?
Добавьте временную колонку со значением ВРег(Строка.Наименование), отсортируйте по ней и удалите колонку.
Чем Сортировать отличается от Свернуть?
Сортировать только меняет порядок строк. Свернуть группирует строки по указанным колонкам и суммирует числовые, количество строк уменьшается.
Как вернуть исходный порядок после сортировки?
Перед сортировкой добавьте колонку с номером строки и заполните её в цикле. Чтобы вернуть порядок, отсортируйте по этой колонке.