Как программно установить отбор в динамическом списке на управляемой форме 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Почему прямой отбор не работает в управляемых формах и динамических списках?

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

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

Пошаговое решение: Программная установка отбора через КомпоновщикНастроек

Для корректной установки отбора в динамическом списке на управляемой форме, мы должны работать с объектом КомпоновщикНастроек. Этот объект позволяет нам управлять всеми аспектами схемы компоновки данных, лежащей в основе списка. Рассмотрим подробнее каждый шаг:

  1. Получение объекта динамического списка.

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

    ДинамическийСписок = Элементы.ИмяВашегоДинамическогоСписка;

    Здесь ИмяВашегоДинамическогоСписка – это имя элемента формы, например, СписокДокументов, СписокНоменклатуры и т.д.

  2. Доступ к настройкам отбора через КомпоновщикНастроек.

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

    
    // Получаем коллекцию элементов отбора
    КоллекцияОтбора = ДинамическийСписок.КомпоновщикНастроек.Настройки.Отбор.Элементы;
    
  3. Очистка существующих отборов (по необходимости).

    Очень часто перед установкой нового отбора требуется очистить все ранее установленные отборы, чтобы избежать их наложения и получить только нужный результат. Это хорошая практика, чтобы гарантировать предсказуемое поведение.

    КоллекцияОтбора.Очистить();
  4. Создание нового элемента отбора.

    Для каждого условия отбора нам потребуется создать отдельный объект типа ЭлементОтбораКомпоновкиДанных. Мы добавляем его в коллекцию отбора.

    
    НовыйЭлементОтбора = КоллекцияОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    
  5. Установка левого значения (поля, по которому отбираем).

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

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

    Обратите внимание, что имя поля указывается в виде строки и должно соответствовать имени поля в запросе или источнике данных СКД.

  6. Установка вида сравнения.

    Свойство ВидСравнения определяет, как именно будет производиться сравнение левого и правого значений (например, "равно", "больше", "содержит"). Мы используем значения из перечисления ВидСравненияКомпоновкиДанных.

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

    Некоторые распространенные виды сравнения:

    • ВидСравненияКомпоновкиДанных.Равно: Точное совпадение.
    • ВидСравненияКомпоновкиДанных.НеРавно: Неравенство.
    • ВидСравненияКомпоновкиДанных.Больше: Больше чем.
    • ВидСравненияКомпоновкиДанных.Меньше: Меньше чем.
    • ВидСравненияКомпоновкиДанных.БольшеИлиРавно: Больше или равно.
    • ВидСравненияКомпоновкиДанных.МеньшеИлиРавно: Меньше или равно.
    • ВидСравненияКомпоновкиДанных.Содержит: Для строковых значений, содержит подстроку.
    • ВидСравненияКомпоновкиДанных.НеСодержит: Для строковых значений, не содержит подстроку.
    • ВидСравненияКомпоновкиДанных.ВСписке: Значение входит в список.
    • ВидСравненияКомпоновкиДанных.НеВСписке: Значение не входит в список.
    • ВидСравненияКомпоновкиДанных.Заполнено: Поле не пустое.
    • ВидСравненияКомпоновкиДанных.НеЗаполнено: Поле пустое.
  7. Установка правого значения (значения, с которым сравниваем).

    Свойство ПравоеЗначение определяет конкретное значение, по которому будет производиться отбор. Тип этого значения должен соответствовать типу поля, указанного в ЛевоеЗначение.

    
    НовыйЭлементОтбора.ПравоеЗначение = Перечисления.СтатусыДокументов.Проведен; // Например, элемент перечисления
    

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

    
    МассивЗначений = Новый Массив();
    МассивЗначений.Добавить(Перечисления.СтатусыДокументов.Проведен);
    МассивЗначений.Добавить(Перечисления.СтатусыДокументов.Согласован);
    НовыйЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
    НовыйЭлементОтбора.ПравоеЗначение = МассивЗначений;
    
  8. Включение элемента отбора.

    Чтобы элемент отбора был активен, необходимо установить его свойство Использование в Истина.

    НовыйЭлементОтбора.Использование = Истина;
  9. Настройка режима отображения (опционально).

    Свойство РежимОтображения определяет, как элемент отбора будет виден или не виден пользователю в настройках динамического списка. Это может быть полезно для создания "скрытых" отборов, которые пользователь не может изменить.

    
    // Чтобы пользователь не видел и не мог изменить этот отбор
    НовыйЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.НеОтображать;
    // Чтобы пользователь видел и мог изменять отбор
    // НовыйЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.ОтображатьВсегда;
    
  10. Обновление динамического списка.

    После того как все настройки отбора сделаны, необходимо вызвать метод ОбновитьСписок() у динамического списка, чтобы примененные изменения вступили в силу и данные в списке обновились с учетом нового отбора.

    ДинамическийСписок.ОбновитьСписок();

