К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как сделать отбор в таблице значений 1С

Как выполнить отбор строк в таблице значений 1С: метод НайтиСтроки, параметры отбора, обход строк, запрос к таблице. Примеры кода, типичные ошибки и FAQ.

Таблица значений в 1С — это объект для хранения и обработки данных в памяти: списков товаров, строк документов, результатов обмена. Почти в каждой обработке возникает задача выбрать из таблицы только нужные строки — например, позиции с определённым складом, контрагентом или ненулевым остатком. Для этого в платформе есть несколько инструментов, и выбор между ними влияет и на скорость кода, и на его читаемость.

Основной способ отбора — метод НайтиСтроки() с параметром типа «Структура». Дополнительно используются перебор строк с условием, метод Найти() для поиска одной строки, построитель отчёта и временный запрос к таблице. Ниже разобраны все варианты с примерами кода, ограничениями и типичными ошибками.

Как работает метод НайтиСтроки

Метод НайтиСтроки() принимает один обязательный параметр — структуру, где ключи совпадают с именами колонок таблицы, а значения задают условия поиска. Результат — массив строк таблицы значений, удовлетворяющих всем условиям одновременно (условия объединяются по логике «И»). Если совпадений нет, возвращается пустой массив, а не Неопределено — это важно при проверке результата.

Типичный пример: есть таблица Товары с колонками «Номенклатура», «Склад», «Количество». Нужно выбрать строки по конкретному складу:

Отбор = Новый Структура;

Отбор.Вставить("Склад", ОсновнойСклад);

НайденныеСтроки = Товары.НайтиСтроки(Отбор);

Для Каждого Строка Из НайденныеСтроки Цикл

Сообщить(Строка.Номенклатура);

КонецЦикла;

Отбор можно задавать сразу по нескольким колонкам. Например, найти строки по складу и номенклатуре одновременно: Новый Структура("Склад, Номенклатура", Склад, Товар). Порядок ключей в структуре на результат не влияет.

Отбор по нескольким условиям и поиск одной строки

Несколько полей в структуре отбора

Когда условий несколько, удобно формировать структуру динамически, добавляя ключи только при заполненных значениях. Это типовой приём в формах обработок, где пользователь может задать часть фильтров:

Отбор = Новый Структура;

Если ЗначениеЗаполнено(Склад) Тогда

Отбор.Вставить("Склад", Склад);

КонецЕсли;

Если ЗначениеЗаполнено(Номенклатура) Тогда

Отбор.Вставить("Номенклатура", Номенклатура);

КонецЕсли;

Если Отбор.Количество() > 0 Тогда

Строки = Товары.НайтиСтроки(Отбор);

Иначе

Строки = Товары; // отбор не задан — работаем со всей таблицей

КонецЕсли;

Когда нужна только одна строка — метод Найти

Если заведомо достаточно первого совпадения (например, поиск по уникальному коду), используйте Найти(Значение, ИмяКолонки). Он возвращает строку или Неопределено, если ничего не найдено. Это короче и быстрее, чем НайтиСтроки с последующей проверкой количества:

Строка = Товары.Найти(ИскомыйКод, "Код");

Если Строка = Неопределено Тогда

// строки с таким кодом нет

КонецЕсли;

Сравнение способов отбора

НайтиСтроки

Равенство по одной или нескольким колонкам, нужны все совпадения. Не поддерживает неравенство, «ИЛИ», сравнения «больше/меньше».

Найти

Нужна одна строка по равенству в одной колонке. Возвращает Неопределено при отсутствии результата.

Перебор с условием

Сложные условия: неравенство, диапазоны, сравнение колонок между собой, логика «ИЛИ». Требует ручного цикла.

Запрос к таблице

Большие таблицы, группировки, соединения, сортировка результата. Требует передачи таблицы параметром и текста запроса.

Отбор со сложными условиями через перебор строк

Метод НайтиСтроки умеет только равенство. Если условие — «количество больше нуля», «дата в диапазоне», «склад не равен указанному» или «совпадает хотя бы одно из полей», применяется обычный цикл с проверкой внутри:

