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