Как выполнить отбор по типу документа в таблице значений (метод НайтиСтроки)?

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

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

Выясним причину: почему НайтиСтроки не работает с типом напрямую

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

Когда мы передаем в отбор Тип("ДокументСсылка.ПеремещениеНоменклатуры"), система сравнивает объект типа «Ссылка» с объектом типа «Тип». Естественно, они никогда не будут равны. Метод НайтиСтроки() не умеет вычислять тип значения «на лету» для каждой строки, он просто сравнивает содержимое ячеек с тем, что передано в структуру отбора.

Решение №1: Использование цикла (классический метод)

Самый простой и понятный способ — это ручной перебор строк. Мы создаем массив, в который будем помещать найденные строки, и проверяем условие типа для каждой строки. Разберем по шагам реализацию этого метода:


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

Преимущества: простота реализации, не требуется модификация структуры ТаблицаЗначений.

Недостатки: низкая скорость работы на очень больших объемах данных (десятки и сотни тысяч строк), так как цикл выполняется в интерпретаторе 1С.

Решение №2: Вспомогательная колонка «ТипДокумента»

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

Рассмотрим, как это реализовать программно:

  1. Добавляем колонку в таблицу значений.
  2. Заполняем её типами значений из основной колонки.
  3. Выполняем поиск по новой колонке.

// 1. Добавляем колонку
ДанныеТз.Колонки.Добавить("ТипРегистратора", Новый ОписаниеТипов("Тип"));

// 2. Заполняем её
Для каждого Стр Из ДанныеТз Цикл
    Стр.ТипРегистратора = ТипЗнч(Стр.РегистраторСсылка);
КонецЦикла;

// 3. Теперь НайтиСтроки сработает корректно
Отбор = Новый Структура;
Отбор.Вставить("ТипРегистратора", Тип("ДокументСсылка.ПеремещениеНоменклатуры"));
НайденныеСтроки = ДанныеТз.НайтиСтроки(Отбор);

Если вы получаете таблицу из запроса, колонку с типом можно добавить еще эффективнее, используя конструкцию ТипЗначения(Ссылка) КАК ТипДокумента прямо в тексте запроса.

Решение №3: Запрос к таблице значений (универсальный способ)

Наиболее профессиональным и гибким способом является использование объекта Запрос. Платформа позволяет передавать ТаблицаЗначений в качестве параметра запроса и работать с ней как с временной таблицей. Посмотрим на пример:


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

Важный нюанс: Чтобы запрос к ТаблицаЗначений сработал, у колонок таблицы должны быть четко определены типы. Если колонка «Регистратор» имеет тип ПроизвольноеПоле, запрос может выдать ошибку. Используйте ОписаниеТипов при создании или доработке таблицы.

Специфика работы с Системой компоновки данных (СКД)

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

Сравнение производительности и рекомендации

При выборе метода стоит ориентироваться на объем данных:

  1. Для небольших таблиц (до 1000 строк): Используйте обычный цикл Для каждого. Это быстро пишется и легко отлаживается.
  2. Для средних таблиц: Метод с вспомогательной колонкой и НайтиСтроки() показывает хорошие результаты, особенно если поиск нужно выполнять многократно. Помните, что для ускорения НайтиСтроки() можно использовать Индексы.Добавить("ИмяКолонки").
  3. Для сложных выборок и больших объемов: Запрос к таблице значений — самый мощный инструмент. Он позволяет использовать операторы ССЫЛКА, ВЫРАЗИТЬ, объединения и другие возможности языка запросов 1С, которые работают оптимизировано на уровне платформы.

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

← На главную