Когда мы работаем с управляемыми формами в 1С 8.3, часто возникает потребность в интерактивной сортировке данных. Классический пример — желание отсортировать колонки элемента ТаблицаЗначений так же, как это происходит в стандартных списках справочников или документов, то есть по простому клику на заголовок колонки. Однако, для элемента ТаблицаЗначений на управляемых формах стандартного события, которое срабатывало бы при нажатии на заголовок колонки и автоматически выполняло сортировку, к сожалению, не предусмотрено. Это означает, что "из коробки" такой функциональности нет. Тем не менее, существуют обходные пути и дополнительные подходы, которые позволяют реализовать подобную функциональность, имитируя желаемое поведение. Давайте рассмотрим, как мы можем подойти к решению этой задачи.
Прежде всего, важно понять, что элемент ТаблицаЗначений (ТЗ) на управляемой форме в 1С 8.3 представляет собой клиентский объект, который работает с данными, уже загруженными в оперативную память. В отличие от ДинамическогоСписка, который напрямую взаимодействует с базой данных и умеет формировать запросы с условиями сортировки (ORDER BY) на стороне сервера, ТЗ является более "простым" хранилищем. Поэтому система не предоставляет встроенного механизма для обработки кликов по заголовкам ТЗ с целью автоматической сортировки.
При нажатии на заголовок колонки ТаблицыЗначений никакое стандартное событие не вызывается, которое позволило бы нам программно перехватить действие пользователя и выполнить сортировку. Это является ключевым моментом, отличающим ТЗ от динамических списков, где такая функциональность реализована по умолчанию.
Если данные для вашей таблицы берутся непосредственно из базы данных (например, из справочника, документа, регистра или произвольного запроса к данным ИБ) и не требуют интенсивного интерактивного изменения на клиенте, наиболее "правильным", поддерживаемым и простым в реализации способом будет использование элемента ДинамическийСписок вместо ТаблицыЗначений. Рассмотрим подробнее преимущества этого подхода.
Автоматическая сортировка по клику: ДинамическийСписок по умолчанию поддерживает сортировку по клику на заголовок колонки. Пользователю достаточно нажать на нужный заголовок, и список автоматически отсортируется по этой колонке, при повторном клике изменится направление сортировки (по возрастанию/убыванию). Эта функциональность уже встроена в платформу и не требует написания дополнительного кода.
Эффективная работа с большими объемами данных: Поскольку ДинамическийСписок работает на стороне сервера, он загружает данные порциями по мере необходимости. Это значительно повышает производительность при работе с большими объемами данных по сравнению с ТаблицейЗначений, которая загружает все данные целиком на клиент.
Дополнительные возможности: Помимо сортировки, ДинамическийСписок также предоставляет удобные функции, такие как поиск, отбор, группировка, иерархический просмотр, а также флажки в динамическом списке, которые также работают "из коробки" и значительно улучшают пользовательский опыт.
Простота настройки: Для использования ДинамическогоСписка вам потребуется создать новый реквизит формы с типом ДинамическийСписок, указать для него основной запрос к данным (например, Справочник.Товары или более сложный запрос, подготовленный в консоли (удобно через инструментарий разработчика с консолью запросов и СКД)) и перетащить нужные поля на форму. Платформа сама позаботится об остальном.
Когда использовать ДинамическийСписок:
Если по какой-либо причине использование ДинамическогоСписка невозможно (например, данные формируются полностью программно на клиенте, являются результатом сложной обработки, или требуется высокая скорость внесения изменений, не привязанных к объектам базы данных), то сортировку ТаблицыЗначений придется реализовывать программно. Для имитации поведения "по нажатию на заголовок" нам придется использовать обходные пути.
ТЗ.Сортировать()Это основной метод для программной сортировки ТаблицыЗначений. Его синтаксис довольно прост и интуитивно понятен. Мы можем указать имя колонки и направление сортировки.
Синтаксис метода:
ТЗ.Сортировать("ИмяКолонки [Возр|Убыв][, ИмяКолонки2 [Возр|Убыв]]");
Где:
ИмяКолонки — строка с именем колонки, по которой нужно выполнить сортировку.Возр — сортировка по возрастанию (по умолчанию).Убыв — сортировка по убыванию.Примеры использования:
// Сортировка по колонке "Остаток" по убыванию
МояТаблицаЗначений.Сортировать("Остаток Убыв");
// Сортировка по колонке "Наименование" по возрастанию
МояТаблицаЗначений.Сортировать("Наименование Возр");
// Сортировка по нескольким колонкам: сначала по "Группа" по возрастанию, затем по "Цена" по убыванию
МояТаблицаЗначений.Сортировать("Группа Возр, Цена Убыв");
Мы видим, что сам метод сортировки достаточно мощный. Основная задача в данном сценарии — это как вызвать этот метод при действиях пользователя, имитирующих клик по заголовку.
Чтобы предоставить пользователю возможность сортировки по клику, можно разместить над колонками ТаблицыЗначений другие элементы формы (в этом поможет инструментарий для программного изменения форм), которые будут обрабатывать событие нажатия. Чаще всего для этой цели используют Кнопки или Декорации с типом "Поле надписи".
Размещение элементов: Разместите элемент Кнопка или Декорация над каждой колонкой ТаблицыЗначений, которую вы хотите сделать сортируемой. Придайте им вид заголовка колонки, например, установив соответствующий текст (название колонки) и настроив стиль.
Обработка события нажатия: Для каждой такой кнопки или декорации создайте обработчик события Нажатие. В этом обработчике мы будем вызывать метод ТЗ.Сортировать().
Определение порядка сортировки (Возр/Убыв): Чтобы при повторном клике по тому же "заголовку" менялось направление сортировки, нам потребуется хранить информацию о текущем порядке сортировки для каждой колонки. Мы можем использовать для этого реквизит формы типа Структура или Соответствие, где ключом будет имя колонки, а значением — текущее направление сортировки (например, "Возр" или "Убыв").
Пример алгоритма:
Пример кода для обработчика нажатия кнопки/декорации:
Допустим, у нас есть реквизит формы СостояниеСортировкиКолонок типа Соответствие и процедура СортироватьТаблицу.
// В модуле формы
// Реквизит формы: СостояниеСортировкиКолонок (Тип: Соответствие)
&НаКлиенте
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Инициализируем соответствие для хранения состояний сортировки
СостояниеСортировкиКолонок = Новый Соответствие;
КонецПроцедуры
&НаКлиенте
Процедура ОбработкаНажатияЗаголовкаКолонки(Элемент)
// Получаем имя колонки из имени элемента формы, например, "ЗаголовокКолонкиОстаток" -> "Остаток"
ИмяКолонки = СтрЗаменить(Элемент.Имя, "ЗаголовокКолонки", "");
ТекущееНаправление = СостояниеСортировкиКолонок.Получить(ИмяКолонки);
Если ТекущееНаправление = Неопределено Или ТекущееНаправление = "Убыв" Тогда
НаправлениеСортировки = "Возр";
Иначе
НаправлениеСортировки = "Убыв";
КонецЕсли;
// Очищаем предыдущие состояния сортировки, если хотим сортировать только по одной колонке
// Если нужна многоуровневая, этот шаг пропускаем или модифицируем
СостояниеСортировкиКолонок.Очистить();
СостояниеСортировкиКолонок.Вставить(ИмяКолонки, НаправлениеСортировки);
СортироватьТаблицу(ИмяКолонки, НаправлениеСортировки);
КонецПроцедуры
&НаКлиенте
Процедура СортироватьТаблицу(ИмяКолонки, НаправлениеСортировки)
// Доступ к ТаблицеЗначений, например, "МоиДанные" - реквизит формы
МоиДанные.Сортировать(ИмяКолонки + " " + НаправлениеСортировки);
КонецПроцедуры
Вызовы и настройки: На каждой кнопке/декорации, например, с именем "ЗаголовокКолонкиОстаток", нужно будет указать вызов процедуры ОбработкаНажатияЗаголовкаКолонки в событии Нажатие.
Вызовы:
// Для кнопки/декорации с именем "ЗаголовокКолонкиОстаток"
// Обработчик события "Нажатие"
&НаКлиенте
Процедура ЗаголовокКолонкиОстатокНажатие(Элемент)
ОбработкаНажатияЗаголовкаКолонки(Элемент);
КонецПроцедуры
Сложности при использовании кнопок/декораций:
ТаблицыЗначений. Если пользователь изменяет ширину колонок ТЗ, кнопки/декорации не будут автоматически подстраиваться. Вам придется программно отслеживать изменение ширины колонок (например, через событие ПриИзмененииШириныКолонки для элемента таблицы, если оно есть, или через другие обходные пути) и вручную корректировать размеры и позиции этих "заголовков". Это может быть достаточно трудоемко.
Более стандартный и менее трудоемкий в реализации подход, чем создание отдельных кнопок, — это добавление команд сортировки в контекстное меню для колонок ТаблицыЗначений.
Создание команд: В командной панели формы (или непосредственно в командной панели элемента ТаблицаЗначений) создайте две новые команды: "Сортировать по возрастанию" и "Сортировать по убыванию".
Обработчики команд: Для каждой команды создайте соответствующий обработчик. В этих обработчиках мы будем вызывать метод ТЗ.Сортировать(), но нам нужно знать, по какой колонке была нажата команда.
Пример: Определить текущую колонку можно через свойство ЭлементыФормы.МояТаблица.ТекущаяКолонка (для управляемой формы это будет ЭлементУправления.ТекущаяКолонка).
// В модуле формы
&НаКлиенте
Процедура СортироватьПоВозрастанию(Команда)
// Получаем текущую колонку, если пользователь вызвал команду из контекстного меню
// или выделил колонку
Если Элементы.МояТаблица.ТекущаяКолонка <> Неопределено Тогда
ИмяКолонки = Элементы.МояТаблица.ТекущаяКолонка.Имя;
// Имя колонки элемента формы может отличаться от имени колонки в ТаблицеЗначений
// Необходимо сопоставить. Например, если колонка в ТЗ называется "Остаток",
// а на форме это колонка "МояТаблицаОстаток", то нужно извлечь "Остаток".
// Или просто убедиться, что имена совпадают.
ИмяКолонкиТЗ = СтрЗаменить(ИмяКолонки, "МояТаблица", "");
СортироватьТаблицу(ИмяКолонкиТЗ, "Возр");
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура СортироватьПоУбыванию(Команда)
Если Элементы.МояТаблица.ТекущаяКолонка <> Неопределено Тогда
ИмяКолонки = Элементы.МояТаблица.ТекущаяКолонка.Имя;
ИмяКолонкиТЗ = СтрЗаменить(ИмяКолонки, "МояТаблица", "");
СортироватьТаблицу(ИмяКолонкиТЗ, "Убыв");
КонецЕсли;
КонецПроцедуры
Размещение в контекстном меню: Перетащите созданные команды в группу "Контекстное меню" для элемента ТаблицаЗначений в дизайнере формы. Теперь пользователь сможет нажать правой кнопкой мыши на любую колонку, и в контекстном меню появятся ваши команды сортировки.
Этот подход требует двух кликов (правой кнопкой мыши и выбор пункта меню), что не совсем то же самое, что "клик по заголовку", но является стандартным, легко реализуемым и понятным для пользователя механизмом.
Отображение текущего порядка сортировки: При программной сортировке полезно визуально отображать пользователю, по какой колонке и в каком направлении сейчас отсортированы данные. Для этого можно изменять текст заголовка "кнопок" (добавляя стрелочки вверх/вниз) или использовать условное форматирование.
Производительность: Метод ТЗ.Сортировать() работает на клиенте и может быть медленным для очень больших ТаблицЗначений (тысячи и десятки тысяч строк), так как все данные должны быть загружены в память и обработаны. В таких случаях ДинамическийСписок остается предпочтительным решением.
Сохранение состояния: Если пользователь часто работает с этой формой, возможно, стоит сохранять последний порядок сортировки (например, в пользовательских настройках) и применять его при открытии формы.
Мы рассмотрели различные подходы к решению задачи интерактивной сортировки ТаблицыЗначений на управляемых формах 1С 8.3. Хотя прямого аналога сортировки динамических списков для ТЗ не существует, с помощью программных методов и некоторой дополнительной работы можно добиться желаемого результата. Всегда старайтесь использовать ДинамическийСписок, если это возможно по условиям вашей задачи, так как это наиболее эффективное и поддерживаемое платформой решение.