Решение задач 1С:Предприятие 8 на примерах

Отбор динамического списка 1С программно: Список.Отбор, БСП и параметры

Управляемые формыОпубликовано

Отбор динамического списка ставят из кода постоянно: показать только свои документы, отфильтровать список по складу, выбранному на форме, открыть форму списка уже отфильтрованной. В статье — где в 8.3 хранится отбор и какой набор настроек выбирать, рабочий код установки и изменения отбора, группы «ИЛИ», процедура БСП УстановитьЭлементОтбораДинамическогоСписка и параметры динамического списка.

Задача: показать в списке только нужные записи

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

Где хранится отбор динамического списка

У реквизита типа ДинамическийСписок есть свойство КомпоновщикНастроек с тремя наборами настроек. Окончательный отбор складывается из всех трёх.

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

Для программного отбора в большинстве случаев нужен первый вариант — Список.Отбор. Его значения не перезаписываются сохранёнными пользовательскими настройками и не показываются в диалоге настройки списка, поэтому пользователь не снимет ограничение случайно.

Установить отбор динамического списка программно

Отбор, который должен действовать всегда, ставьте в обработчике ПриСозданииНаСервере. Элемент отбора добавляется в коллекцию Список.Отбор.Элементы, поле задаётся объектом ПолеКомпоновкиДанных.

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

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

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

Здесь Пользователи.ТекущийПользователь() — функция БСП; в конфигурации без БСП подставьте своё значение. Имя поля — это имя поля динамического списка, а не реквизита формы: если список построен на произвольном запросе, используйте псевдоним из текста запроса. Можно обращаться и к реквизитам через точку, например "Контрагент.ИНН".

Основные виды сравнения

Значение ВидСравненияКомпоновкиДанныхЧто делаетПравоеЗначение
Равно, НеРавноТочное совпадениеОдно значение
Больше, БольшеИлиРавно, Меньше, МеньшеИлиРавноСравнение чисел и датОдно значение
ВСписке, НеВСпискеВходит в набор значенийСписокЗначений
ВИерархии, ВСпискеПоИерархииЭлемент и все подчинённые (для иерархических справочников)Группа или список групп
Содержит, НеСодержитПодстрока в строковом полеСтрока
Заполнено, НеЗаполненоПроверка на пустое значениеНе нужно

Изменить отбор без дублей

Если код установки отбора вызывается повторно (например, при каждом изменении поля на форме), простое Добавить() будет плодить одинаковые элементы. Правильнее найти элемент по полю и изменить его, а добавлять только при отсутствии.

&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьОтборСписка(Список, ИмяПоля, Значение, Использование = Истина)

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

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

    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
    ЭлементОтбора.ПравоеЗначение = Значение;
    ЭлементОтбора.Использование = Использование;

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

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

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

Типичный сценарий: над списком стоит поле «Склад», пользователь выбирает значение — список фильтруется. Отбор динамического списка доступен на клиенте, поэтому серверный вызов не нужен: достаточно обработчика ПриИзменении.

&НаКлиенте
Процедура ОтборСкладПриИзменении(Элемент)

    УстановитьОтборСписка(Список, "Склад", ОтборСклад, ЗначениеЗаполнено(ОтборСклад));

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

Здесь ОтборСклад — реквизит формы с полем ввода, а УстановитьОтборСписка — процедура из предыдущего раздела. Если значение очищено, отбор выключается и список снова показывает все записи. Платформа сама перечитывает данные списка после изменения отбора.

Отбор по нескольким значениям и группа ИЛИ

Элементы верхнего уровня объединяются по «И». Для условия «ИЛИ» создайте группу элементов отбора и уже в неё добавляйте условия.

// Статус "Новый" или "В работе"
Статусы = Новый СписокЗначений;
Статусы.Добавить(Перечисления.СтатусыЗаказов.Новый);
Статусы.Добавить(Перечисления.СтатусыЗаказов.ВРаботе);

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

// Ответственный = текущий пользователь ИЛИ ответственный не заполнен
ГруппаИли = Список.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаИли.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
ГруппаИли.Использование = Истина;

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

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

Перечисление и его значения в примере условные — подставьте свои.

Отбор по периоду

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

&НаКлиенте
Процедура ПериодПриИзменении(Элемент)

    УстановитьОтборПоПериоду();

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

&НаКлиенте
Процедура УстановитьОтборПоПериоду()

    Список.Отбор.Элементы.Очистить();

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

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

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

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

ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка

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