Полный пример кода для установки отбора

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


&НаСервере
Процедура УстановитьОтборПоСтатусуДокумента(СтатусДляОтбора)

    // 1. Получаем объект динамического списка
    ДинамическийСписок = Элементы.СписокДокументов; 

    // Проверяем, что динамический список существует
    Если ДинамическийСписок = Неопределено Тогда
        Возврат;
    КонецЕсли;

    // 2. Доступ к настройкам отбора через КомпоновщикНастроек
    //    и 3. Очистка текущих отборов
    ДинамическийСписок.КомпоновщикНастроек.Настройки.Отбор.Элементы.Очистить();

    // 4. Создаем новый элемент отбора
    НовыйЭлементОтбора = ДинамическийСписок.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

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

    // 6. Устанавливаем вид сравнения (в данном случае - "Равно")
    НовыйЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;

    // 7. Устанавливаем значение, по которому будем отбирать
    НовыйЭлементОтбора.ПравоеЗначение = СтатусДляОтбора; // Передаем статус как параметр процедуры

    // 8. Разрешаем использование элемента отбора
    НовыйЭлементОтбора.Использование = Истина;

    // 9. Устанавливаем режим отображения отбора (например, чтобы пользователь не мог его изменить)
    НовыйЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.НеОтображать; 

    // 10. Обновляем список, чтобы применились новые настройки
    ДинамическийСписок.ОбновитьСписок();

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

&НаКлиенте
Процедура КомандаУстановитьОтбор(Команда)
    // Вызываем серверную процедуру для установки отбора
    УстановитьОтборПоСтатусуДокумента(Перечисления.СтатусыДокументов.Проведен);
КонецПроцедуры

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

Работа с группами отборов

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

Рассмотрим, как это работает:

  1. Создание группы отбора.

    
    ГруппаОтбора = КоллекцияОтбора.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
    
  2. Установка вида группы.

    Для группы нужно определить ее вид, то есть, как будут связаны элементы внутри этой группы: "И" (Все), "ИЛИ" (Любой) или "Не И" / "Не ИЛИ".

    
    ГруппаОтбора.ВидГруппы = ВидГруппыЭлементовОтбораКомпоновкиДанных.И; // Элементы внутри группы будут связаны через "И"
    // или
    // ГруппаОтбора.ВидГруппы = ВидГруппыЭлементовОтбораКомпоновкиДанных.ИЛИ; // Элементы внутри группы будут связаны через "ИЛИ"
    
  3. Добавление элементов в группу.

    Теперь мы добавляем ЭлементОтбораКомпоновкиДанных (или даже вложенные группы) в коллекцию Элементы самой группы.

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

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

Важные моменты и возможные трудности

Альтернативные подходы (и почему они менее предпочтительны для простых отборов)

Хотя КомпоновщикНастроек является основным и наиболее гибким способом управления отборами, существуют и другие методы, но они обычно сложнее или менее универсальны для простых задач:

  1. Программное изменение текста запроса динамического списка.

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

    Например, мы можем получить ДинамическийСписок.ТекстЗапроса, модифицировать его и затем установить обратно. Однако при этом теряется вся гибкость СКД, и пользовательские настройки (сортировки, группировки) могут быть сброшены или работать некорректно.

  2. Использование параметра ПроизвольныйЗапрос (если доступно).

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

Для большинства задач по установке отбора КомпоновщикНастроек предлагает оптимальный баланс между гибкостью и простотой использования. Мы рекомендуем всегда начинать решение задачи с этого подхода.

Заключение

Теперь мы с вами разобрались, как правильно программно устанавливать отборы в динамических списках на управляемых формах 1С 8.3. Ключевым моментом является понимание того, что взаимодействие происходит через объект КомпоновщикНастроек, а не через прямое свойство Отбор. Мы рассмотрели пошаговый процесс, включающий создание элементов отбора, настройку их свойств (левое/правое значение, вид сравнения, использование, режим отображения) и обязательное обновление списка. Также мы затронули вопросы работы с группами отборов для построения сложных условий и обсудили важные нюансы, которые помогут избежать распространенных ошибок.

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

← На главную