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

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

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

Как программно установить отбор в 1С: ОтборСтрок, элементы отбора динамического списка, СКД и запросы. Примеры кода, типичные ошибки и проверка результата.

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

Единого «универсального» способа отбора нет: метод зависит от того, где находятся данные. Для таблицы значений используется метод НайтиСтроки() с отбором, для динамического списка формы — коллекция ЭлементыОтбора, для отчётов на СКД — настройки компоновщика, а для выборки из базы — условие ГДЕ в запросе. Ниже разобраны все основные сценарии с рабочими примерами кода.

Отбор в таблице значений через НайтиСтроки

Таблица значений — самый частый объект, с которым работают на сервере: результат запроса, загруженные из файла данные, промежуточные расчёты. Чтобы выбрать из неё нужные строки, используется метод НайтиСтроки(), которому передаётся структура с условиями отбора.

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

Отбор.Вставить("Организация", ТекущаяОрганизация);

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

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

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

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

КонецЦикла;

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

Если нужен отбор с условием «ИЛИ» или сложным сравнением, используйте обычный обход:

Для Каждого Строка Из ТаблицаДокументов Цикл

Если Строка.Сумма > 100000 ИЛИ Строка.Валюта = ВалютаUSD Тогда

// строка проходит отбор

КонецЕсли;

КонецЦикла;

Программный отбор динамического списка на форме

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

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

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

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

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

ЭлементОтбора.ПравоеЗначение = Параметры.Организация;

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

ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;

КонецПроцедуры;

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

Изменение и отключение существующего отбора

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

Для Каждого ЭлементОтбора Из Список.Отбор.Элементы Цикл

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

ЭлементОтбора.ПравоеЗначение = НоваяОрганизация;

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

КонецЕсли;

КонецЦикла;

bsl
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
ЭлементОтбора.ПравоеЗначение = СписокКонтрагентов;
ЭлементОтбора.Использование = Истина;

Отбор в запросе через условие ГДЕ

Когда данные нужно выбрать из базы, а не из уже загруженной таблицы, правильное место для отбора — текст запроса. Условие задаётся в секции ГДЕ, а значения передаются через параметры. Это быстрее и безопаснее, чем выгружать всю таблицу и фильтровать её в коде.

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

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

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Ссылка,

| РеализацияТоваровУслуг.СуммаДокумента

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода

| И РеализацияТоваровУслуг.Контрагент = &Контрагент

| И РеализацияТоваровУслуг.Проведен";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));

Запрос.УстановитьПараметр("Контрагент", ВыбранныйКонтрагент);

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

Никогда не подставляйте значения в текст запроса конкатенацией строк — только через параметры. Подстановка строк ломает запрос на специальных символах, создаёт риск ошибок с типами дат и чисел и затрудняет отладку. Для отбора по списку значений используйте оператор В (&СписокЗначений), передав в параметр массив или список значений.

Отбор в отчётах на СКД

В отчётах на системе компоновки данных программный отбор добавляется в настройки компоновщика. Типичная задача — установить отбор до формирования отчёта, например по значению из параметров открытия формы.

Настройки = Отчет.КомпоновщикНастроек.Настройки;

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

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

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

ЭлементОтбора.ПравоеЗначение = ВыбранныйСклад;

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

Если отбор задаётся из обработчика ПриСозданииНаСервере формы отчёта, обращайтесь к Отчет.КомпоновщикНастроек.Настройки. Учтите, что при загрузке пользовательских настроек программно добавленный отбор может быть перекрыт — проверяйте итоговое поведение на форме после всех стандартных обработчиков.

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

НайтиСтроки() таблицы значений

Подходит для данных уже в памяти. Только равенство, только серверный код.

Список.Отбор на форме

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

Условие ГДЕ в запросе

Оптимально для выборки из базы: фильтрация на стороне СУБД, минимальный объём передаваемых данных.

Отбор в настройках СКД

Для отчётов: гибкие условия, группы И/ИЛИ, интеграция с пользовательскими настройками.

Выбор вида сравнения и типичные условия

Вид сравнения определяет, как система будет сопоставлять значение поля с эталоном. Выбор зависит от типа данных и задачи.