ПараметрТипНазначение
ДинамическийСписокДинамическийСписокСписок, в котором ставится отбор
ИмяПоляСтрокаПоле отбора
ПравоеЗначениеПроизвольныйЗначение отбора; если передать Неопределено, значение не меняется
ВидСравненияВидСравненияКомпоновкиДанныхУсловие отбора
ПредставлениеСтрокаЕсли указано, выводится только флажок с этим представлением, без значения
ИспользованиеБулевоФлажок использования отбора
РежимОтображенияРежимОтображенияЭлементаНастройкиКомпоновкиДанныхСпособ отображения отбора пользователю
ИдентификаторПользовательскойНастройкиСтрокаСвязь с пользовательскими настройками
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    Если Параметры.Свойство("Организация") Тогда
        ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
            Список, "Организация", Параметры.Организация,
            ВидСравненияКомпоновкиДанных.Равно, , Истина,
            РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный);
    КонецЕсли;

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

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

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

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

ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Наименование КАК Наименование,
    ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
ИЗ
    Справочник.Номенклатура КАК Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&НаДату, Склад = &Склад) КАК Остатки
        ПО Номенклатура.Ссылка = Остатки.Номенклатура

Значения параметров задаются методом УстановитьЗначениеПараметра коллекции Список.Параметры. Пока параметр не установлен, список может не показывать данные или выдавать ошибку, поэтому задайте все параметры уже в ПриСозданииНаСервере.

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

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

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

&НаКлиенте
Процедура СкладПриИзменении(Элемент)

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

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

В конфигурациях на БСП то же делает ОбщегоНазначенияКлиентСервер.УстановитьПараметрДинамическогоСписка(Список, ИмяПараметра, Значение, Использование).

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

Отбор при открытии формы списка

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

&НаКлиенте
Процедура ОткрытьЗаказыКонтрагента(Команда)

    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", Новый Структура("Контрагент", Объект.Контрагент));
    ОткрытьФорму("Документ.ЗаказКлиента.ФормаСписка", ПараметрыФормы, ЭтотОбъект);

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

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

Типичные ошибки

  • Дубли элементов отбора при повторном вызове кода. Ищите элемент по полю или используйте функцию БСП.
  • Неверное имя поля. Нужно имя поля динамического списка (псевдоним в произвольном запросе), а не имя реквизита формы.
  • Отбор поставлен в пользовательские настройки вместо Список.Отбор — пользователь снимает его в настройках, и данные «утекают».
  • Один и тот же реквизит в фиксированном и пользовательском отборе. Результат получается неочевидным; держите программные и пользовательские условия на разных полях.
  • Не установлен параметр произвольного запроса — список пустой или выдаёт ошибку при открытии.
  • Отбор вместо параметра для виртуальной таблицы остатков: условие применяется после расчёта остатков по всему регистру, и список работает медленно.

Актуальность для новых версий

Объекты компоновки данных, с которыми работает отбор динамического списка (ЭлементОтбораКомпоновкиДанных, ПолеКомпоновкиДанных, ВидСравненияКомпоновкиДанных), одинаковы во всех версиях 8.3 для управляемых форм. Процедуры УстановитьЭлементОтбораДинамическогоСписка и УстановитьПараметрДинамическогоСписка входят в общий модуль ОбщегоНазначенияКлиентСервер БСП; состав их параметров уточняйте по комментарию в своей версии библиотеки.

Частые вопросы

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

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

Чем Список.Отбор отличается от пользовательских настроек?

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

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

Да. Отбор динамического списка доступен на клиенте, поэтому фильтр по полю формы можно поставить прямо в обработчике ПриИзменении без серверного вызова. Список перечитает данные сам.

Как сделать отбор с условием ИЛИ?

Добавьте в Список.Отбор.Элементы группу с типом ГруппаЭлементовОтбораКомпоновкиДанных, установите ей ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли и добавляйте условия в элементы группы.

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

Когда значение нужно внутри запроса: в параметрах виртуальной таблицы, в соединении или выражении. Для этого включают произвольный запрос и задают значение через Список.Параметры.УстановитьЗначениеПараметра.

Как открыть форму списка сразу с отбором?

Передайте в параметрах ОткрытьФорму структуру Отбор, например Новый Структура("Отбор", Новый Структура("Контрагент", Контрагент)). Платформа установит отбор по указанному полю.

&НаКлиенте и &НаСервере в 1С: директивы компиляции в управляемых формах

Управляемые формы

Чем отличаются директивы &НаКлиенте, &НаСервере и &НаСервереБезКонтекста, что доступно на клиенте и на сервере, как передавать данные в управляемой форме и не делать лишних серверных вызовов.

Элементы формы 1С: программное добавление на управляемую форму

Управляемые формы

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

Как открыть форму в управляемом приложении 1С и обработать результат после закрытия

Управляемые формы

Шесть типовых сценариев открытия управляемой формы в 1С: новый объект, создание на основании, существующий документ, форма выбора и получение результата после закрытия через ОписаниеОповещения.

Условное оформление элементов формы программным способом

Управляемые формы

Шесть примеров программного условного оформления в управляемой форме 1С: цвет поля по значению, сравнение двух реквизитов, оформление строк динамического списка и условие по текущей дате.