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

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

Как сортировать дерево в 1С

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

Дерево значений в 1С — иерархическая структура, и стандартная сортировка таблицы значений к ней напрямую не применима. Разработчики сталкиваются с задачей упорядочить строки дерева по колонке: по наименованию, по сумме, по дате — при этом сохранив связь «родитель–потомок». Встроенный язык предоставляет для этого метод Сортировать(), но у него есть особенности, которые важно понимать до написания кода.

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

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

Объект ДеревоЗначений состоит из колонок и коллекции строк, где каждая строка в свою очередь содержит собственную коллекцию подчинённых строк. Когда вы вызываете метод сортировки, платформа упорядочивает строки внутри каждой коллекции отдельно: корневые строки сортируются между собой, дети каждого родителя — только внутри своего родителя. Строка никогда не «перепрыгнет» в другую ветку.

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

Сортировка дерева значений методом Сортировать

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

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

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

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

1c
Дерево.Сортировать("Группа Возр, Сумма Убыв", Истина);

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

Когда дерево отображается на управляемой форме как реквизит типа ДеревоЗначений, прямого метода сортировки у реквизита формы нет. Нужно получить объект дерева, отсортировать его и вернуть обратно в форму. Делается это через РеквизитФормыВЗначение и ЗначениеВРеквизитФормы.

&НаСервере

Процедура ОтсортироватьДеревоНаСервере()

Дерево = РеквизитФормыВЗначение("ДеревоСтрок");

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

ЗначениеВРеквизитФормы(Дерево, "ДеревоСтрок");

КонецПроцедуры

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

Сортировка через запрос с итогами по иерархии

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

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

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка,

| Номенклатура.Наименование КАК Наименование

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

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

| Наименование

|ИТОГИ ПО

| Ссылка ТОЛЬКО ИЕРАРХИЯ";

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

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

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

При ручном построении дерева (заполнением строк в коде) сортировка выполняется после полного заполнения. Не вызывайте Сортировать после добавления каждой строки — это лишние вычисления. Заполните дерево целиком, затем отсортируйте один раз с параметром Истина.

Порядок действий при ручном построении
  1. 1
    Создайте дерево значений и опишите колонки с нужными типами
  2. 2
    Заполните строки всех уровней иерархии
  3. 3
    Вызовите Дерево.Сортировать("Колонка Возр", Истина) один раз
  4. 4
    Выведите дерево на форму или обработайте дальше
  5. 5
    Проверьте порядок на корневом уровне и внутри вложенных ветвей

Типичные ошибки и ограничения

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

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

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

Проверка результата и альтернативные подходы

После сортировки проверьте порядок минимум на двух уровнях: корневые строки и дочерние строки хотя бы одной ветки с несколькими элементами. Полезно временно вывести дерево в табличный документ или на форму и визуально убедиться, что иерархия не «сломалась» — родители и потомки остались на своих местах.

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

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

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

Порядок корневых строк
Норма

Строки идут по возрастанию/убыванию значения колонки

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

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

Порядок внутри ветвей
Норма

Дочерние строки каждого родителя тоже отсортированы

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

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

Целостность иерархии
Норма

Каждая строка осталась под своим родителем

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

Строки перемешались между ветками — значит, сортировалась не та структура

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

Можно ли отсортировать дерево по нескольким колонкам?

Да. Перечислите колонки через запятую в первом параметре: Дерево.Сортировать("Группа Возр, Наименование Возр", Истина). Сравнение идёт слева направо: при равенстве первой колонки учитывается вторая.

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

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

Как отсортировать только один уровень дерева?

Вызовите Сортировать у коллекции строк нужного уровня: например, СтрокаРодитель.Строки.Сортировать("Наименование") — отсортируются только дети конкретного родителя.

Работает ли метод Сортировать на управляемой форме напрямую?

Нет. Реквизит формы нужно преобразовать в объект через РеквизитФормыВЗначение на сервере, отсортировать и вернуть через ЗначениеВРеквизитФормы.

Что быстрее: сортировка дерева или упорядочивание в запросе?

При больших объёмах быстрее упорядочивание в запросе, так как сортировку выполняет СУБД. Сортировка дерева на встроенном языке оправдана для небольших деревьев или данных, собранных не запросом.

Итог

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

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