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

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При разработке на платформе 1С:Предприятие 8.2 (или в режиме совместимости, как в случае с УТ 10.3) программисты часто сталкиваются с жесткими ограничениями стандартных механизмов отображения данных. Одна из таких проблем — невозможность отсортировать ДокументСписок по сложному алгоритму или по порядку, полученному из внешнего запроса. Рассмотрим подробнее, почему стандартные средства здесь бессильны и как мы можем решить эту задачу альтернативными способами.

Анализ проблемы: почему ДокументСписок не подходит

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

Проанализируем причину: объект ДокументСписок в обычных формах — это динамическая выборка данных напрямую из таблицы базы данных SQL. Сортировка в таком списке выполняется на уровне СУБД. Чтобы СУБД могла выполнить сортировку, поле должно физически существовать в таблице и, желательно, быть проиндексировано. Любые попытки «подсунуть» список значений для сортировки или использовать событие ПриВыводеСтроки для изменения порядка строк обречены на провал, так как оформление строк происходит уже после того, как порядок данных определен сервером.

Решение №1: Использование Таблицы Значений

Если количество документов в вашем списке не превышает нескольких тысяч, самым простым и надежным решением будет отказ от стандартного типа ДокументСписок в пользу ТаблицыЗначений. Рассмотрим по шагам, как это реализовать:

  1. Создадим на форме новое Табличное поле.
  2. В свойствах этого поля в качестве ТипЗначения выберем ТаблицаЗначений.
  3. Добавим колонки, которые должны видеть пользователи (Ссылка, Дата, Номер и т.д.), а также служебную колонку Приоритет (тип Число).
  4. Напишем код заполнения этой таблицы при открытии формы или нажатии кнопки обновления.

Посмотрим на пример кода, который выполняет запрос и заполняет нашу таблицу:


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

Запрос.УстановитьПараметр("СписокЗаказов", НужныеЗаказы);
// Допустим, приоритет мы вычисляем в самом запросе или передаем извне
РезультатЗапроса = Запрос.Выполнить();

// Выгружаем результат напрямую в таблицу значений на форме
ТаблицаНаФорме = РезультатЗапроса.Выгрузить();
ЭлементыФормы.ТабличноеПолеЗаказы.СоздатьКолонки();

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

Решение №2: Использование ПостроителяОтчета

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

Проанализируем алгоритм реализации:

  1. Разместим на форме ТабличноеПоле.
  2. В коде инициализации формы настроим ПостроительОтчета.

Построитель = Новый ПостроительОтчета;
Построитель.Текст = 
"ВЫБРАТЬ
|	ЗаказПокупателя.Ссылка КАК Ссылка,
|	ЗаказПокупателя.Дата КАК Дата
|ИЗ
|	Документ.ЗаказПокупателя КАК ЗаказПокупателя
|{ГДЕ
|	ЗаказПокупателя.Ссылка.*}
|УПОРЯДОЧИТЬ ПО
|	ЗаказПокупателя.Дата"; // Здесь можно вставить вашу сложную логику

Построитель.ЗаполнитьНастройки();
// Выводим результат в табличное поле
ЭлементыФормы.ТабличноеПоле1.Значение = Построитель.Результат.Выгрузить();
ЭлементыФормы.ТабличноеПоле1.СоздатьКолонки();

Этот метод позволяет динамически менять порядок УПОРЯДОЧИТЬ ПО непосредственно в тексте запроса перед его выполнением. Однако помните, что интерактивность (например, открытие формы документа при двойном клике) придется прописывать вручную в событии Выбор табличного поля.

Почему метод ПриВыводеСтроки не поможет с сортировкой

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


Процедура ДокументСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    // Поиск индекса в списке для определения порядка
    Индекс = СписокПриоритетов.НайтиПоЗначению(ДанныеСтроки.Ссылка);
    ОформлениеСтроки.Ячейки.Приоритет.УстановитьТекст(Индекс);
КонецПроцедуры

Это позволит показать значение приоритета в колонке, но попытка нажать на заголовок этой колонки для сортировки либо не приведет к результату, либо вызовет ошибку. Платформа 1С в обычных формах просто не умеет передавать данные из оформления строк обратно в SQL-запрос для упорядочивания. Сортировка возможна только по тем данным, которые «понимает» база данных.

Резюме для практического применения

Подведем итоги нашего исследования:

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

← На главную