Как получить строки табличного поля с учетом пользовательского отбора в обычных формах 1С?

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

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

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

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

Разберем два эффективных и быстрых способа решения этой задачи.

Способ 1. Использование метода ПроверитьСтроку() элемента управления

Наиболее лаконичный и быстрый способ обработки строк непосредственно в исходной таблице — встроенный метод ПроверитьСтроку() объекта ТабличноеПоле. В обычном приложении этот метод принимает в качестве параметра саму строку источника данных (объект СтрокаТаблицыЗначений или СтрокаТабличнойЧасти), а не числовой идентификатор, как на управляемых формах.

Метод выполняет мгновенную проверку строки на соответствие текущим условиям отбора и поиска в оперативной памяти без смены фокуса и без перерисовки интерфейса.

Разберем по шагам алгоритм применения этого метода:

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

Посмотрим на пример программного кода:


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

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

Способ 2. Выгрузка отобранных строк через ПостроительЗапроса

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

Выясним причину частой ошибки при реализации этого способа: коллекция ОтборСтрок содержит сложные фильтры (не только «Равно», но и «В интервале», «Не равно», «В списке»). Чтобы не писать громоздкие ветвления условий для каждого вида сравнения, воспользуемся тем, что имена ключевых свойств у элементов отбора формы и объекта ПостроительЗапроса.Отбор полностью совпадают.

Проанализируем программную реализацию переноса фильтров:


Построитель = Новый ПостроительЗапроса;

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

// Получаем коллекцию отборов, установленных пользователем в табличном поле
ОтборФормы = ЭлементыФормы.ТабличноеПоле1.ОтборСтрок;

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

// Выполняем фильтрацию таблицы в памяти
Построитель.Выполнить();

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

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

Сравнение подходов

Рассмотрим, в каких случаях следует выбирать каждый из методов:

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