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