При разработке управляемых форм в 1С:Предприятие 8.3 мы постоянно сталкиваемся с объектом ДинамическийСписок. Это мощный инструмент для отображения данных из таблиц базы или результатов запросов. Одной из самых частых задач, встающих перед программистом, является необходимость программно установить отбор при открытии формы или по нажатию кнопки.
В этой статье мы подробно, шаг за шагом, разберем, как правильно управлять отборами динамического списка через встроенный язык. Мы проанализируем структуру объекта, выясним разницу между видами настроек и напишем универсальный код, который вы сможете использовать в своих проектах.
Прежде чем писать код, давайте разберемся, как устроен ДинамическийСписок. В отличие от обычных списков (как это было в 1С 8.1 или обычных формах), управляемый список строится на базе Системы Компоновки Данных (СКД). Это значит, что прямого доступа к "строкам" для отбора нет. Все управление идет через объект КомпоновщикНастроек.
Рассмотрим два основных свойства компоновщика, с которыми нам предстоит работать:
FixedSettings) — отборы, установленные здесь, применяются "жестко". Пользователь не видит их в стандартной панели настроек и зачастую не может их отключить. Это идеально подходит для логики, диктуемой бизнес-процессом (например, показать документы только по текущей организации).UserSettings) — это те настройки, которые пользователь видит в форме (в шапке списка или по кнопке "Настроить список"). Изменяя их программно, мы как бы эмулируем действия пользователя.Этот метод является наиболее надежным, если нам нужно скрыть отбор от пользователя или гарантировать, что он будет применен поверх любых пользовательских фильтров. Давайте посмотрим, как это реализуется на практике.
Для начала нам необходимо получить коллекцию элементов отбора. Обратимся к свойству Отбор внутри фиксированных настроек.
Разберем алгоритм действий:
Посмотрим на пример кода, который устанавливает отбор по полю Склад:
// Создаем новый элемент отбора
НовыйОтбор = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// Указываем, по какому полю будем фильтровать.
// Важно: имя поля должно совпадать с полем в запросе динамического списка.
НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Склад");
// Устанавливаем вид сравнения (Равно, ВСписке, Содержит и т.д.)
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
// Задаем значение, по которому фильтруем
НовыйОтбор.ПравоеЗначение = СсылкаНаСклад;
// Включаем отбор
НовыйОтбор.Использование = Истина;
Давайте проанализируем этот код. Мы используем конструктор Новый ПолеКомпоновкиДанных. Это критически важный момент: нельзя просто передать строку "Склад", система ожидает именно объект типа ПолеКомпоновкиДанных.
Важный нюанс: Если вы используете произвольный запрос в динамическом списке, убедитесь, что поле, по которому вы делаете отбор, присутствует в выборке этого запроса (на вкладке "Компоновка данных" в конструкторе запроса, либо просто в списке полей).
Часто бывает неудобно каждый раз писать 5-6 строк кода для добавления одного отбора. Давайте создадим универсальную процедуру, которую можно разместить в общем модуле или в модуле формы, чтобы упростить процесс.
Посмотрим, как можно оптимизировать код:
&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьОтборВДинамическомСписке(Список, ИмяПоля, Значение, ВидСравнения = Неопределено, Использование = Истина)
// Если вид сравнения не передан, считаем, что это "Равно"
Если ВидСравнения = Неопределено Тогда
ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
КонецЕсли;
// Ищем, нет ли уже такого отбора в фиксированных настройках, чтобы не плодить дубли
ЭлементыОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы;
НайденныйЭлемент = Неопределено;
Для Каждого Элемент Из ЭлементыОтбора Цикл
// Проверяем тип, так как в коллекции могут быть и ГруппыОтбора
Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных")
И Элемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяПоля) Тогда
НайденныйЭлемент = Элемент;
Прервать;
КонецЕсли;
КонецЦикла;
// Если не нашли - создаем новый, если нашли - обновляем его
Если НайденныйЭлемент = Неопределено Тогда
НайденныйЭлемент = ЭлементыОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НайденныйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяПоля);
КонецЕсли;
НайденныйЭлемент.ВидСравнения = ВидСравнения;
НайденныйЭлемент.ПравоеЗначение = Значение;
НайденныйЭлемент.Использование = Использование;
КонецПроцедуры
Теперь, имея такую процедуру, мы можем устанавливать отбор в одну строку кода внутри обработчика ПриСозданииНаСервере:
// Пример использования
УстановитьОтборВДинамическомСписке(Список, "Контрагент", Объект.Покупатель);
Если ваша конфигурация построена на базе БСП (например, ERP, УТ 11, Бухгалтерия 3.0), то разработчики 1С уже позаботились о вас. Рассмотрим модуль ОбщегоНазначенияКлиентСервер. В нем есть готовые методы для манипуляции отборами.
Разберем пример использования типовой функции:
// Добавление отбора через БСП
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список,
"Организация",
МояОрганизация,
ВидСравненияКомпоновкиДанных.Равно,
"Организация (только просмотр)",
Истина
);
Использование функций БСП предпочтительнее, так как они корректно обрабатывают различные сложные ситуации (например, когда отбор находится внутри группы ИЛИ).
Иногда нам нужно установить отбор так, чтобы пользователь видел его в настройках и мог при желании отключить. Для этого мы должны работать со свойством ПользовательскиеНастройки.
Однако здесь есть подводный камень. Структура пользовательских настроек сложнее. Элементы там хранятся по идентификаторам. Связь между основными настройками и пользовательскими осуществляется через свойство ИдентификаторПользовательскойНастройки.
Посмотрим, как правильно найти нужный элемент в пользовательских настройках:
Процедура УстановитьПользовательскийОтбор(Список, ИмяПоля, Значение)
Компоновщик = Список.КомпоновщикНастроек;
// 1. Ищем элемент в основных настройках (или создаем его там, если его нет в схеме)
// В простых случаях можно перебирать элементы пользовательских настроек напрямую
Для Каждого ЭлементНастройки Из Компоновщик.ПользовательскиеНастройки.Элементы Цикл
// Нам нужны только элементы отбора
Если ТипЗнч(ЭлементНастройки) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
If ЭлементНастройки.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяПоля) Тогда
ЭлементНастройки.ПравоеЗначение = Значение;
ЭлементНастройки.Использование = Истина;
// Включаем отображение в быстрых настройках
ЭлементНастройки.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ;
Возврат;
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Если не нашли - добавляем (работает для динамических списков без жесткой схемы)
НовыйЭлемент = Компоновщик.ПользовательскиеНастройки.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяПоля);
НовыйЭлемент.ПравоеЗначение = Значение;
НовыйЭлемент.Использование = Истина;
КонецПроцедуры
Что делать, если задача стоит сложнее: "Показать документы, где Склад = Склад1 ИЛИ Склад = Склад2"? Стандартный список отборов работает по логике "И" (должны выполняться все условия). Для реализации логики "ИЛИ" нам потребуется использовать ГруппаОтбораКомпоновкиДанных.
Рассмотрим реализацию группировки условий:
// Получаем коллекцию элементов
Коллекция = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы;
// Создаем новую группу
НоваяГруппа = Коллекция.Добавить(Тип("ГруппаОтбораКомпоновкиДанных"));
// Устанавливаем тип группировки - ИЛИ
НоваяГруппа.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
// Добавляем элементы ВНУТРЬ этой группы
Элемент1 = НоваяГруппа.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Элемент1.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Статус");
Элемент1.ПравоеЗначение = "ВРаботе";
Элемент1.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Элемент2 = НоваяГруппа.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Элемент2.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Статус");
Элемент2.ПравоеЗначение = "НаСогласовании";
Элемент2.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
В результате этот код отберет документы, у которых статус либо "ВРаботе", либо "НаСогласовании". Это мощный механизм, позволяющий строить очень гибкие фильтры.
Проанализируем типичные ошибки, которые допускают разработчики при работе с отборами:
СправочникСсылка.Номенклатура, а вы передаете в ПравоеЗначение строку или код, отбор работать не будет. Типы должны строго совпадать.Список.Отбор вместо Компоновщика. В старых версиях платформы или в обычных формах использовалось свойство Отбор самого списка. В управляемых формах 8.3 корректно работать именно через Список.КомпоновщикНастроек.Использование = Истина, фильтр не применится.Мы подробно рассмотрели методы программного управления отборами в динамических списках. Это базовый навык для любого 1С-программиста. Используйте фиксированные настройки для жесткой логики приложения и пользовательские настройки для улучшения UX (User Experience). Не забывайте про возможности БСП, которые могут сэкономить время на написание служебного кода.
Применяя эти знания, вы сможете создавать удобные и функциональные интерфейсы, которые будут реагировать на контекст работы пользователя и показывать именно ту информацию, которая нужна в данный момент.