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