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

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

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

Анализ проблемы: почему стандартный перебор не подходит

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

Основное решение: Использование Построителя отчета

Наиболее универсальным и корректным способом решения данной задачи в обычных формах является использование объекта ПостроительОтчета. Этот объект обладает уникальной способностью анализировать настройки элементов управления и применять их к источнику данных.

Рассмотрим по шагам, как это реализовать:

  1. Создание объекта построителя: Нам понадобится новый экземпляр ПостроительОтчета.
  2. Инициализация источника данных: Мы используем специальный объект ОписаниеИсточникаДанных.
  3. Передача элемента формы: Важнейший нюанс заключается в том, что в качестве источника нужно передавать не саму таблицу с данными, а именно элемент управления (Табличное Поле). Это позволяет построителю "увидеть" текущие настройки отбора.

Посмотрим на пример программного кода, который решает эту задачу:


// Предположим, имя элемента Табличного поля на форме - "ТЗДанные"
// Создаем новый построитель отчета
Построитель = Новый ПостроительОтчета;

// Важно: передаем именно элемент формы (ТабличноеПоле)
// Это позволит построителю автоматически подхватить установленный пользователем отбор
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ЭлементыФормы.ТЗДанные);

// Выполняем построение
Построитель.Выполнить();

// Получаем результат в виде выборки или таблицы значений
Результат = Построитель.Результат; // Это объект РезультатЗапроса
Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл
    // Здесь выполняем необходимые действия с отфильтрованной строкой
    Сообщить("Обработка строки: " + Выборка.Наименование);
КонецЦикла;

Разбор нюансов работы с ОписаниемИсточникаДанных

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

Важный момент: если вы столкнулись с ошибкой "Несоответствие типов" при инициализации источника, убедитесь, что вы передаете именно объект элемента управления. В коде это выглядит как ЭлементыФормы.ИмяВашегоПоля.

Альтернативный метод: Использование функции НайтиСтроки()

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

Если пользователь в интерфейсе установил отбор:

...то метод НайтиСтроки() использовать не получится, так как структуру для таких условий создать невозможно. Однако, если вы точно знаете, что отбор всегда будет простым (например, только по конкретному складу или организации), вы можете программно прочитать ЭлементыФормы.ИмяТП.Отбор, сформировать структуру и передать её в НайтиСтроки().

Ручная синхронизация отборов

В некоторых сложных случаях может потребоваться ручной перенос условий. Каждый элемент в коллекции Отбор табличного поля является объектом ЭлементОтбора. Рассмотрим пример того, как можно проанализировать эти условия:


Для Каждого Элемент Из ЭлементыФормы.ТЗДанные.Отбор Цикл
    Если Элемент.Использование Тогда
        ИмяПоля = Элемент.ПутьКДанным;
        ВидСравнения = Элемент.ВидСравнения;
        Значение = Элемент.Значение;
        
        // Здесь можно реализовать собственную логику фильтрации
        // или динамически собрать текст запроса
    КонецЕсли;
КонецЦикла;

Этот путь значительно более трудоемкий, так как вам придется самостоятельно обрабатывать все виды сравнения (ВСписке, Между, Содержит и т.д.). Поэтому использование ПостроителяОтчета остается приоритетным вариантом.

Особенности для динамических списков

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

Рассмотрим пример получения итогов по отфильтрованным строкам:


Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ЭлементыФормы.СписокДокументов);
Построитель.Выполнить();

// Выгружаем результат в таблицу для быстрого подсчета итогов
ТаблицаРезультат = Построитель.Результат.Выгрузить();
ИтоговаяСумма = ТаблицаРезультат.Итог("СуммаДокумента");
Сообщить("Сумма видимых документов: " + ИтоговаяСумма);

Заключение

Мы рассмотрели основной механизм работы с видимыми строками в обычных формах 1С. Подведем итог: использование ПостроителяОтчета с передачей ЭлементаФормы в качестве источника — это наиболее надежный и эффективный метод. Он позволяет избежать написания сложного кода по разбору коллекций отбора и корректно обрабатывает любые условия сравнения, установленные пользователем в интерфейсе.

← На главную