Как программно получить данные ручного отбора в таблице значений на управляемой форме

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

В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда на управляемой форме используется реквизит типа ТаблицаЗначений. Платформа предоставляет пользователю мощный стандартный функционал: возможность устанавливать произвольные отборы и осуществлять поиск (через Ctrl+F или строку поиска). Однако, когда возникает задача программно обработать только те строки, которые пользователь отобрал вручную, выясняется, что прямого доступа к коллекции установленных фильтров у объекта ТаблицаФормы нет. В этой статье мы подробно разберем, как обойти это ограничение, проанализируем доступные методы и выясним, почему платформа ведет себя именно так.

Анализ проблемы: почему нельзя просто прочитать отбор?

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

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

Решение 1: Использование метода ПроверитьСтроку

Это самый популярный и действенный способ, если нам нужно понять, какие строки остались в таблице после того, как пользователь применил фильтры. Метод ПроверитьСтроку() принадлежит элементу формы (таблице) и возвращает булево значение: Истина, если строка отображается, и Ложь, если она скрыта отбором или поиском.

Важное условие: данный метод работает исключительно на клиенте, так как именно клиентское приложение «знает», что видит пользователь.

Рассмотрим пошагово реализацию этого алгоритма:

  1. Организуем цикл по всем строкам исходной таблицы значений.
  2. Для каждой строки получаем ее уникальный идентификатор.
  3. Передаем этот идентификатор в метод ПроверитьСтроку() элемента формы.
  4. Если метод вернул Истина, выполняем необходимую логику обработки.

Пример кода для реализации этой логики:


&НаКлиенте
Процедура ОбработатьОтфильтрованныеСтроки(Команда)
    
    // Получаем элемент формы, связанный с нашей таблицей
    ТаблицаЭлемент = Элементы.ТЧДанные;
    
    // Перебираем данные из реквизита формы (Таблицы Значений)
    Для Каждого СтрокаДанных Из Объект.ТЧДанные Цикл
        
        // Получаем внутренний идентификатор строки
        Идентификатор = СтрокаДанных.ПолучитьИдентификатор();
        
        // Проверяем, видна ли эта строка пользователю прямо сейчас
        Если ТаблицаЭлемент.ПроверитьСтроку(Идентификатор) Тогда
            // Строка прошла фильтр и поиск
            Сообщить("Строка с индексом " + Объект.ТЧДанные.Индекс(СтрокаДанных) + " видима.");
            // Здесь можно добавить строку в массив для передачи на сервер
        Иначе
            // Строка скрыта ручным отбором
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Нюанс производительности: стоит учитывать, что при наличии в таблице десятков тысяч строк, такой перебор на клиенте может привести к кратковременному зависанию интерфейса. Это связано с тем, что каждое обращение к методу ПроверитьСтроку() заставляет клиентское приложение обращаться к визуальному представлению элемента.

Решение 2: Переход на Динамический Список

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

Даже если ваши данные не хранятся в базе данных, а вычисляются программно, вы можете:

В ДинамическомСписке доступ к отборам прозрачен:


// Пример доступа к настройкам в Динамическом Списке
Настройки = Список.КомпоновщикНастроек.Настройки;
Для Каждого ЭлементОтбора Из Настройки.Отбор.Элементы Цикл
    Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
        // Здесь мы видим ЛевоеЗначение, ВидСравнения и ПравоеЗначение
    КонецЕсли;
КонецЦикла;

Решение 3: Использование СКД для вывода Таблицы Значений

Существует продвинутый способ сохранить гибкость ТаблицыЗначений, но получить мощь КомпоновщикаНастроек. Мы можем использовать Систему Компоновки Данных (СКД) программно:

  1. Создаем внешнюю схему компоновки, где источником данных является объект (наша ТЗ).
  2. Размещаем на форме КомпоновщикНастроек.
  3. Выводим настройки отбора этого компоновщика на форму.
  4. Программно применяем эти настройки к нашей таблице или используем их для фильтрации при обработке.

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

Решение 4: Реализация собственного механизма фильтрации

Если «магия» 1С с методом ПроверитьСтроку по каким-то причинам не подходит, мы можем полностью взять управление на себя. Проанализируем, как это сделать:

  1. Создаем на форме группу реквизитов для фильтрации (например, поле ввода «Контрагент», дата «С» и «По»).
  2. В обработчике события ПриИзменении этих реквизитов вызываем процедуру фильтрации.
  3. Внутри процедуры используем метод таблицы значений НайтиСтроки() или Скопировать() с параметром СтруктураОтбора.
  4. Результат фильтрации загружаем в реквизит формы, связанный с визуальной таблицей.

Этот метод гарантирует, что мы всегда знаем точные параметры фильтра, так как сами их храним в реквизитах формы.

Резюме и рекомендации

Подведем итог нашему анализу:

1. Если нужно быстро узнать, какие строки видны — используем ПроверитьСтроку() в цикле на клиенте. Это простое решение, не требующее переделки структуры формы.

2. Метод ПроверитьСтроку() учитывает не только «Отбор», но и «Поиск» (то, что введено в поле поиска), что делает его очень мощным инструментом для определения финального набора данных на экране.

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

4. Для очень больших таблиц (100 000+ строк) старайтесь избегать циклов на клиенте. В таких случаях лучше реализовать серверную фильтрацию через передачу параметров отбора в запрос.

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

← На главную