Как выполнить фильтрацию Таблицы Значений в 1С и получить результат в виде новой таблицы?

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

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

Метод 1: Использование встроенного метода Скопировать()

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

Рассмотрим пример кода, в котором мы сначала получаем уникальный список помещений, а затем в цикле создаем отфильтрованные таблицы:


// 1. Получаем исходную таблицу с данными
ТЗ_ВсеТовары = ПолучитьТоварыДляЗаказа();

// 2. Определяем список уникальных комбинаций помещений (этаж и линия)
ПараметрыСклада = ТЗ_ВсеТовары.Скопировать();
ПараметрыСклада.Свернуть("Этаж, Линия");

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

Важно помнить, что метод Скопировать() принимает два необязательных параметра: ПараметрыОтбора (структура) и Колонки (строка со списком колонок). Если не указать колонки, система скопирует все существующие поля.

Метод 2: Использование НайтиСтроки() и преобразование массива в ТЗ

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

Проанализируем ситуацию, как превратить массив строк обратно в таблицу с той же структурой:


// Создаем пустую таблицу с аналогичной структурой колонок
ТЗ_Фильтр = ТЗ_ВсеТовары.СкопироватьКолонки();

// Выполняем поиск строк по структуре
Парам = Новый Структура("Помещение", НужноеПомещение);
МассивСтрок = ТЗ_ВсеТовары.НайтиСтроки(Парам);

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

Использование метода ЗаполнитьЗначенияСвойств позволяет быстро скопировать все данные из строки-источника в строку-приемник без перечисления каждого поля вручную.

Метод 3: Оптимизация через Индексы для больших таблиц

Если в вашей таблице десятки тысяч строк, последовательный перебор при каждом вызове Скопировать() или НайтиСтроки() приведет к существенным задержкам. Чтобы ускорить процесс, необходимо использовать индексацию.

Разберем, как добавить индекс перед началом обработки:


// Добавляем индекс по колонке, по которой будет идти поиск
ТЗ_ВсеТовары.Индексы.Добавить("Помещение");
// Теперь методы НайтиСтроки() и Скопировать() будут работать на порядок быстрее

Важный момент: Индексация имеет смысл только в том случае, если вы планируете выполнять поиск многократно. Создание самого индекса также требует времени и ресурсов памяти.

Метод 4: Сложная фильтрация с помощью Запроса

Если условие фильтрации сложнее, чем просто "равно" (например, нужно отобрать товары, где цена больше 100 и остаток меньше 10), структура отбора не подойдет. В этом случае лучше использовать механизм запросов.

Посмотрим на алгоритм действий:

  1. Создаем новый Запрос.
  2. Создаем МенеджерВременныхТаблиц.
  3. Передаем исходную ТЗ в запрос как параметр.
  4. Во тексте запроса описываем условия в секции ГДЕ.
  5. Выгружаем результат запроса методом Выгрузить().

МВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МВТ;

// Передаем таблицу в запрос
Запрос.Текст = 
    "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Товары ИЗ &ТЗ КАК ТЗ;
    |ВЫБРАТЬ * ИЗ ВТ_Товары ГДЕ Помещение = &Помещение И Цена > 100";
    
Запрос.УстановитьПараметр("ТЗ", ТЗ_ВсеТовары);
Запрос.УстановитьПараметр("Помещение", НужноеПомещение);

ДанныеЗаказа = Запрос.Выполнить().Выгрузить();

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

Метод 5: Фильтрация "на месте" путем удаления строк

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


ТЗ_Копия = ТЗ_ВсеТовары.Скопировать();
КоличествоСтрок = ТЗ_Копия.Количество();

// Обходим таблицу с конца
Для Счетчик = 1 По КоличествоСтрок Цикл
    Индекс = КоличествоСтрок - Счетчик;
    Стр = ТЗ_Копия[Индекс];
    
    Если Стр.Помещение <> "НужноеПомещение" Тогда
        ТЗ_Копия.Удалить(Стр);
    КонецЕсли;
КонецЦикла;

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

Выясним, какой метод лучше выбрать в конкретной ситуации:

Использование правильного метода фильтрации не только упрощает код, но и значительно повышает стабильность работы системы при росте объемов обрабатываемой информации.

← На главную