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