Разработка интерфейсов в системе «1С:Предприятие 8» часто ставит перед программистами интересные задачи. Одна из классических ситуаций, с которой сталкиваются как начинающие, так и опытные разработчики — это создание удобного механизма фильтрации данных на управляемой форме. Вы наверняка замечали, что в типовых конфигурациях для списков документов или справочников прямо в командной панели доступны удобные кнопки вроде «Отбор по значению в текущей колонке». Однако, пытаясь перенести этот функционал в свою внешнюю обработку, вы можете обнаружить, что для вашей таблицы эти команды просто недоступны.
Выясним причину этой проблемы. Дело в том, что на платформе «1С:Предприятие 8» стандартные команды поиска и отбора «из коробки» жестко привязаны к определенным типам данных. Они автоматически генерируются для динамических списков (ДинамическийСписок) и табличных частей объектов (ТабличнаяЧасть). Если же вы вывели на форму реквизит с типом ТаблицаЗначений (который на клиенте позиционируется как ДанныеФормыКоллекция), платформа лишает нас этой стандартной магии командной панели.
В этой статье мы подробно разберем, как обойти это ограничение, и рассмотрим несколько эффективных способов реализации отборов для таблицы значений на управляемой форме.
Проанализируем ситуацию и разберем по шагам доступные варианты решения.
Посмотрим на пример, предложенный в обсуждении на форуме. Это самый простой способ, который не требует написания сложного программного кода для фильтрации, так как задействует стандартные механизмы платформы.
Если мы разрабатываем внешнюю обработку, мы можем создать внутри самого объекта обработки табличную часть. Назовем её, например, ОтображаемыеДанные. Структура колонок этой табличной части должна полностью совпадать с теми данными, которые мы планировали выводить в таблицу значений.
Разберем по шагам схему работы этого метода:
Для переноса данных мы используем стандартные и очень быстрые методы платформы Загрузить() и Выгрузить(). Рассмотрим пример кода, который выполняет эту операцию на сервере:
// Пример заполнения табличной части обработки из таблицы значений
&НаСервере
Процедура ЗаполнитьДанныеНаСервере(ТаблицаИсточник)
// Очищаем табличную часть и загружаем в нее данные из ТЗ
Объект.ОтображаемыеДанные.Загрузить(ТаблицаИсточник);
КонецПроцедуры
Если пользователь в процессе работы редактирует данные в табличной части на форме, и нам необходимо получить их обратно в виде чистой таблицы значений для дальнейшей обработки (например, для проведения документов или выгрузки в файл), мы выполняем обратную операцию:
// Получение таблицы значений из табличной части для последующей обработки
&НаСервере
Функция ПолучитьТаблицуИзТабличнойЧасти()
Возврат Объект.ОтображаемыеДанные.Выгрузить();
КонецФункции
Преимущества метода: Минимум кода, полноценная поддержка стандартных платформенных отборов и поиска, работающих без дополнительных усилий со стороны программиста.
Что делать, если нам категорически нельзя или не хочется создавать дублирующие табличные части в объекте, и мы обязаны работать непосредственно с реквизитом формы типа ТаблицаЗначений? В этом случае мы можем реализовать функционал отбора программно.
Для таблиц на управляемой форме у элемента управления существует замечательное свойство ОтборСтрок. Оно позволяет мгновенно отфильтровать строки таблицы прямо на клиенте без обращений к серверу. Данное свойство принимает значение типа ФиксированнаяСтруктура, где ключом выступает имя колонки, а значением — то, по чему мы хотим отфильтровать таблицу.
Рассмотрим, как создать свою кнопку отбора по текущему значению:
УстановитьОтборПоТекущемуЗначению.Проанализируем программный код реализации этой процедуры:
&НаКлиенте
Процедура УстановитьОтборПоТекущемуЗначению(Команда)
// Получаем строку, на которой в данный момент стоит курсор
ТекущиеДанные = Элементы.ТаблицаДанныхФормы.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
ПоказатьПредупреждение(, "Не выбрана строка для установки отбора!");
Возврат;
КонецЕсли;
// Определяем текущий элемент (колонку), на которой сфокусирован пользователь
ТекущийЭлемент = Элементы.ТаблицаДанныхФормы.ТекущийЭлемент;
ПутьКДанным = ТекущийЭлемент.ПутьКДанным;
// Поскольку ПутьКДанным возвращает строку вида "ИмяТаблицы.ИмяКолонки",
// нам нужно вычленить только имя самой колонки
ПозицияТочки = Найти(ПутьКДанным, ".");
Если ПозицияТочки > 0 Тогда
ИмяКолонки = Сред(ПутьКДанным, ПозицияТочки + 1);
Иначе
ИмяКолонки = ПутьКДанным;
КонецЕсли;
// Получаем значение ячейки в текущей строке и текущей колонке
ЗначениеОтбора = ТекущиеДанные[ИмяКолонки];
// Создаем структуру отбора и применяем её к свойству ОтборСтрок
СтруктураОтбора = Новый ФиксированнаяСтруктура(ИмяКолонки, ЗначениеОтбора);
Элементы.ТаблицаДанныхФормы.ОтборСтрок = СтруктураОтбора;
КонецПроцедуры
Для того чтобы пользователь мог легко вернуть таблицу к исходному состоянию, обязательно нужно предоставить ему возможность сбросить установленные фильтры. Для этого создаем команду СброситьВсеОтборы и пишем простой код:
&НаКлиенте
Процедура СброситьВсеОтборы(Команда)
// Сброс отбора происходит путем присвоения свойству значения Неопределено
Элементы.ТаблицаДанныхФормы.ОтборСтрок = Неопределено;
КонецПроцедуры
Важная особенность работы «ОтборСтрок»: Этот метод работает исключительно быстро, так как фильтрация происходит в памяти клиентского приложения. Для числовых, ссылочных типов и булевых значений сравнение идет по точному соответствию («Равно»). Если вы накладываете отбор на текстовую колонку, платформа выполняет поиск по вхождению подстроки («Содержит»).
Иногда лучшим решением является обучение пользователей стандартному поведению системы. Мало кто знает, но платформа «1С:Предприятие 8» предоставляет встроенный функционал поиска для любых отображаемых таблиц на форме, включая обычные Таблицы Значений.
Пользователю достаточно выделить нужную ячейку в таблице значений и нажать комбинацию клавиш Alt + F. Платформа самостоятельно откроет окно поиска с уже подставленным значением текущей колонки. После нажатия кнопки «Найти» таблица будет мгновенно отфильтрована.
Сброс такого поиска осуществляется стандартным сочетанием клавиш Ctrl + Q или нажатием на кнопку сброса на стандартной панели. Этот метод абсолютно бесплатный с точки зрения разработки, так как не требует написания ни единой строчки кода.
Если вам требуется сложная логика фильтрации (например, скрывать определенные строки на основе сложных комплексных условий, которые нельзя описать простой структурой) или если вы хотите физически управлять составом данных на форме, можно реализовать фильтрацию на стороне сервера.
Для этого на управляемой форме создаются два реквизита:
ИсходнаяТаблицаДанных (тип ТаблицаЗначений, не выводится на форму и служит эталонным хранилищем всех строк).ОтображаемаяТаблицаДанных (тип ТаблицаЗначений, выводится на форму пользователю).При изменении параметров отборов на клиенте мы вызываем серверный метод, который выбирает нужные строки из исходной таблицы и копирует их в отображаемую:
&НаСервере
Процедура ПрименитьСерверныйФильтр(ЗначениеФильтра)
// Получаем таблицы из реквизитов формы
ТЗ_Источник = РеквизитФормыВЗначение("ИсходнаяТаблицаДанных", Тип("ТаблицаЗначений"));
// Выполняем поиск строк по условию
СтруктураПоиска = Новый Структура("Статус", ЗначениеФильтра);
НайденныеСтроки = ТЗ_Источник.НайтиСтроки(СтруктураПоиска);
// Очищаем отображаемую на форме таблицу
ОтображаемаяТаблицаДанных.Очистить();
// Заполняем её найденными строками
Для Каждого СтрокаТЗ Из НайденныеСтроки Цикл
ЗаполнитьЗначенияСвойств(ОтобраемаяТаблицаДанных.Добавить(), СтрокаТЗ);
КонецЦикла;
КонецПроцедуры
Этот метод дает полный контроль над данными, однако требует серверных вызовов, что может сказаться на производительности при работе под высокой нагрузкой или на медленных каналах связи.
Мы подробно разобрали, почему не работают стандартные кнопки командной панели для реквизитов типа ТаблицаЗначений, и изучили четыре различных подхода для решения этой задачи. Выбор конкретного метода зависит от архитектуры вашей обработки:
ОтборСтрок на клиенте.