При разработке расширений для типовых конфигураций, таких как Управление торговлей 11.4, ERP или Комплексная автоматизация, часто возникает задача ограничить видимость данных в списках. Например, нам нужно, чтобы при открытии формы списка документов «Расходный кассовый ордер» пользователь видел только те записи, сумма которых превышает определенный порог. В этой статье мы подробно разберем, как правильно реализовать такой функционал, проанализируем типичные ошибки начинающих разработчиков и рассмотрим наиболее эффективные методы управления динамическими списками.
Рассмотрим ситуацию, с которой часто сталкиваются программисты. Пытаясь установить отбор, разработчик создает в расширении процедуру-перехватчик ПриСозданииНаСервереПосле и пишет код, создающий новый объект НастройкиКомпоновкиДанных. Давайте выясним причину, по которой такой подход не дает результата.
Проблема заключается в том, что когда мы пишем Список = Новый НастройкиКомпоновкиДанных, мы создаем в памяти абсолютно новый, независимый объект, который никак не связан с тем динамическим списком, который отображается на форме. Даже если мы заполним этот объект правильными полями и видами сравнения, сама форма о них «не узнает», так как ее основной реквизит продолжает использовать свои старые настройки.
Важный момент: динамический список на форме — это уже существующий объект (реквизит формы), у которого есть свойство Отбор. Именно с этим свойством и нужно работать напрямую.
Для того чтобы отбор заработал, нам необходимо обратиться к конкретному реквизиту формы, который является динамическим списком. В типовых конфигурациях имя этого реквизита часто совпадает с именем списка (например, Список или РасходныеКассовыеОрдера).
Разберем по шагам правильный алгоритм действий в расширении:
ПриСозданииНаСервере с типом вызова «После».Посмотрим на пример работающего кода:
&НаСервере
Процедура Расш_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Обращаемся напрямую к реквизиту формы "Список" (или иному имени списка)
НовыйЭлемент = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// Указываем поле, по которому будет идти фильтрация
НовыйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СуммаДокумента");
// Устанавливаем условие (Больше, Меньше, Равно и т.д.)
НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Больше;
// Задаем значение для сравнения
НовыйЭлемент.ПравоеЗначение = 100;
// Активируем отбор
НовыйЭлемент.Использование = Истина;
// Делаем отбор недоступным для изменения пользователем (по желанию)
НовыйЭлемент.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
КонецПроцедуры
Если вы работаете в современной конфигурации на базе Библиотеки стандартных подсистем (БСП), мы рекомендуем использовать встроенные программные интерфейсы. Это делает код более коротким, понятным и защищенным от ошибок (например, от дублирования одного и того же отбора при повторном открытии формы).
Проанализируем использование процедуры УстановитьЭлементОтбораДинамическогоСписка из общего модуля ОбщегоНазначенияКлиентСервер. Рассмотрим пример:
&НаСервере
Процедура Расш_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Имя реквизита списка, имя поля в запросе, значение и вид сравнения
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список,
"СуммаДокумента",
100,
ВидСравненияКомпоновкиДанных.Больше,
"Отбор по сумме", // Заголовок (необязательно)
Истина, // Использование
РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный
);
КонецПроцедуры
Этот метод хорош тем, что он самостоятельно проверяет наличие существующего отбора по данному полю и либо обновляет его, либо создает новый, избавляя разработчика от лишних проверок.
Иногда требуется установить такой отбор, который пользователь вообще не сможет увидеть или сбросить через меню «Настроить список». В этом случае обычное свойство Отбор не совсем подходит, так как оно смешивается с пользовательскими фильтрами.
Выясним, как использовать ФиксированныеНастройки. Отборы, помещенные в эту коллекцию, работают параллельно с пользовательскими. То есть, если мы зафиксируем отбор по сумме > 100, а пользователь сам поставит фильтр по конкретному контрагенту, система покажет документы, удовлетворяющие обоим условиям одновременно.
Рассмотрим пример реализации через фиксированные настройки:
&НаСервере
Процедура УстановитьЖесткийОтбор(Форма)
Настройки = Форма.Список.КомпоновщикНастроек.ФиксированныеНастройки;
// Проверяем, нет ли уже такого отбора, чтобы не плодить копии
Элемент = Неопределено;
Для Каждого Эл Из Настройки.Отбор.Элементы Цикл
Если ТипЗнч(Эл) = Тип("ЭлементОтбораКомпоновкиДанных")
И Эл.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СуммаДокумента") Тогда
Элемент = Эл;
Прервать;
КонецЕсли;
КонецЦикла;
Если Элемент = Неопределено Тогда
Элемент = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
КонецЕсли;
Элемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СуммаДокумента");
Элемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Больше;
Элемент.ПравоеЗначение = 100;
Элемент.Использование = Истина;
КонецПроцедуры
Проанализируем ситуацию с точки зрения скорости работы базы данных. Динамический список — это, по сути, SQL-запрос, который выполняется каждый раз при прокрутке или обновлении формы. Если мы устанавливаем отбор по полю СуммаДокумента в базе, где миллионы документов, система может начать «подтормаживать».
Для оптимизации работы списка рекомендуем:
Дата, Номер, Проведен, Контрагент).ГДЕ непосредственно в текст SQL-запроса.Мы рассмотрели несколько способов программного управления фильтрами в динамических списках. Подведем итоги: для простых задач в расширении достаточно использовать метод Добавить() в коллекции Список.Отбор.Элементы. Для более профессиональной разработки в типовых конфигурациях лучше применять методы БСП, а для создания скрытых от пользователя ограничений — Фиксированные настройки компоновщика данных. Помните, что правильное обращение к реквизитам формы — это залог стабильной работы вашего расширения.