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

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

Как сделать отбор в массиве 1С

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

Задача отбора элементов из массива встречается в 1С постоянно: нужно выбрать строки с определённым складом, документы за период, контрагентов с задолженностью. Встроенный язык не имеет отдельной функции «фильтр массива», поэтому отбор реализуется несколькими способами — от простого перебора с условием до выгрузки в таблицу значений и использования запроса.

Выбор способа зависит от того, что лежит в массиве. Если это простые значения (строки, числа, ссылки), подойдёт цикл с проверкой условия. Если массив содержит структуры или строки таблицы значений, удобнее метод НайтиСтроки или запрос. Для больших объёмов данных правильнее вообще не загружать всё в массив, а отбирать на стороне СУБД.

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

Отбор перебором: универсальный способ для любого массива

Базовый приём — создать пустой массив-результат и в цикле проверять каждый элемент исходного массива. Если элемент удовлетворяет условию, он добавляется в результат методом Добавить(). Способ работает с любыми типами данных и не требует дополнительных объектов.

МассивСкладов = Новый Массив;

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

МассивСкладов.Добавить("Розничный");

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

Отобранные = Новый Массив;

Для Каждого Элемент Из МассивСкладов Цикл

Если Элемент = "Основной" Тогда

Отобранные.Добавить(Элемент);

КонецЕсли;

КонецЦикла;

// Отобранные содержит 2 элемента

Если в массиве лежат ссылки или структуры, условие проверяется по реквизиту или ключу. Обратите внимание: обращение к реквизиту ссылки в цикле вызывает обращение к базе данных за каждым элементом — при сотнях элементов это заметно замедлит код.

Отобранные = Новый Массив;

Для Каждого Строка Из МассивСтруктур Цикл

Если Строка.Сумма > 10000 И Строка.Проведен Тогда

Отобранные.Добавить(Строка);

КонецЕсли;

КонецЦикла;

Отбор строк таблицы значений методом НайтиСтроки

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

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

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

Отбор.Вставить("Активен", Истина);

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

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

// обработка отобранных строк

КонецЦикла;

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

Тот же приём работает для табличных частей документов и справочников: Документ.Товары.НайтиСтроки(Отбор) вернёт массив строк табличной части. Это стандартный способ найти в документе строки с конкретной номенклатурой.

Отбор через запрос: быстро и для больших объёмов

Если массив содержит ссылки и нужно отобрать их по реквизитам, самый производительный путь — запрос с параметром-массивом. Платформа умеет передавать массив в параметр и проверять вхождение оператором В.

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

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

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Ссылка В (&МассивСсылок)

| И Номенклатура.ВидНоменклатуры = &Вид";

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

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

Отобранные = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");

Метод ВыгрузитьКолонку возвращает массив — то есть на выходе вы получаете отфильтрованный массив ссылок одним обращением к базе. Это правильная замена циклу с проверкой реквизитов.

Запросом можно отбирать и внутри таблицы значений: передайте её как параметр, поместите во временную таблицу и наложите любые условия — сравнения, ПОДОБНО, соединения с другими таблицами.

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

Отбор в динамических списках и формах

Отдельный сценарий — отбор не в прикладном массиве, а в списке на форме. Для динамического списка отбор задаётся через элементы коллекции Отбор.Элементы: добавляется элемент, указывается поле, вид сравнения и значение.

ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ПометкаУдаления");

ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;

ЭлементОтбора.ПравоеЗначение = Ложь;

ЭлементОтбора.Использование = Истина;

Если нужно отобрать по списку значений (аналог отбора массивом), используйте вид сравнения ВСписке и передайте в правое значение СписокЗначений или массив. Это стандартный способ показать в списке только документы по выбранным контрагентам.

Для таблицы значений на форме (реквизит формы) применяется свойство ОтборСтрок у элемента формы — туда передаётся фиксированная структура отбора, похожая на параметр НайтиСтроки.

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

Сравнение вариантов

Перебор в цикле

Универсален, работает с любыми типами и сложными условиями. Медленный при обращении к реквизитам ссылок и на очень больших массивах.

НайтиСтроки

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

Запрос с В (&Массив)

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

Отбор динамического списка

Единственный правильный способ фильтровать данные в форме списка; не применим для программной обработки массивов в коде.

Как ориентироваться на практике: массив простых значений — цикл; таблица значений и равенство — НайтиСтроки; ссылки и проверка реквизитов — запрос; отображение пользователю — отбор списка на форме.

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

Как выбрать действие

