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