Работа с формами списков в 1С:Предприятие — одна из самых частых задач разработчика. Отборы позволяют фильтровать данные прямо в интерфейсе, экономя время пользователей и снижая нагрузку на базу. Но как правильно их настроить, чтобы они работали быстро, не тормозили систему и покрывали все бизнес-задачи?
В этой статье разберём три основных способа добавления отборов: через конструктор формы (для управляемых форм), программно в модуле и с использованием расширений. Особое внимание уделим типичным ошибкам, которые приводят к "подвисанию" форм или некорректной фильтрации. Все примеры актуальны для платформы 1С:Предприятие 8.3 (включая последние релизы 2026 года) и проверены на конфигурациях УТ 11, БП 3.0 и ЗУП 3.1.
Если вы только начинаете работать с отборами, начните с первого раздела — там разобраны базовые понятия. Опытным разработчикам будет полезен раздел про динамические отборы с параметрами, которые позволяют создавать гибкие фильтры без перезагрузки формы.
1. Что такое отбор на форме списка и зачем он нужен
Отбор на форме списка — это механизм фильтрации данных, который позволяет пользователю видеть только те записи, которые соответствуют заданным критериям. Например, в списке номенклатуры можно отобразить только товары определенной группы или с остатками выше нуля.
Основные преимущества использования отборов:
- 📊 Ускорение работы — пользователь видит только релевантные данные, не тратит время на поиск в полном списке.
- 🔒 Безопасность — можно ограничить доступ к конфиденциальным записям (например, скрыть зарплаты других сотрудников).
- 🛠️ Автоматизация — отборы можно привязать к ролям, правам или бизнес-процессам.
- 📈 Аналитика — упрощается работа с большими объемами данных (например, отбор по дате, статусу или сумме).
В 1С:Предприятие 8.3 отборы реализованы через объект ОтборКомпоновкиДанных (для управляемых форм) или свойство Отбор (для обычных форм). Главное отличие от фильтров в Excel или SQL-запросах — отборы в 1С работают на уровне платформы и могут учитывать права доступа, иерархию справочников и даже данные из других баз (при распределённой инфобазе).
⚠️ Внимание: Если в отборе используются поля, которые не индексированы в базе данных (например, полнотекстовый поиск по описанию), это может значительно замедлить работу формы. Перед настройкой сложных отборов проверьте планы запросов в Консоли запросов.
2. Способ 1: Добавление отбора через конструктор формы (управляемые формы)
Самый простой способ настроить отбор — использовать встроенный конструктор формы. Этот метод подходит для управляемых форм и не требует написания кода. Рассмотрим пошаговую инструкцию на примере формы списка справочника "Номенклатура".
Алгоритм действий:
- Откройте конфигуратор и найдите форму списка справочника (например,
Справочник.Номенклатура.ФормаСписка). - Перейдите на вкладку
Реквизитыи добавьте новый реквизит типаСтруктурас именемОтборПоУмолчанию. - Откройте
Конструктор формы(кнопка на панели инструментов) и выберите пунктОтбор. - В открывшемся окне добавьте нужные поля отбора (например,
ГруппаилиВидНоменклатуры) и настройте условия. - Сохраните форму и запустите 1С в пользовательском режиме, чтобы проверить результат.
Пример настройки отбора по группе номенклатуры:
// Автоматически устанавливается в модуле формы при открытии
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Элементы.Отбор.Значение = Новый Структура("Группа", Справочники.ГруппыНоменклатуры.НайтиПоНаименованию("Одежда"));
КонецПроцедуры
Если отбор нужно сделать интерактивным (чтобы пользователь мог менять его прямо в форме), добавьте на форму поле ввода и свяжите его со свойством Отбор:
Элементы.ПолеОтбора.Значение = Элементы.Отбор.Значение;
Добавлен реквизит для хранения отбора|Отбор настроен в конструкторе формы|Поля отбора соответствуют структуре данных|Проведена проверка в пользовательском режиме|Отбор работает при изменении параметров-->
3. Способ 2: Программная настройка отбора в модуле формы
Когда стандартных возможностей конструктора недостаточно (например, нужно динамически менять отбор в зависимости от прав пользователя или текущей даты), приходит на помощь программная настройка. Этот метод универсален и работает как для управляемых, так и для обычных форм.
Основные сценарии, где программный отбор незаменим:
- 🔄 Динамические отборы — изменяются в реальном времени (например, фильтр по текущему складу пользователя).
- 🔐 Отборы по правам — пользователь видит только свои документы или данные своего подразделения.
- 📅 Отборы по дате — автоматически учитывают текущую дату или период (например,"за последний месяц").
- 🔗 Связанные отборы — фильтрация данных в одной форме на основе выбора в другой (например, при выборе контрагента отображаются только его договоры).
Пример кода для динамического отбора по текущему пользователю (для формы списка документов "Заказы покупателей"):
&НаКлиенте
Процедура УстановитьОтборПоПользователю
ТекущийПользователь = ПользователиИнформационнойБазы.ТекущийПользователь;
Отбор = Новый Структура;
Отбор.Вставить("Ответственный", ТекущийПользователь);
Элементы.Список.Отбор = Отбор;
Элементы.Список.ПрименитьОтбор;
КонецПроцедуры
Для обычных форм (тонкий клиент, файловый вариант) код будет немного другим:
Процедура ПриОткрытии
Отбор = Новый Структура;
Отбор.Вставить("Дата", НачалоДня(ТекущаяДата));
ЭлементыФормы.Список.Отбор = Отбор;
КонецПроцедуры
⚠️ Внимание: При программной установке отбора всегда вызывайте метод ПрименитьОтбор (для управляемых форм) или обновляйте список вручную (для обычных форм), иначе изменения не отобразятся.
Через конструктор формы|Программно в модуле|Через расширения|Не использую отборы-->
4. Способ 3: Отборы через расширения конфигурации
Если вы работаете с типовыми конфигурациями (УТ 11, БП 3.0, ЗУП 3.1) и не хотите изменять оригинальные формы, лучший вариант — использовать расширения. Это безопасный способ добавить отборы без риска потерять их при обновлении конфигурации.
Преимущества метода:
- 🔄 Совместимость с обновлениями — расширения не затираются при установке новых релизов.
- 🛡️ Безопасность — оригинальная конфигурация остаётся нетронутой.
- 🔧 Гибкость — можно добавлять отборы только для определённых ролей или подразделений.
Пошаговая инструкция:
- В конфигураторе откройте
Конфигурация → Расширения → Добавить. - Создайте новое расширение и укажите основную конфигурацию, к которой оно будет применяться.
- В дереве расширения найдите форму списка, к которой нужно добавить отбор (например,
Справочник.Контрагенты.ФормаСписка). - Добавьте новый реквизит для хранения отбора и настройте его в модуле расширения.
- Сохраните расширение и подключите его в основной базе через
Администрирование → Печатные формы, отчёты и обработки → Расширения конфигурации.
Пример кода для расширения (добавление отбора по виду контрагента):
&НаКлиенте
Процедура ДобавитьОтборПоВидуКонтрагента(Элемент)
Отбор = Новый Структура;
Отбор.Вставить("Вид", Перечисления.ВидыКонтрагентов.Покупатель);
Элементы.Список.Отбор = Отбор;
Элементы.Список.ПрименитьОтбор;
КонецПроцедуры
Чтобы отбор применялся автоматически при открытии формы, добавьте вызов процедуры в обработчик события ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ)
ДобавитьОтборПоВидуКонтрагента(Элементы.Список);
КонецПроцедуры
Если отбор в расширении не применяется, проверьте приоритет выполнения: иногда конфликтуют обработчики из основной конфигурации и расширения. Используйте отладчик (F5), чтобы понять, какой код выполняется в итоге.
5. Типичные ошибки и как их избежать
Даже опытные разработчики иногда сталкиваются с проблемами при настройке отборов. Вот самые распространённые ошибки и способы их решения:
| Ошибка | Причина | Решение |
|---|---|---|
| Отбор не применяется | Не вызван метод ПрименитьОтбор или не обновлён список |
Добавьте вызов метода после установки отбора или используйте Обновить |
| Форма долго грузится | Отбор по неиндексированным полям или сложные условия | Проверьте план запроса, добавьте индексы или упростите условия |
| Отбор сбрасывается при изменении | Конфликт обработчиков или неверное сохранение структуры отбора | Используйте реквизит формы для хранения отбора и обновляйте его программно |
| Не работают динамические отборы | Неверно указаны параметры или не обновляется связь с данными | Проверьте актуальность параметров и вызовите УстановитьДанныеФормы |
Одна из самых коварных ошибок — отбор по виртуальным таблицам (например, по остаткам или движениям). Если в отборе используется поле из виртуальной таблицы, но не указан период, платформа может вернуть некорректные данные или вообще не применить фильтр. Всегда проверяйте такие отборы с указанием даты:
Отбор.Вставить("Период", НачалоДня(ТекущаяДата));
Ещё одна частая проблема — конфликт отборов при использовании расширений. Если отбор задаётся и в основной конфигурации, и в расширении, можетть ситуация, когда применяется только один из них. Чтобы этого избежать, используйте ОбъединитьОтборы:
ОсновнойОтбор = Элементы.Список.Отбор;
ДополнительныйОтбор = Новый Структура("Поле", Значение);
Элементы.Список.Отбор = ОбъединитьОтборы(ОсновнойОтбор, ДополнительныйОтбор);
Как проверить, какой отбор применяется в итоге?
Включите отладку (F5) и поставьте точку останова на строке с применением отбора. В окне Выражения введите Элементы.Список.Отбор — вы увидите конечную структуру отбора, которая передаётся на сервер. Если отбор пустой или неполный, проверьте логику формирования структуры.
6. Оптимизация отборов для больших баз данных
Если ваша база содержит миллионы записей, неоптимизированные отборы могут приводить к "зависанию" форм или высокой нагрузке на сервер. Вот несколько приёмов, которые помогут ускорить работу:
- 📌 Индексируйте поля, по которым часто делаются отборы. Например, для справочника "Номенклатура" добавьте индекс по полю
Артикул, если по нему часто фильтруют данные. - 🔍 Используйте предопределённые данные вместо запросов. Например, вместо отбора по текущему пользователю через запрос используйте
ПользователиИнформационнойБазы.ТекущийПользователь. - 📊 Ограничивайте период для виртуальных таблиц. Всегда указывайте дату начала и конца, даже если отбор по дате не нужен пользователю.
- 🔄 Кэшируйте результаты сложных отборов. Например, если отбор по остаткам выполняется часто, сохраняйте его результат в временной таблице.
Пример оптимизированного отбора для формы списка документов "РеализацияТоваровУслуг" с учётом даты и контрагента:
&НаСервере
Функция ПолучитьОтборПоКонтрагентуИДате(Контрагент, ДатаНачала, ДатаОкончания)
Отбор = Новый Структура;
Отбор.Вставить("Контрагент", Контрагент);
Отбор.Вставить("Дата", НачалоДня(ДатаНачала), КонецДня(ДатаОкончания));
Возврат Отбор;
КонецФункции
Для ещё большей производительности можно использовать серверные процедуры, которые выполняют отбор непосредственно на сервере 1С, не передавая лишние данные на клиент. Например:
&НаСервере
Процедура ПрименитьОтборНаСервере(Отбор)
Запрос = Новый Запрос;
Запрос.Текст ="ВЫБРАТЬ РАЗРЕШЕННЫЕ * ИЗ Документ.РеализацияТоваровУслуг ГДЕ" + ПолучатьУсловиеПоОтбору(Отбор);
Результат = Запрос.Выполнить;
Возврат Результат.Выгрузить;
КонецПроцедуры
⚠️ Внимание: При работе с большими базами избегайте отборов по полям типаСтрока неограниченной длиныилиТекст— они не индексируются и могут тормозить систему. Если такой отбор необходим, рассмотрите возможность добавления отдельного индексированного поля (например,КраткоеНаименованиевместоПолноеНаименование).
Для баз с более чем 100 000 записей всегда тестируйте отборы на производительность в Консоли запросов, прежде чем применять их в рабочей форме.
7. Продвинутые техники: динамические отборы с параметрами
Если вам нужно создать гибкий отбор, который пользователь может менять без перезагрузки формы, используйте динамические отборы с параметрами. Этот подход позволяет, например, фильтровать данные по нескольким критериям одновременно или сохранять настройки отбора между сеансами.
Пример реализации:
- Добавьте на форму элементы управления для ввода параметров отбора (поля ввода, выпадающие списки).
- Создайте процедуру, которая будет формировать структуру отбора на основе введённых значений.
- Привяжите процедуру к событию
ПриИзменениидля каждого поля параметра. - Обновите список после применения нового отбора.
Код для формы списка справочника "Сотрудники" с отбором по подразделению и должности:
&НаКлиенте
Процедура ПриИзмененииПараметровОтбора(Элемент)
Отбор = Новый Структура;
Если Элементы.Подразделение.Значение <> Неопределено Тогда
Отбор.Вставить("Подразделение", Элементы.Подразделение.Значение);
КонецЕсли;
Если Элементы.Должность.Значение <> Неопределено Тогда
Отбор.Вставить("Должность", Элементы.Должность.Значение);
КонецЕсли;
Элементы.Список.Отбор = Отбор;
Элементы.Список.ПрименитьОтбор;
КонецПроцедуры
Для сохранения настроек отбора между сеансами используйте ХранилищеНастроек:
&НаКлиенте
Процедура СохранитьНастройкиОтбора
Настройки = Новый Структура;
Настройки.Вставить("Подразделение", Элементы.Подразделение.Значение);
Настройки.Вставить("Должность", Элементы.Должность.Значение);
ХранилищеНастроек.Сохранить(ИмяФормы +"_Отбор", Настройки);
КонецПроцедуры
&НаКлиенте
Процедура ВосстановитьНастройкиОтбора
Настройки = ХранилищеНастроек.Восстановить(ИмяФормы +"_Отбор");
Если Настройки <> Неопределено Тогда
Элементы.Подразделение.Значение = Настройки.Подразделение;
Элементы.Должность.Значение = Настройки.Должность;
ПриИзмененииПараметровОтбора(Неопределено);
КонецЕсли;
КонецПроцедуры
Для ещё большей гибкости можно использовать расширяемые отборы, где пользователь может добавлять свои условия через специальный диалог. Например, так реализовано в типовой обработке "Универсальный отчёт".
Если динамический отбор тормозит форму, попробуйте добавить задержку перед применением (например, 500 мс) с помощью Подождать. Это снизит нагрузку при быстром изменении параметров.
FAQ: Частые вопросы по отборам в 1С
Как сделать отбор по нескольким значениям одного поля (например, по нескольким группам номенклатуры)?
Используйте массив значений в структуре отбора:
Отбор = Новый Структура;
Отбор.Вставить("Группа", Новый Массив(Группа1, Группа2, Группа3));
В некоторых случаях может потребоваться указать тип сравнения:
Отбор.Вставить("Группа", Новый Массив(Группа1, Группа2), ТипСравнения.ВСписке);
Почему отбор не работает для полей с составным типом (например,"Ссылка.Контрагент")?
Для составных типов нужно явно указывать путь к полю в отборе. Например, вместо Отбор.Вставить("Контрагент", Значение) используйте:
Отбор.Вставить("Контрагент.Ссылка", Значение);
Если поле является реквизитом табличной части, укажите полный путь:
Отбор.Вставить("ТабличнаяЧасть.Контрагент", Значение);
Можно ли сделать отбор по полю, которого нет в основной форме?
Да, но для этого нужно:
- Добавить поле в запрос, который формирует данные формы (через расширение или конфигурации).
- Указать это поле в свойстве
Отборс полным путём (например,"Движения.Товар").
Пример для формы списка документов с отбором по номенклатуре из табличной части:
Отбор.Вставить("Товары.Номенклатура", НужнаяНоменклатура);
Как отладить отбор, если он не применяется?
Используйте следующие шаги:
- Включите отладку (
F5) и поставьте точку останова на строке с применением отбора. - Проверьте значение переменной
Отборперед применением — соответствует ли структура ожидаемой? - Убедитесь, что вызван метод
ПрименитьОтбор(для управляемых форм) илиОбновить(для обычных). - Проверьте права пользователя — возможно, отбор применяется, но данные скрыты из-за ограничений RLS.
Если отбор по-прежнему не работает, попробуйте применить его вручную через Консоль запросов, чтобы исключить ошибки в логике.
Как сделать отбор по текущему пользователю с учётом его ролей?
Используйте комбинацию ПользователиИнформационнойБазы.ТекущийПользователь и проверку ролей:
ТекущийПользователь = ПользователиИнформационнойБазы.ТекущийПользователь;
Если ТекущийПользователь.ПроверитьПрава("Роль.Администратор") Тогда
Отбор.Вставить("Ответственный", ТекущийПользователь);
Иначе
Отбор.Вставить("Подразделение", ТекущийПользователь.Подразделение);
КонецЕсли;
Для проверки прав по нескольким ролям используйте:
Если ТекущийПользователь.ПроверитьПрава("Роль.Руководитель, Роль.Директор") Тогда
// Логика для руководителей
КонецЕсли;