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