При разработке на платформе 1С:Предприятие 8 программисты часто сталкиваются с задачей поиска данных внутри коллекций, таких как табличные части (ТЧ). Стандартный подход с использованием цикла Для Каждого прост в реализации, но крайне неэффективен при работе с большими объемами данных. В этой статье мы подробно разберем, как реализовать групповой поиск значений, избегая последовательного перебора строк, и проанализируем наиболее производительные методы, доступные в системе.
Метод НайтиСтроки() является штатным инструментом для поиска в таблицах значений и табличных частях. Однако у него есть существенная особенность: в качестве параметра отбора он принимает Структура. Это накладывает два серьезных ограничения:
Рассмотрим ситуацию, когда нам нужно найти строки, где в колонке Номенклатура содержится любое значение из массива МассивТоваров. Передать массив напрямую в структуру поиска нельзя. Выясним, какие альтернативы существуют для решения этой задачи.
Проанализируем самый мощный и гибкий способ — использование языка запросов. Этот метод позволяет реализовать условие В (&Массив), которое идеально подходит для поиска множества значений за один раз. Это особенно актуально, когда поиск выполняется на стороне сервера.
Разберем алгоритм по шагам:
ТаблицаЗначений.ГДЕ Поле В (&МассивЗначений).Пример программного кода для реализации этого метода:
// Допустим, у нас есть МассивНужныхЗначений и Объект.Товары (табличная часть)
// 1. Выгружаем ТЧ в таблицу значений
ТЗ_Товары = Объект.Товары.Выгрузить();
// 2. Создаем запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВременнаяТаблица.НомерСтроки,
| ВременнаяТаблица.Номенклатура,
| ВременнаяТаблица.Количество
|ПОМЕСТИТЬ ВТ_Товары
|ИЗ
| &ТЗ_Товары КАК ВременнаяТаблица
|;
|
|ВЫБРАТЬ
| ВТ_Товары.НомерСтроки
|ИЗ
| ВТ_Товары КАК ВТ_Товары
|ГДЕ
| ВТ_Товары.Номенклатура В (&МассивНужныхЗначений)";
Запрос.УстановитьПараметр("ТЗ_Товары", ТЗ_Товары);
Запрос.УстановитьПараметр("МассивНужныхЗначений", МассивНужныхЗначений);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Работаем с найденными строками
// Например, можно получить саму строку ТЧ по индексу (НомерСтроки - 1)
СтрокаТЧ = Объект.Товары[Выборка.НомерСтроки - 1];
КонецЦикла;
Если специфика задачи все же требует использования метода НайтиСтроки() в цикле (например, при сложной логике объединения результатов), критически важно обеспечить скорость работы этого метода. По умолчанию НайтиСтроки() выполняет последовательное сканирование коллекции, что при 10 000 строк превращается в очень медленную операцию.
Посмотрим на пример того, как ускорить поиск с помощью индексов. Индексация создает хеш-таблицу в памяти, что позволяет находить нужные строки практически мгновенно.
// Сначала выгружаем в таблицу значений
ТаблицаПоиска = Объект.Товары.Выгрузить();
// ОБЯЗАТЕЛЬНО добавляем индекс по колонке, по которой будем искать
ТаблицаПоиска.Индексы.Добавить("Номенклатура");
// Теперь поиск в цикле по массиву будет работать в десятки раз быстрее
ОбщийМассивСтрок = Новый Массив;
Для Каждого ИскомоеЗначение Из МассивНужныхЗначений Цикл
Отбор = Новый Структура("Номенклатура", ИскомоеЗначение);
НайденныеСтроки = ТаблицаПоиска.НайтиСтроки(Отбор);
// Добавляем результаты в общую коллекцию
Для Каждого Строка Из НайденныеСтроки Цикл
ОбщийМассивСтрок.Добавить(Строка);
КонецЦикла;
КонецЦикла;
Иногда под "поиском" подразумевается фильтрация строк на экране, чтобы пользователь увидел только те позиции, которые входят в массив. В управляемых формах для этого используется свойство ОтборСтрок элемента формы типа Таблица. Для настройки отборов и фильтрации зависимых строк на форме можно использовать решение для связывания табличных частей на управляемых формах.
Однако здесь мы сталкиваемся с тем же ограничением: ФиксированнаяСтруктура, используемая в ОтборСтрок, не поддерживает массивы. Чтобы обойти это ограничение, программисты часто используют один из следующих приемов:
ПометкаПоиска (тип Булево). Проходим по ТЧ, устанавливаем Истина для строк, входящих в массив, и устанавливаем отбор по этой колонке.ДинамическийСписок с произвольным запросом, где условие В (&Массив) реализуется стандартным методом УстановитьПараметр().Проанализируем ситуацию: какой метод выбрать в зависимости от условий задачи?
ТаблицаЗначений и один раз постройте Индекс. Это обеспечит максимальную отзывчивость системы.Важный нюанс: Помните, что при выгрузке табличной части в таблицу значений (Выгрузить()) вы работаете с копией данных. Если вы измените данные в ТаблицаЗначений, они не изменятся в исходной табличной части объекта автоматически. Для связи всегда используйте колонку НомерСтроки или уникальный идентификатор строки.
Таким образом, мы выяснили, что "красивого" метода вроде НайтиСтрокиПоМассиву() в 1С не существует, но комбинация выгрузки в ТЗ и использования запроса является индустриальным стандартом решения этой задачи, обеспечивающим отличную производительность и чистоту кода.