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

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

При разработке сложных обработок в среде 1С:Предприятие 8.3 программисты часто сталкиваются с задачей фильтрации данных внутри табличной части. Стандартный механизм ОтборСтрок у элементов формы имеет существенное ограничение: он поддерживает только вид сравнения Равно. Если же задача требует удаления строк по условиям "Больше", "В списке" или "Между" (особенно по номеру строки), стандартных средств становится недостаточно. В данной статье мы разберем профессиональный подход к решению этой задачи с использованием Системы компоновки данных (СКД).

Почему стандартные методы не подходят?

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

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

Шаг 1: Подготовка интерфейса и реквизитов

Для реализации универсального фильтра нам понадобится специальный реквизит формы. Рассмотрим алгоритм настройки:

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

Шаг 2: Программная генерация схемы СКД

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


// Пример формирования текста запроса для инициализации СКД
ПоляЗапроса = Новый Массив;
Для Каждого Колонка Из Объект.ТабличнаяЧасть1.Выгрузить().Колонки Цикл
    ТипКолонки = Колонка.ТипЗначения.Типы()[0];
    Если ТипКолонки = Тип("Число") Тогда
        ПоляЗапроса.Добавить("ВЫРАЗИТЬ(0 КАК ЧИСЛО(15, 2)) КАК " + Колонка.Имя);
    ИначеЕсли ТипКолонки = Тип("Строка") Тогда
        ПоляЗапроса.Добавить("ВЫРАЗИТЬ("""" КАК СТРОКА(100)) КАК " + Колонка.Имя);
    Иначе
        // Для ссылочных типов находим пустое значение через метаданные
        ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипКолонки);
        Если ОбъектМетаданных <> Неопределено Тогда
            ПоляЗапроса.Добавить("ЗНАЧЕНИЕ(" + ОбъектМетаданных.ПолноеИмя + ".ПустаяСсылка) КАК " + Колонка.Имя);
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

ТекстЗапроса = "ВЫБРАТЬ " + СтрСоединить(ПоляЗапроса, ", ");

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

Шаг 3: Выполнение фильтрации через СКД

Теперь рассмотрим основной алгоритм. Мы должны передать данные нашей табличной части в СКД как Внешний набор данных, применить пользовательские настройки и получить таблицу строк, которые подлежат удалению.

Рассмотрим процесс по шагам:

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

// Процедура удаления строк по фильтру
Процедура УдалитьСтрокиПоФильтру() Экспорт
    
    Схема = ПолучитьСхемуСКД(); // Ваша программно созданная схема
    Настройки = Компоновщик.ПолучитьНастройки();
    
    // Подготавливаем внешние данные
    ВнешниеНаборыДанных = Новый Структура;
    ВнешниеНаборыДанных.Вставить("ТаблицаДляФильтра", Объект.ТабличнаяЧасть1.Выгрузить());
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    ТаблицаРезультат = Новый ТаблицаЗначений;
    ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    // Теперь в ТаблицаРезультат только те строки, которые соответствуют фильтру
    // Выполняем удаление
    УдалитьНайденныеСтроки(ТаблицаРезультат);
    
КонецПроцедуры

Шаг 4: Эффективное удаление строк

При удалении строк важно учитывать производительность и корректность индексов. Если мы будем просто искать каждую строку методом Найти(), это может замедлить работу на больших объемах данных. Проанализируем два подхода:

Подход А: Использование массива. Мы можем собрать все строки, подлежащие удалению, в массив, а затем обойти его. Важно: для табличных частей объектов (например, в обработках или документах) лучше всего использовать метод Удалить() самой коллекции.


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

Важные нюансы и советы

Рассмотрим несколько критических моментов, которые помогут избежать ошибок:

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

Таким образом, мы разобрали, как превратить "легкую" на первый взгляд задачу в надежное и универсальное решение, достойное профессионального разработчика 1С.

← На главную