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