Как реализовать сортировку в таблице значений и динамическом списке в 1С

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

При разработке интерфейсов на управляемых формах в платформе «1С:Предприятие 8.3» программисты часто сталкиваются с задачей сортировки данных в табличных частях. Начинающие разработчики нередко путают поведение динамического списка и таблицы значений, выведенной на форму. В этой статье мы подробно разберем, почему в таблице значений на управляемой форме по умолчанию отсутствуют интерактивные стрелочки сортировки в шапке колонок, как решить эту задачу стандартными средствами платформы, как реализовать быструю программную сортировку на клиенте и как оптимизировать этот процесс в соответствии со стандартами разработки фирмы «1С». ---

1. Разница между динамическим списком и таблицей значений

Для начала выясним причину, почему поведение этих двух объектов при выводе на форму так сильно отличается.

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

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

---

2. Как пользователю отсортировать таблицу значений стандартными средствами

Если на форме размещена таблица, связанная с таблицей значений или табличной частью, пользователь все равно может отсортировать её без написания какого-либо программного кода. Для этого используются стандартные команды платформы:

  1. Через кнопку «Еще»: В командной панели, связанной с таблицей, всегда присутствует стандартная кнопка «Еще». При её нажатии открывается меню, в котором доступны команды сортировки по возрастанию или убыванию текущей колонки.
  2. Через контекстное меню: Если пользователь кликнет правой кнопкой мыши (ПКМ) по ячейке нужной колонки, в открывшемся контекстном меню будут доступны те же стандартные команды сортировки.

---

3. Программная сортировка таблицы значений прямо на клиенте

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

Рассмотрим подробнее объект ДанныеФормыКоллекция, который выступает типом данных для табличных частей и таблиц значений на форме. У этого объекта есть собственный метод Сортировать(), доступный непосредственно в клиентском контексте. Это позволяет выполнять сортировку мгновенно без нагрузки на сервер и без лишней сериализации данных.

Разберем по шагам, как выполнить программную сортировку на клиенте:


&НаКлиенте
Процедура СортироватьТаблицуНаКлиенте()
    
    // Сортировка по одной колонке по возрастанию
    Объект.Товары.Сортировать("Номенклатура Возр");
    
    // Пример многоуровневой сортировки (по нескольким колонкам)
    Объект.Товары.Сортировать("Склад Возр, Количество Убыв");
    
КонецПроцедуры

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

---

4. Имитация интерактивной сортировки по клику на заголовок ТЗ

Если бизнес-требования обязывают сделать так, чтобы пользователь мог сортировать таблицу значений простым кликом по заголовку колонки (как в динамическом списке), мы можем применить обходной путь. Для этого мы задействуем обработчик события таблицы Выбор или ПриАктивизацииЯчейки, либо добавим собственные кнопки в командную панель. Рассмотрим вариант с использованием события изменения активной колонки для имитации клика.

Разберем пример реализации, в котором мы будем отслеживать клик по колонке и менять направление сортировки:


&НаКлиенте
Перем ТекущееНаправлениеСортировки; // Хранит направление сортировки

&НаКлиенте
Процедура ТоварыПриАктивизацииЯчейки(Элемент)
    
    ТекущаяКолонка = Элемент.ТекущийЭлемент.Имя;
    
    // Исключаем системные колонки, которые не нужно сортировать
    Если ТекущаяКолонка = "ТоварыНомерСтроки" Тогда
        Возврат;
    КонецЕсли;
    
    // Определяем имя реквизита (убираем префикс пути к данным, если необходимо)
    ИмяПоляДляСортировки = Элемент.ТекущийЭлемент.ПутьКДанным;
    // Например, из "Объект.Товары.Номенклатура" получаем "Номенклатура"
    ЧастиПути = СтрРазделить(ИмяПоляДляСортировки, ".");
    ИмяКолонки = ЧастиПути[ЧастиПути.ВГраница()];
    
    // Меняем направление сортировки при повторном клике на ту же колонку
    Если ТекущееНаправлениеСортировки = "Возр" Тогда
        ТекущееНаправлениеСортировки = "Убыв";
    Иначе
        ТекущееНаправлениеСортировки = "Возр";
    КонецЕсли;
    
    // Выполняем сортировку коллекции на клиенте
    Объект.Товары.Сортировать(ИмяКолонки + " " + ТекущееНаправлениеСортировки);
    
КонецПроцедуры

---

5. Передача данных таблицы значений в Динамический список

Иногда разработчики пытаются пойти от обратного: вместо того чтобы настраивать ТЗ, они хотят "засунуть" её в динамический список, чтобы использовать все плюсы СКД (включая автоматические стрелочки сортировки и быстрые отборы).

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

Тем не менее, существуют правильные архитектурные способы обхода этого ограничения:

Способ А. Использование массива простых типов

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

В запросе динамического списка пишется стандартное условие отбора:


ВЫБРАТЬ
    ДокументТаблица.Ссылка,
    ДокументТаблица.Дата,
    ДокументТаблица.Номер
ИЗ
    Документ.РеализацияТоваровУслуг КАК ДокументТаблица
ГДЕ
    ДокументТаблица.Ссылка В (&МассивДокументов)

Способ Б. Временные физические таблицы базы данных

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

6. Оптимизация сортировки ТЗ по стандартам разработки 1С (Стандарт #std781)

Когда мы работаем с большими таблицами значений на стороне сервера, критически важно соблюдать требования к производительности. Стандарты разработки фирмы «1С» накладывают строгие ограничения на сортировку таблиц значений по колонкам, содержащим ссылочный тип данных (например, ссылки на справочники или документы).

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

Для правильного решения этой задачи разработчики используют два основных подхода:

Подход 1. Сортировка по вспомогательной текстовой колонке

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


// Пример запроса, подготавливающего данные для быстрой сортировки
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Товары.Ссылка КАК Номенклатура,
    |	Товары.Наименование КАК НоменклатураПредставление,
    |	Товары.Код КАК Код
    |ИЗ
    |	Справочник.Номенклатура КАК Товары";

ТаблицаДанных = Запрос.Выполнить().Выгрузить();

// Сортируем по текстовому представлению - СУБД больше не опрашивается!
ТаблицаДанных.Сортировать("НоменклатураПредставление Возр");

Подход 2. Использование объекта «СравнениеЗначений»

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


// Создаем объект сравнения значений
ОбъектСравнения = Новый СравнениеЗначений;

// Выполняем быструю и безопасную сортировку по ссылочному полю
ТаблицаДанных.Сортировать("Номенклатура", ОбъектСравнения);

---

7. Заключение

Мы подробно разобрали особенности работы механизмов сортировки в различных объектах интерфейса 1С. Подведем итог:

← На главную