При работе с платформой 1С:Предприятие 8.3 в режиме управляемого приложения, мы часто сталкиваемся с необходимостью динамической настройки интерфейса и поведения форм. Одной из распространенных задач является программная установка отбора для данных, отображаемых в динамическом списке. Казалось бы, задача проста, но многие разработчики поначалу пытаются использовать свойство Отбор напрямую у элемента формы, что приводит к неверным результатам или ошибкам. Давайте разберем, почему так происходит, и как правильно решить эту задачу, используя механизмы системы компоновки данных (СКД).
При переходе от обычных форм к управляемым и внедрении принципов СКД, подход к работе с данными значительно изменился. В обычных формах мы могли напрямую управлять свойством Отбор у табличных частей или списков. Однако в управляемых формах ДинамическийСписок получает свои данные, используя механизм СКД. Это означает, что все настройки, включая отборы, сортировки и группировки, должны быть переданы именно через компоновщик настроек СКД, который лежит в основе динамического списка.
Свойство Отбор, которое иногда можно обнаружить у элементов формы, предназначенных для обычных форм или для более специфических случаев, не имеет прямого влияния на данные ДинамическогоСписка. Поэтому, пытаясь применить отбор через Список.Отбор.Элементы.Добавить(), как это часто делалось в старых подходах, мы не увидим желаемого результата. Вместо этого, нам необходимо взаимодействовать со свойством КомпоновщикНастроек динамического списка.
Для корректной установки отбора в динамическом списке на управляемой форме, мы должны работать с объектом КомпоновщикНастроек. Этот объект позволяет нам управлять всеми аспектами схемы компоновки данных, лежащей в основе списка. Рассмотрим подробнее каждый шаг:
Получение объекта динамического списка.
Первым делом нам необходимо получить ссылку на сам элемент формы, который представляет собой динамический список. Обычно это делается через коллекцию Элементы формы, указывая имя элемента, заданное в конфигураторе.
ДинамическийСписок = Элементы.ИмяВашегоДинамическогоСписка;
Здесь ИмяВашегоДинамическогоСписка – это имя элемента формы, например, СписокДокументов, СписокНоменклатуры и т.д.
Доступ к настройкам отбора через КомпоновщикНастроек.
После получения объекта динамического списка, мы обращаемся к его свойству КомпоновщикНастроек, затем к Настройки, и уже оттуда к свойству Отбор. Это свойство представляет собой коллекцию элементов отбора.
// Получаем коллекцию элементов отбора
КоллекцияОтбора = ДинамическийСписок.КомпоновщикНастроек.Настройки.Отбор.Элементы;
Очистка существующих отборов (по необходимости).
Очень часто перед установкой нового отбора требуется очистить все ранее установленные отборы, чтобы избежать их наложения и получить только нужный результат. Это хорошая практика, чтобы гарантировать предсказуемое поведение.
КоллекцияОтбора.Очистить();
Создание нового элемента отбора.
Для каждого условия отбора нам потребуется создать отдельный объект типа ЭлементОтбораКомпоновкиДанных. Мы добавляем его в коллекцию отбора.
НовыйЭлементОтбора = КоллекцияОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Установка левого значения (поля, по которому отбираем).
Свойство ЛевоеЗначение объекта ЭлементОтбораКомпоновкиДанных указывает, по какому полю данных будет производиться отбор. Это поле должно быть доступно в схеме компоновки данных, на основе которой построен динамический список. Мы используем объект ПолеКомпоновкиДанных для его указания.
НовыйЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СтатусДокумента");
Обратите внимание, что имя поля указывается в виде строки и должно соответствовать имени поля в запросе или источнике данных СКД.
Установка вида сравнения.
Свойство ВидСравнения определяет, как именно будет производиться сравнение левого и правого значений (например, "равно", "больше", "содержит"). Мы используем значения из перечисления ВидСравненияКомпоновкиДанных.
НовыйЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно; // Например, "Равно"
Некоторые распространенные виды сравнения:
ВидСравненияКомпоновкиДанных.Равно: Точное совпадение.ВидСравненияКомпоновкиДанных.НеРавно: Неравенство.ВидСравненияКомпоновкиДанных.Больше: Больше чем.ВидСравненияКомпоновкиДанных.Меньше: Меньше чем.ВидСравненияКомпоновкиДанных.БольшеИлиРавно: Больше или равно.ВидСравненияКомпоновкиДанных.МеньшеИлиРавно: Меньше или равно.ВидСравненияКомпоновкиДанных.Содержит: Для строковых значений, содержит подстроку.ВидСравненияКомпоновкиДанных.НеСодержит: Для строковых значений, не содержит подстроку.ВидСравненияКомпоновкиДанных.ВСписке: Значение входит в список.ВидСравненияКомпоновкиДанных.НеВСписке: Значение не входит в список.ВидСравненияКомпоновкиДанных.Заполнено: Поле не пустое.ВидСравненияКомпоновкиДанных.НеЗаполнено: Поле пустое.Установка правого значения (значения, с которым сравниваем).
Свойство ПравоеЗначение определяет конкретное значение, по которому будет производиться отбор. Тип этого значения должен соответствовать типу поля, указанного в ЛевоеЗначение.
НовыйЭлементОтбора.ПравоеЗначение = Перечисления.СтатусыДокументов.Проведен; // Например, элемент перечисления
Если мы используем ВидСравненияКомпоновкиДанных.ВСписке или НеВСписке, тогда ПравоеЗначение должно быть коллекцией, например, Массив.
МассивЗначений = Новый Массив();
МассивЗначений.Добавить(Перечисления.СтатусыДокументов.Проведен);
МассивЗначений.Добавить(Перечисления.СтатусыДокументов.Согласован);
НовыйЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
НовыйЭлементОтбора.ПравоеЗначение = МассивЗначений;
Включение элемента отбора.
Чтобы элемент отбора был активен, необходимо установить его свойство Использование в Истина.
НовыйЭлементОтбора.Использование = Истина;
Настройка режима отображения (опционально).
Свойство РежимОтображения определяет, как элемент отбора будет виден или не виден пользователю в настройках динамического списка. Это может быть полезно для создания "скрытых" отборов, которые пользователь не может изменить.
// Чтобы пользователь не видел и не мог изменить этот отбор
НовыйЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.НеОтображать;
// Чтобы пользователь видел и мог изменять отбор
// НовыйЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.ОтображатьВсегда;
Обновление динамического списка.
После того как все настройки отбора сделаны, необходимо вызвать метод ОбновитьСписок() у динамического списка, чтобы примененные изменения вступили в силу и данные в списке обновились с учетом нового отбора.
ДинамическийСписок.ОбновитьСписок();
Давайте посмотрим на комплексный пример, который включает в себя все описанные шаги. Предположим, у нас есть динамический список с именем СписокДокументов, и мы хотим отобразить только документы со статусом "Проведен".
&НаСервере
Процедура УстановитьОтборПоСтатусуДокумента(СтатусДляОтбора)
// 1. Получаем объект динамического списка
ДинамическийСписок = Элементы.СписокДокументов;
// Проверяем, что динамический список существует
Если ДинамическийСписок = Неопределено Тогда
Возврат;
КонецЕсли;
// 2. Доступ к настройкам отбора через КомпоновщикНастроек
// и 3. Очистка текущих отборов
ДинамическийСписок.КомпоновщикНастроек.Настройки.Отбор.Элементы.Очистить();
// 4. Создаем новый элемент отбора
НовыйЭлементОтбора = ДинамическийСписок.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// 5. Указываем поле, по которому будем отбирать.
// Предполагаем, что в СКД списка есть поле "СтатусДокумента".
НовыйЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СтатусДокумента");
// 6. Устанавливаем вид сравнения (в данном случае - "Равно")
НовыйЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
// 7. Устанавливаем значение, по которому будем отбирать
НовыйЭлементОтбора.ПравоеЗначение = СтатусДляОтбора; // Передаем статус как параметр процедуры
// 8. Разрешаем использование элемента отбора
НовыйЭлементОтбора.Использование = Истина;
// 9. Устанавливаем режим отображения отбора (например, чтобы пользователь не мог его изменить)
НовыйЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.НеОтображать;
// 10. Обновляем список, чтобы применились новые настройки
ДинамическийСписок.ОбновитьСписок();
КонецПроцедуры
&НаКлиенте
Процедура КомандаУстановитьОтбор(Команда)
// Вызываем серверную процедуру для установки отбора
УстановитьОтборПоСтатусуДокумента(Перечисления.СтатусыДокументов.Проведен);
КонецПроцедуры
В этом примере мы создали процедуру УстановитьОтборПоСтатусуДокумента на сервере, которая принимает нужный статус в качестве параметра. Затем мы вызываем ее из клиентской процедуры, например, при нажатии на кнопку формы. Это обеспечивает правильное взаимодействие с данными на сервере, где обычно и выполняется логика работы с СКД.
Иногда требуется установить более сложные условия отбора, например, "Статус = Проведен И Дата > НачалоМесяца" или "Статус = Отменен ИЛИ (Статус = Новый И Менеджер = ТекущийПользователь)". Для таких случаев в СКД предусмотрены группы отборов. Вместо добавления ЭлементОтбораКомпоновкиДанных напрямую в коллекцию Отбор.Элементы, мы можем добавить ГруппаЭлементовОтбораКомпоновкиДанных.
Рассмотрим, как это работает:
Создание группы отбора.
ГруппаОтбора = КоллекцияОтбора.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
Установка вида группы.
Для группы нужно определить ее вид, то есть, как будут связаны элементы внутри этой группы: "И" (Все), "ИЛИ" (Любой) или "Не И" / "Не ИЛИ".
ГруппаОтбора.ВидГруппы = ВидГруппыЭлементовОтбораКомпоновкиДанных.И; // Элементы внутри группы будут связаны через "И"
// или
// ГруппаОтбора.ВидГруппы = ВидГруппыЭлементовОтбораКомпоновкиДанных.ИЛИ; // Элементы внутри группы будут связаны через "ИЛИ"
Добавление элементов в группу.
Теперь мы добавляем ЭлементОтбораКомпоновкиДанных (или даже вложенные группы) в коллекцию Элементы самой группы.
Элемент1 = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Элемент1.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СтатусДокумента");
Элемент1.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Элемент1.ПравоеЗначение = Перечисления.СтатусыДокументов.Проведен;
Элемент1.Использование = Истина;
Элемент2 = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Элемент2.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ДатаДокумента");
Элемент2.ВидСравнения = ВидСравненияКомпоновкиДанных.БольшеИлиРавно;
Элемент2.ПравоеЗначение = НачалоМесяца(ТекущаяДата());
Элемент2.Использование = Истина;
Таким образом, мы можем строить сколь угодно сложные иерархические структуры отборов, полностью управляя логикой фильтрации данных.
Доступность поля в СКД: Убедитесь, что поле, по которому вы пытаетесь установить отбор (ЛевоеЗначение), действительно присутствует в схеме компоновки данных динамического списка. Если поле отсутствует, отбор не сработает, или вы получите ошибку.
Типы данных: Важно, чтобы тип ПравогоЗначения соответствовал типу данных поля, указанного в ЛевоеЗначение. Например, если поле имеет тип "Дата", то и ПравоеЗначение должно быть датой, а не строкой.
Контекст выполнения: Код, работающий с ДинамическийСписок.КомпоновщикНастроек, должен выполняться на сервере (в серверной процедуре или функции). На клиенте прямой доступ к этим свойствам невозможен.
Вызов ОбновитьСписок(): Никогда не забывайте вызывать метод ОбновитьСписок() после изменения настроек отбора. Без этого изменения не будут применены, и список не обновит свои данные.
Производительность: Слишком большое количество сложных отборов или частые программные изменения могут влиять на производительность. Старайтесь оптимизировать запросы и использовать индексы в базе данных, если это необходимо.
Хотя КомпоновщикНастроек является основным и наиболее гибким способом управления отборами, существуют и другие методы, но они обычно сложнее или менее универсальны для простых задач:
Программное изменение текста запроса динамического списка.
Можно получить текст запроса, который формирует динамический список, изменить его, добавив условия в секцию ГДЕ, и затем установить измененный текст запроса обратно. Этот подход дает полный контроль над запросом, но значительно сложнее в реализации и поддержке. Он оправдан, когда требуется очень специфическая логика формирования данных, которую СКД не может обеспечить стандартными средствами (например, использование временных таблиц со сложной логикой).
Например, мы можем получить ДинамическийСписок.ТекстЗапроса, модифицировать его и затем установить обратно. Однако при этом теряется вся гибкость СКД, и пользовательские настройки (сортировки, группировки) могут быть сброшены или работать некорректно.
Использование параметра ПроизвольныйЗапрос (если доступно).
В некоторых случаях, если динамический список создан на основе произвольного запроса (хотя это не типовой подход для большинства объектов), можно модифицировать сам текст запроса. Но это, по сути, вариация предыдущего пункта и не является решением для динамического списка, построенного на основе обычных объектов конфигурации с типовой СКД.
Для большинства задач по установке отбора КомпоновщикНастроек предлагает оптимальный баланс между гибкостью и простотой использования. Мы рекомендуем всегда начинать решение задачи с этого подхода.
Теперь мы с вами разобрались, как правильно программно устанавливать отборы в динамических списках на управляемых формах 1С 8.3. Ключевым моментом является понимание того, что взаимодействие происходит через объект КомпоновщикНастроек, а не через прямое свойство Отбор. Мы рассмотрели пошаговый процесс, включающий создание элементов отбора, настройку их свойств (левое/правое значение, вид сравнения, использование, режим отображения) и обязательное обновление списка. Также мы затронули вопросы работы с группами отборов для построения сложных условий и обсудили важные нюансы, которые помогут избежать распространенных ошибок.
Применяя эти знания, вы сможете эффективно управлять данными, отображаемыми в ваших управляемых формах, делая их более функциональными и адаптивными к потребностям пользователей.