Для Каждого Строка Из Товары Цикл

Если Строка.Количество > 0

И Строка.Склад <> РезервныйСклад Тогда

// обработка подходящей строки

КонецЕсли;

КонецЦикла;

Если отобранные строки нужны отдельно, создайте копию таблицы с теми же колонками через Товары.СкопироватьКолонки() и добавляйте в неё подходящие строки методом ЗаполнитьЗначенияСвойств или вручную. Альтернатива — метод Скопировать() с параметром отбора: Товары.Скопировать(Новый Структура("Склад", Склад)) вернёт новую таблицу только с отобранными строками.

Учтите: удалять строки из таблицы прямо в цикле Для Каждого нельзя — это приводит к пропуску строк или ошибке. Для удаления соберите строки в массив и удаляйте после цикла, либо используйте индексный цикл с конца таблицы к началу.

Отбор через запрос к таблице значений

Когда таблица большая, а условия сложные — соединение с другой таблицей, группировка, сортировка, функции над полями — выгоднее передать таблицу в запрос как параметр и отобрать данные средствами языка запросов:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Т.Номенклатура,

| СУММА(Т.Количество) КАК Количество

|ПОМЕСТИТЬ ВТ

|ИЗ &Товары КАК Т

|ГДЕ Т.Склад = &Склад

|;

|ВЫБРАТЬ * ИЗ ВТ

|УПОРЯДОЧИТЬ ПО Количество УБЫВ";

Запрос.УстановитьПараметр("Товары", Товары);

Запрос.УстановитьПараметр("Склад", Склад);

Результат = Запрос.Выполнить().Выгрузить();

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

На таблицах в несколько десятков тысяч строк разница между НайтиСтроки и перебором почти незаметна, но запрос к таблице удобнее, когда дальше нужны итоги или сортировка. Для пары сотен строк выбирайте самый читаемый вариант, а не самый «быстрый».
ПЗ
Практическое замечание

Проверка результата отбора

После НайтиСтроки всегда проверяйте количество найденных строк перед обращением к элементам массива. Обращение НайденныеСтроки[0] без проверки — частый источник ошибки «Индекс находится за границами массива»:

Если НайденныеСтроки.Количество() = 0 Тогда

// ничего не найдено — обработать ситуацию

ИначеЕсли НайденныеСтроки.Количество() = 1 Тогда

// ровно одна строка — ожидаемый случай

Иначе

// дублей быть не должно — стоит зафиксировать предупреждение

КонецЕсли;

Для метода Найти проверка другая — на Неопределено. Смешивать эти подходы нельзя: НайтиСтроки никогда не вернёт Неопределено, а Найти никогда не вернёт пустой массив.

Контрольные точки

Как проверить результат

Что вернул НайтиСтроки
Норма

Массив, возможно пустой — проверяем Количество()

Тревожный признак

Сравнение с Неопределено — такой проверки недостаточно, условие никогда не сработает

Что вернул Найти
Норма

Строка таблицы или Неопределено

Тревожный признак

Обращение к полям результата без проверки на Неопределено

Тип значения в отборе
Норма

Тип совпадает с типом колонки

Тревожный признак

Строка вместо числа или ссылки — отбор молча ничего не находит

Типичные ошибки при отборе в таблице значений

Большинство проблем с отбором сводится к несовпадению типов и неверным ожиданиям от результата. Разберём самые частые сценарии.

Первая группа ошибок — типы данных. Если колонка имеет составной тип или значение пришло из формы как строка, отбор по ссылке или числу ничего не найдёт, и платформа не сообщит об этом — просто вернёт пустой массив. Вторая группа — логика: разработчик ожидает поведение «ИЛИ», а НайтиСтроки всегда работает по «И». Для «ИЛИ» нужно либо несколько вызовов с объединением массивов, либо перебор с условием.

