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

Программист 1С v8.3 (Обычные формы)
← На главную

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

Причина ограничения: почему нельзя сортировать «через точку»

Проанализируем архитектуру работы обычных форм. Объект ДокументСписок напрямую связан с соответствующей таблицей в базе данных (SQL). Когда пользователь нажимает на заголовок колонки для сортировки, платформа генерирует SQL-запрос с предложением ORDER BY. Проблема заключается в том, что в таблице документов физически нет поля Очередность, оно находится в другой таблице справочника. Стандартный механизм ДокументСписок в ОФ не умеет автоматически выполнять JOIN (соединение таблиц) для целей сортировки, в отличие от Динамического списка в управляемых формах.

Решение 1: Денормализация данных (дублирование реквизита)

Рассмотрим самый производительный с точки зрения пользователя вариант. Он заключается в том, чтобы перенести «далекий» реквизит непосредственно в сам документ. Это позволит платформе использовать стандартные индексы таблицы документа.

  1. Создание реквизита: Добавим в документ реквизит ПорядокСтатуса с типом Число. Обязательно установим для него свойство «Индексировать».
  2. Автоматизация обновления: Чтобы данные оставались актуальными, нам необходимо обновлять это поле при каждом изменении статуса в документе или при изменении очередности в самом справочнике статусов.

Для обновления данных при записи документа используем следующий подход в модуле объекта:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если ЗначениеЗаполнено(СтатусДокумента) Тогда
        ЭтотОбъект.ПорядокСтатуса = СтатусДокумента.Очередность;
    КонецЕсли;
КонецПроцедуры

Однако этого недостаточно. Если пользователь изменит значение Очередность в справочнике Статусы, порядок в документах станет неверным. Проанализируем, как решить эту проблему с помощью Подписки на события. Создадим подписку на событие ПриЗаписи для справочника Статусы:


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

Важно: Этот метод требует «перезаписи» документов, что может быть критично для больших баз. Однако это единственный способ сохранить стандартный функционал списка с высокой скоростью работы.

Решение 2: Использование Таблицы Значений (ТЗ) как источника данных

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

  1. Удаляем с формы стандартный элемент списка.
  2. Добавляем ТабличноеПоле и программно заполняем его через запрос.
  3. В запросе мы можем легко обратиться к реквизиту справочника «через точку» и получить готовую таблицу.

Рассмотрим пример формирования такой таблицы:


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

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

Решение 3: Программное управление настройкой порядка

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


Процедура УстановитьДоступностьСортировки(Список)
    Для каждого Поле Из Список.НастройкаПорядка Цикл
        // Исключаем системные поля, которые нельзя индексировать
        Если Поле.Имя <> "Ссылка" И Поле.Имя <> "Проведен" Тогда
            Поле.Доступность = Истина;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Вызов этой процедуры в ПриОткрытии формы позволит пользователю через стандартное меню «Установить отбор и сортировку» выбрать ваше новое числовое поле ПорядокСтатуса.

Решение 4: Построитель отчета на форме

Малоизвестный, но эффективный метод для ОФ — использование объекта ПостроительОтчета. Он позволяет выводить данные в табличное поле на форме, при этом предоставляя пользователю мощные механизмы отборов и сортировок, включая обращения к связанным таблицам. ПостроительОтчета генерирует запрос динамически, что позволяет ему «пробрасывать» сортировку по вложенным полям справочников. Это решение является своего рода «предком» динамических списков Управляемого приложения.

Выводы и рекомендации

Выбор метода зависит от объема данных и требований к интерфейсу:

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

← На главную