В массиве строки, числа, даты и условие простоеИспользуйте цикл Для Каждого с проверкой и новым массивом-результатом
Данные в таблице значений и отбор по равенствуПримените НайтиСтроки со структурой отбора
Нужно отобрать ссылки по реквизитам из базыНапишите запрос с параметром-массивом и оператором В
Нужно скрыть лишние строки в списке на формеНастройте Отбор.Элементы динамического списка или ОтборСтрок таблицы формы

Типичные ошибки и как их избежать

Первая распространённая ошибка — удаление элементов из массива внутри цикла перебора. Индексы смещаются, часть элементов пропускается. Если нужно именно удалить, а не собрать новый массив, перебирайте массив с конца по индексу.

Для Инд = 1 - Массив.Количество() По 0 Цикл

Индекс = -Инд;

Если Не УсловиеПодходит(Массив[Индекс]) Тогда

Массив.Удалить(Индекс);

КонецЕсли;

КонецЦикла;

Вторая ошибка — сравнение ссылок по строковому представлению или наименованию. Сравнивайте ссылки напрямую оператором равенства: платформа корректно сравнивает ссылки одного типа, а поиск по наименованию даст дубли и ложные совпадения.

Третья ошибка — игнорирование пустого результата. НайтиСтроки и запрос законно возвращают пустой массив; обращение к элементу по индексу без проверки Количество() приведёт к ошибке выполнения.

Типичные ошибки
01
Удаление элементов в прямом цикле перебора — пропускаются элементы из-за сдвига индексов; удаляйте с конца или собирайте новый массив
02
Проверка реквизитов ссылок в цикле — сотни обращений к базе; заменяйте запросом с В(&Массив)
03
Ожидание от НайтиСтроки условий больше/меньше — метод сравнивает только на равенство
04
Отсутствие проверки пустого результата — обращение к Отобранные[0] вызывает ошибку, если ничего не найдено

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

После отбора полезно убедиться, что результат соответствует ожиданиям: количество элементов, отсутствие дублей, корректность данных. Для отладки используйте Сообщить() с количеством элементов или смотрите содержимое массива в отладчике через табло.

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

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

Количество отобранных элементов
Норма

Совпадает с ожидаемым числом по тестовым данным

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

Ноль при заведомо подходящих данных — проверьте условие и типы сравниваемых значений

Типы значений в условии
Норма

Сравниваются значения одного типа (ссылка со ссылкой, строка со строкой)

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

Ссылка сравнивается со строкой — отбор всегда пустой

Дубли в результате
Норма

Каждый элемент встречается ожидаемое число раз

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

Дубли из-за повторного добавления или неуникального ключа отбора

Для тонкой проверки условий с датами помните, что сравнение дат учитывает время: отбор «Дата = 01.01.2026» не найдёт документ с датой 01.01.2026 10:30:00. Используйте диапазоны или функции НачалоДня/КонецДня.

Часто задаваемые вопросы

Можно ли отобрать элементы массива по части строки (аналог LIKE)?

Напрямую в цикле — через функцию СтрНайти(Элемент, Подстрока) > 0. Для таблицы значений удобнее запрос с оператором ПОДОБНО и шаблоном "%подстрока%", передав таблицу как параметр во временную таблицу.

Как удалить из массива дубли?

Пройдите по массиву и добавляйте элементы в новый массив только если Новый.Найти(Элемент) = Неопределено. Для больших массивов быстрее выгрузить значения в таблицу значений и применить Свернуть() по колонке.

НайтиСтроки ничего не находит, хотя значения есть. В чём причина?

Чаще всего несовпадение типов: в колонке хранится ссылка, а в структуре отбора передана строка, или число сравнивается со строкой. Проверьте тип значения в колонке в отладчике и приведите значение отбора к тому же типу.

Можно ли передать массив в параметр запроса для отбора?

Да. Установите параметр методом УстановитьПараметр("Имя", Массив) и используйте в тексте запроса условие Поле В (&Имя). Платформа сама преобразует массив в список значений для СУБД.

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

Для данных уже в памяти и простого равенства НайтиСтроки обычно быстрее цикла. Если отбор требует чтения реквизитов ссылок из базы, запрос выигрывает у любого перебора, потому что выполняет одно обращение к СУБД вместо множества.

Как отобрать строки табличной части документа по номенклатуре?

Сформируйте структуру: Отбор = Новый Структура("Номенклатура", ИскомаяСсылка) и вызовите ДокументОбъект.Товары.НайтиСтроки(Отбор). Метод вернёт массив строк табличной части, доступных для чтения и изменения.

Итог

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

Отбор в массиве 1С делается циклом с условием и новым массивом-результатом; для таблиц значений — НайтиСтроки с равенством; для ссылок с проверкой реквизитов — запросом с В(&Массив). Не удаляйте элементы в прямом переборе, следите за типами сравниваемых значений и всегда проверяйте пустой результат.