В процессе разработки на платформе 1С:Предприятие 8.3 одной из наиболее частотных задач является управление данными в динамических списках. Часто нам требуется не просто вывести все записи таблицы, а ограничить их по определенному критерию — например, показать документы только по конкретному договору. Однако при реализации этой задачи начинающие разработчики часто сталкиваются с трудностями, связанными с типами данных и контекстом выполнения кода. Разберем подробно, как правильно устанавливать отборы, почему возникают ошибки сериализации и какой метод выбрать в зависимости от бизнес-логики.
Проанализируем ситуацию, описанную в сообщении №10. При попытке установить отбор возникает ошибка: Ошибка отображения типов: Отсутствует отображение для типа 'ПолеФормы'. Это происходит потому, что в свойство ПравоеЗначение элемента отбора передается элемент управления формы (визуальный объект), а не само значение, которое в нем содержится.
В управляемом приложении 1С объекты интерфейса (элементы формы) существуют только на клиенте и не могут быть переданы на сервер «как есть». Настройки динамического списка (Компоновщик настроек) требуют передачи конкретных ссылок, строк или чисел. Если вы обращаетесь к значению через Элементы.Договор, вы обращаетесь к полю формы. Для корректной работы следует обращаться напрямую к реквизиту формы, к которому привязано это поле (например, просто Договор или Объект.Договор).
Рассмотрим стандартный способ установки отбора через обращение к элементам компоновки данных динамического списка. Этот метод универсален и подходит для списков, работающих как на основе основной таблицы, так и на основе произвольного запроса.
Процедуру установки отбора лучше всего выносить на сервер. Разберем по шагам создание нового элемента отбора:
&НаСервере
Процедура УстановитьОтборНаСервере()
// 1. Очищаем старые отборы по этому полю, чтобы избежать дублирования
ПолеОтбора = Новый ПолеКомпоновкиДанных("Договор");
Индекс = 0;
Пока Индекс < Список.Отбор.Элементы.Количество() Цикл
Элемент = Список.Отбор.Элементы[Индекс];
Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных")
И Элемент.ЛевоеЗначение = ПолеОтбора Тогда
Список.Отбор.Элементы.Удалить(Элемент);
Иначе
Индекс = Индекс + 1;
КонецЕсли;
КонецЦикла;
// 2. Добавляем новый элемент отбора
НовыйОтбор = Список.Отбор.Эelements.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйОтбор.ЛевоеЗначение = ПолеОтбора;
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
НовыйОтбор.Использование = Истина;
// Важно: передаем реквизит (ссылку), а не элемент формы!
НовыйОтбор.ПравоеЗначение = Объект.Договор;
КонецПроцедуры
В данном примере мы используем ПолеКомпоновкиДанных. Обратите внимание, что имя поля должно точно совпадать с именем реквизита в источнике данных динамического списка. Если ваш список построен на запросе, используйте псевдоним поля из текста запроса.
Выясним, в чем разница между различными коллекциями компоновщика настроек, так как это критично для интерфейса пользователя:
Посмотрим на пример установки «жесткого» отбора, который нельзя отключить через интерфейс:
&НаСервере
Процедура УстановитьФиксированныйОтбор()
ГруппаОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор;
ГруппаОтбора.Элементы.Очистить(); // Осторожно: удалит все фиксированные отборы!
НовыйЭлемент = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Договор");
НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
НовыйЭлемент.ПравоеЗначение = Объект.Договор;
НовыйЭлемент.Использование = Истина;
КонецПроцедуры
Проанализируем ситуацию, когда динамический список использует сложный произвольный запрос. В этом случае гораздо эффективнее и правильнее использовать параметры самого запроса, а не механизмы отбора компоновки.
Во-первых, в тексте запроса динамического списка должно быть условие:
ГДЕ Таблица.Договор = &ВыбранныйДоговор
Во-вторых, в коде модуля формы мы устанавливаем значение этого параметра:
&НаСервере
Процедура ОбновитьДанныеСписка()
// Используем метод УстановитьЗначениеПараметра для коллекции Параметры
Список.Параметры.УстановитьЗначениеПараметра("ВыбранныйДоговор", Объект.Договор);
КонецПроцедуры
Преимущество этого метода: Платформа оптимизирует выполнение запроса на уровне СУБД, что работает значительно быстрее на больших объемах данных, чем наложение фильтров поверх результата общего запроса.
Если нам нужно, чтобы список обновлялся сразу после того, как пользователь выбрал договор в поле на форме, выполним следующие шаги:
ПриИзменении для поля выбора договора.
&НаКлиенте
Процедура ДоговорПриИзменении(Элемент)
// Вызываем серверный контекст для работы с динамическим списком
ОбновитьОтборНаСервере();
КонецПроцедуры
&НаСервере
Процедура ОбновитьОтборНаСервере()
// Используем упрощенный метод установки параметра, если он задан в запросе
Список.Параметры.УстановитьЗначениеПараметра("Договор", Объект.Договор);
КонецПроцедуры
Рассмотрим еще несколько важных моментов, которые помогут избежать ошибок:
ЛОЖЬ или ИСТИНА, убедитесь, что тип поля в списке действительно булево.ПравоеЗначение.ГДЕ (&Договор = ЗНАЧЕНИЕ(Справочник.Договоры.ПустаяСсылка) ИЛИ Договор = &Договор).Таким образом, мы разобрали основные способы программного управления отборами в динамическом списке. Главный секрет успеха — четкое понимание того, где находятся ваши данные (в реквизитах, а не в элементах формы) и какой механизм (параметры или отборы) лучше подходит для конкретной задачи производительности.