Как реализовать сортировку по добавленной вручную колонке табличной части в обычных формах?

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

При разработке на обычных формах 1С 8.x программисты часто сталкиваются с ситуацией, когда стандартного набора реквизитов табличной части (ТЧ) недостаточно для отображения всей необходимой информации. Мы добавляем "виртуальные" колонки программно или через редактор формы, заполняем их в событиях ПриВыводеСтроки или ПриПолученииДанных, но обнаруживаем неприятную особенность: стандартная сортировка по таким колонкам не работает. Платформа просто не "видит" данных для упорядочивания, так как их нет в физической структуре таблицы в базе данных.

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

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

Разберем ситуацию: когда мы используем метод ОформлениеСтроки.Ячейки.ИмяКолонки.Значение = ..., мы лишь отрисовываем текст в интерфейсе. Сама коллекция ТабличнаяЧасть документа об этих данных ничего не знает. Стандартные кнопки командной панели при нажатии обращаются к источнику данных (самой ТЧ), пытаются найти там соответствующее поле и, не находя его, ничего не делают. Проанализируем основные пути решения этой задачи.

Решение 1: Метод «Скрытого реквизита» (самый надежный)

Самый простой и производительный способ — сделать колонку "реальной". Рассмотрим пошагово:

  1. Добавим реквизит в табличную часть документа в дереве метаданных (конфигураторе). Например, Маркировка.
  2. Если мы не хотим, чтобы пользователь мог редактировать это поле вручную, мы можем оставить его на форме, но установить свойство ТолькоПросмотр.
  3. Заполним этот реквизит программно в момент выбора основного объекта. Рассмотрим пример кода для события ГрузыГрузПриИзменении:

Процедура ГрузыГрузПриИзменении(Элемент)
    СтрокаТЧ = ЭлементыФормы.Грузы.ТекущиеДанные;
    Если ЗначениеЗаполнено(СтрокаТЧ.Груз) Тогда
        // Предположим, Маркировка — это реквизит справочника Грузы
        СтрокаТЧ.Маркировка = СтрокаТЧ.Груз.Маркировка;
    КонецЕсли;
КонецПроцедуры

Преимущество: Сортировка будет работать автоматически силами платформы, так как данные теперь физически присутствуют в табличной части.

Решение 2: Сортировка через выгрузку в Таблицу Значений (ТЗ)

Если изменять структуру метаданных нельзя, мы можем реализовать ручную сортировку. Суть метода заключается в том, чтобы выгрузить данные из ТЧ в промежуточную таблицу, добавить туда колонку для сортировки, упорядочить и загрузить обратно.

Рассмотрим алгоритм действий:

  1. Перехватим нажатие на заголовок колонки.
  2. Выгрузим ТЧ в объект ТаблицаЗначений.
  3. Добавим в ТЗ колонку с нужным типом данных.
  4. Заполним её значениями (например, через запрос или циклом).
  5. Отсортируем ТЗ.
  6. Загрузим данные обратно в ТЧ.

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


// Пример сортировки через временную таблицу
ТЗИсточник = Грузы.Выгрузить();
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("ТЗИсточник", ТЗИсточник);

Запрос.Текст = 
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТПриемник ИЗ &ТЗИсточник КАК ТЗИсточник;
|ВЫБРАТЬ * ИЗ ВТПриемник КАК ВТПриемник 
|УПОРЯДОЧИТЬ ПО ВТПриемник.Груз.Маркировка";

Результат = Запрос.Выполнить().Выгрузить();
Грузы.Загрузить(Результат);

Решение 3: Перехват события «ПриНажатииНаЗаголовок»

Чтобы пользователь мог инициировать сортировку привычным кликом по шапке таблицы, нам нужно обработать событие ПриНажатииНаЗаголовок у элемента управления ТабличноеПоле. Выясним, как это сделать правильно:


Процедура ГрузыПриНажатииНаЗаголовок(Элемент, Колонка)
    Если Колонка.Имя = "Маркировка" Тогда
        // Вызываем нашу процедуру сортировки
        ВыполнитьРучнуюСортировку("Груз.Маркировка");
        
        // Визуально помечаем направление сортировки (стрелочка)
        Если Колонка.СостояниеСортировки = НаправлениеСортировки.Возр Тогда
            Колонка.СостояниеСортировки = НаправлениеСортировки.Убыв;
            Грузы.Сортировать("Маркировка Убыв"); // Если добавили реквизит
        Иначе
            Колонка.СостояниеСортировки = НаправлениеСортировки.Возр;
            Грузы.Сортировать("Маркировка Возр");
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Важные нюансы и подводные камни

Проанализируем несколько критических моментов, о которых часто забывают при реализации ручной сортировки:

1. Потеря фокуса (текущей строки). Когда мы выполняем метод Загрузить(), объект ТЧ полностью обновляется, и курсор пользователя прыгает на первую строку. Чтобы этого избежать, перед сортировкой нужно запомнить текущую строку:


// Запоминаем текущие данные
ТекущийГруз = ЭлементыФормы.Грузы.ТекущиеДанные.Груз; 

// ... выполняем выгрузку, сортировку и загрузку ...

// Пытаемся найти строку обратно
ПараметрыОтбора = Новый Структура("Груз", ТекущийГруз);
НайденныеСтроки = Грузы.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
    ЭлементыФормы.Грузы.ТекущаяСтрока = НайденныеСтроки[0];
КонецЕсли;

2. Проблема производительности. Если вы используете ПриВыводеСтроки для получения маркировки через точку (ОформлениеСтроки.ДанныеСтроки.Груз.Маркировка), помните, что это порождает отдельный запрос к базе данных для каждой видимой строки. При сортировке больших таблиц (сотни строк) это может привести к заметным "тормозам". Лучше использовать кэширование данных в Соответствие при открытии формы или при первом обращении.

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

Заключение

Мы рассмотрели несколько подходов к решению задачи. Если есть возможность изменять метаданные — добавление реального реквизита в ТЧ является "золотым стандартом", так как это избавляет от написания лишнего кода и гарантирует стабильную работу стандартных механизмов 1С. Если же метаданные менять нельзя, используйте выгрузку в ТЗ с программной обработкой события нажатия на заголовок, не забывая при этом восстанавливать положение курсора для удобства пользователя.

← На главную