Типичные ошибки
01
Опечатка в имени колонки в структуре отбора — платформа выдаст ошибку только в момент выполнения, а не при компиляции модуля.
02
Проверка результата НайтиСтроки на Неопределено вместо проверки Количество() — ветка «не найдено» никогда не выполнится.
03
Отбор по строковому представлению ссылки вместо самой ссылки — сравнение не сработает, результат пустой.
04
Удаление строк внутри цикла Для Каждого — пропуск строк и непредсказуемый результат.
05
Ожидание логики «ИЛИ» от нескольких ключей структуры — НайтиСтроки объединяет условия только по «И».

Отбор в таблице на управляемой форме

Когда таблица значений является реквизитом управляемой формы, пользовательский отбор визуально делается через настройки динамического списка или стандартные команды, но программно действуют те же методы. Дополнительный нюанс: реквизит формы типа «ТаблицаЗначений» на клиенте недоступен для методов НайтиСтроки в тонком клиенте без контекста сервера — поэтому отбор выполняют в серверной процедуре через РеквизитФормыВЗначение("Товары"), а результат возвращают обратно.

Для отбора строк, отображаемых в элементе формы «ТаблицаФормы», есть свойство ОтборСтрок — оно принимает структуру или фиксированную структуру и фильтрует только видимые строки, не изменяя данные. Это удобно для интерфейсных фильтров без копирования таблицы:

Элементы.Товары.ОтборСтрок = Новый ФиксированнаяСтруктура("Склад", Склад);

// снять отбор:

Элементы.Товары.ОтборСтрок = Неопределено;

Маршрут решения

Как выбрать способ

Нужны строки по точному равенству одного или нескольких полейИспользуйте НайтиСтроки со структурой отбора
Нужна одна строка по уникальному значениюИспользуйте Найти и проверку на Неопределено
Условие содержит неравенство, диапазон или «ИЛИ»Перебирайте строки циклом с условием или используйте запрос
Нужна отдельная таблица с отобранными строкамиВызовите Скопировать(ПараметрыОтбора)
Нужно только скрыть лишние строки в формеУстановите ОтборСтрок у элемента таблицы формы

Частые вопросы

Можно ли в НайтиСтроки задать условие «не равно»?

Нет, метод поддерживает только равенство. Для условия «не равно» используйте перебор строк с проверкой Если Строка.Склад <> Склад Тогда или запрос к таблице значений с оператором ГДЕ.

Как отобрать строки по нескольким возможным значениям одной колонки (условие «ИЛИ»)?

Сделайте массив допустимых значений и в цикле проверяйте вхождение: Если Склады.Найти(Строка.Склад) <> Неопределено Тогда. В запросе тот же эффект даёт оператор В (&СписокСкладов).

Почему НайтиСтроки возвращает пустой массив, хотя строка точно есть?

Чаще всего не совпадает тип значения: в колонке ссылка, а в отборе строка; или в колонке число, а передана строка. Проверьте типы через ТипЗнч() и убедитесь, что имя колонки в структуре написано без ошибок и лишних пробелов.

Как получить новую таблицу только с отобранными строками?

Используйте НоваяТаблица = Товары.Скопировать(Новый Структура("Склад", Склад)). Метод вернёт таблицу с теми же колонками, содержащую только строки, удовлетворяющие отбору. Для сложных условий скопируйте колонки методом СкопироватьКолонки и добавляйте строки в цикле.

Что быстрее: НайтиСтроки или перебор циклом?

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

Можно ли отсортировать результат отбора?

Массив строк, возвращаемый НайтиСтроки, отдельно не сортируется. Отсортируйте саму таблицу методом Сортировать("Колонка Возр") до отбора, либо получите результат через запрос с УПОРЯДОЧИТЬ ПО, либо скопируйте строки в новую таблицу и отсортируйте её.

Итог

Что важно запомнить

Базовый отбор в таблице значений — НайтиСтроки со структурой «колонка = значение», результат всегда массив, который проверяют через Количество(). Для одной строки подходит Найти с проверкой на Неопределено, для сложных условий — цикл с условием или запрос к таблице. Следите за совпадением типов значений и не меняйте таблицу внутри цикла по ней.