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