Вид сравненияКогда применятьОсобенность
Равно / НеРавноСсылки, булево, точные значенияСтрогое совпадение значения и типа
ВСписке / НеВСпискеНесколько допустимых значенийПравое значение — список значений или массив
Больше / Меньше / МеждуЧисла, датыВ запросе «между» задаётся оператором МЕЖДУ
Содержит / НачинаетсяСПоиск по строкамРаботает медленно на больших таблицах, не использует индекс
ВИерархииОтбор по группе справочникаВключает все элементы вложенных групп

Для иерархических справочников (номенклатура, статьи затрат) отбор «Равно» по группе не вернёт элементы внутри неё — нужен вид сравнения ВИерархии или оператор В ИЕРАРХИИ (&Группа) в запросе. Это одна из самых частых причин «неполного» отбора у начинающих разработчиков.

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

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

Нужно отфильтровать форму списка при открытииДобавьте элемент в Список.Отбор в ПриСозданииНаСервере
Нужно выбрать данные для обработки или отчёта из кодаИспользуйте запрос с параметрами и условием ГДЕ
Данные уже выгружены в таблицу значенийПримените НайтиСтроки() или цикл с проверкой условия
Отбор должен настраиваться пользователем в отчётеДобавьте поле в отбор настроек СКД и задайте значение программно

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

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

Полезный приём — вывести итоговый текст запроса динамического списка или СКД в консоли кода (внешняя обработка «Консоль кода» или аналог) и выполнить его с теми же параметрами. Если консоль даёт строки, а форма пустая, проблема в дополнительных элементах отбора, добавленных ранее или пользовательскими настройками.

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

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

Количество строк результата
Норма

Совпадает с ожидаемым при ручной проверке в списке

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

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

Панель настроек динамического списка
Норма

Отбор отображается с нужным условием и включён

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

Отбора нет или он выключен — проверьте свойство Использование

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

Тип совпадает с типом поля (ссылка, дата, число)

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

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

Повторное открытие формы
Норма

Отбор применяется стабильно

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

Отбор пропадает — его перекрывают пользовательские настройки

Типичные ошибки при программном отборе

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

Типичные ошибки
01
Несовпадение типов: в правое значение передана строка "000000001" вместо ссылки на элемент — отбор молча возвращает пустой результат.
02
Дублирование элементов отбора: при каждом вызове процедуры добавляется новый элемент, условия перемножаются по «И» и список пустеет.
03
Отбор по группе справочника видом «Равно» вместо «ВИерархии» — элементы вложенных групп не попадают в результат.
04
Установка отбора на клиенте там, где нужен серверный контекст, — коллекция Список.Отбор доступна на сервере формы.
05
Подстановка значений в текст запроса конкатенацией вместо параметров — ошибки синтаксиса и неверные типы.

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

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

FAQ: частые вопросы о программном отборе

Как сделать отбор по нескольким значениям одного поля?

Используйте вид сравнения «ВСписке» и передайте в правое значение список значений или массив. В запросе аналог — оператор «В (&Список)» с параметром-массивом. Не добавляйте несколько элементов отбора по одному полю с видом «Равно»: они объединятся по «И», и результат будет пустым.

Почему отбор установлен, но список не фильтруется?

Чаще всего не установлено свойство Использование = Истина, либо отбор добавлен не в ту коллекцию (например, в фиксированные настройки, которые затем перезаписываются). Также проверьте, что тип правого значения совпадает с типом поля, — при несовпадении типов отбор тихо не срабатывает.

Как убрать программно установленный отбор?

Пройдите циклом по коллекции Список.Отбор.Элементы, найдите нужный элемент по левому значению и либо установите Использование = Ложь, либо удалите его методом Удалить(). Учитывайте, что индексы элементов сдвигаются при удалении, поэтому удаляйте с конца коллекции или собирайте элементы в отдельный массив.

Можно ли сделать отбор с условием «ИЛИ»?

В таблице значений — только перебором в цикле с собственной проверкой. В динамическом списке и СКД — через группу элементов отбора с типом «ГруппаИли»: добавьте группу методом Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных")), задайте ТипГруппы и поместите условия внутрь неё.

Как отобрать документы за текущий месяц программно?

В запросе используйте условие «Дата МЕЖДУ &Начало И &Конец» с параметрами НачалоМесяца(ТекущаяДатаСеанса()) и КонецМесяца(ТекущаяДатаСеанса()). В динамическом списке добавьте элемент отбора по полю «Дата» с видом сравнения «БольшеИлиРавно» и «МеньшеИлиРавно» — два элемента объединятся по «И» и дадут диапазон.

Чем отбор отличается от параметров динамического списка?

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

Итог

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

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