Параметры и отборы динамического списка: код, настройки и скорость
Содержание
Параметр динамического списка устанавливают одной строкой: Список.Параметры.УстановитьЗначениеПараметра("Склад", Склад);. Обычно это делают в обработчике формы ПриСозданииНаСервере, а при смене значения на форме — прямо на клиенте, в событии ПриИзменении поля. Список перечитается сам, вызывать Элементы.Список.Обновить() не нужно.
Частое заблуждение — путать параметр и отбор. Параметр (&Склад) живёт внутри текста запроса, и без значения список не покажет данные. Отбор накладывается поверх готового запроса, его видит и может менять пользователь. От того, что выбрать, зависят и логика формы, и скорость работы.
Параметр, отбор и настройки: из чего состоит динамический список
Динамический список — это реквизит формы типа ДинамическийСписок. Он не загружает таблицу целиком, а читает данные порциями по мере прокрутки. Под капотом работает система компоновки данных (СКД), поэтому отборы, сортировка и оформление устроены как в отчётах.
Что можно настроить у списка:
- 🔹 Параметры запроса — значения для
&Имяв тексте произвольного запроса. Задаются только программно. - 🔹 Отбор — условия на поля результата. Задаются из кода, через настройки формы или самим пользователем.
- 🔹 Порядок — сортировка. Пользователь меняет её щелчком по колонке.
- 🔹 Условное оформление — цвет и шрифт строк по условию.
- 🔹 Группировка — вывод строк иерархией по полю.
Когда что выбирать:
| Задача | Чем решать | Почему |
|---|---|---|
| Остатки на дату, цена на дату | Параметр в виртуальной таблице | Условие считается внутри таблицы, а не после неё |
| Показать документы только одной организации | Отбор из кода | Не нужен произвольный запрос |
| Фильтр, который пользователь меняет сам | Отбор с пользовательской настройкой | Появляется на форме, сохраняется между сеансами |
| Значение влияет на соединения в запросе | Параметр | Отбор накладывается только на итоговые поля |
Настройка отборов в режиме предприятия
Пользователю для фильтрации кода не нужно. В формах списков с интерфейсом «Такси» есть несколько способов.
- Строка поиска над таблицей. Ищет введённый текст по видимым колонкам. Подходит для поиска по номеру, наименованию, ИНН.
- Меню «Ещё» командной панели списка. Там есть команда настройки списка: на вкладке отбора добавьте поле, вид сравнения и значение. Настройка сохраняется для этого пользователя.
- Быстрые отборы на форме. Если разработчик вывел элементы отбора в режим быстрого доступа, поля фильтра стоят прямо над таблицей: организация, склад, статус.
- Расширенный поиск по колонке — через то же меню «Ещё» или контекстное меню ячейки, в зависимости от конфигурации.
Если список «вдруг» показывает не все документы, первым делом откройте настройку списка и посмотрите вкладку отбора. Пользователь мог сам включить фильтр месяц назад, и он сохранился.
Сбросить пользовательские настройки можно в той же форме настройки списка: там есть команда стандартных настроек. Отборы, которые наложил разработчик из кода, при этом не исчезнут — они не входят в пользовательские настройки.
Как задать параметр динамического списка из кода
Шаг 1. Включите произвольный запрос
Параметры доступны только при произвольном запросе. В конфигураторе откройте свойства реквизита Список и включите флажок Произвольный запрос. Затем через Настройки списка напишите текст запроса с параметром.
Пример запроса с параметром в виртуальной таблице остатков:
ВЫБРАТЬ
Остатки.Номенклатура КАК Номенклатура,
Остатки.Склад КАК Склад,
Остатки.КоличествоОстаток КАК Остаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОстатков, Склад = &Склад) КАК Остатки
Имя регистра условное — подставьте своё. Если в конфигурации задано свойство ОсновнаяТаблица, укажите главную таблицу запроса: так платформа понимает, что является ключом строки.
Шаг 2. Установите значения при открытии формы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Склад = Параметры.Склад; // реквизит формы, пришёл при открытии
Список.Параметры.УстановитьЗначениеПараметра("Склад", Склад);
Список.Параметры.УстановитьЗначениеПараметра("ДатаОстатков", ТекущаяДатаСеанса());
КонецПроцедуры
Имя параметра пишется без амперсанда и должно совпадать с текстом запроса буква в букву.
Шаг 3. Меняйте значение при смене поля на форме
&НаКлиенте
Процедура СкладПриИзменении(Элемент)
Список.Параметры.УстановитьЗначениеПараметра("Склад", Склад);
КонецПроцедуры
Серверный вызов здесь не нужен. Реквизит списка доступен на клиенте, после установки параметра список сам запросит новую порцию данных.
Пример: журнал за выбранный период
Частая задача — дать пользователю выбрать период и показать документы только за него. Заведите на форме реквизит Период типа СтандартныйПериод, а в запросе — условие ГДЕ Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода.
&НаКлиенте
Процедура ПериодПриИзменении(Элемент)
Список.Параметры.УстановитьЗначениеПараметра("НачалоПериода", Период.ДатаНачала);
Список.Параметры.УстановитьЗначениеПараметра("КонецПериода", Период.ДатаОкончания);
КонецПроцедуры
При открытии формы задайте период по умолчанию, например текущий месяц, и установите оба параметра в ПриСозданииНаСервере. Иначе при первом открытии список встретит пустые параметры.
Если параметров требуется не два, а пять-шесть, вынесите установку в одну процедуру УстановитьПараметрыСписка() и вызывайте её из всех обработчиков. Так проще не забыть одно из значений при доработке формы.
Параметры, пришедшие при открытии формы
Значения для параметров часто приходят снаружи: из карточки контрагента, из документа-основания, из команды на панели навигации. Передавайте их в структуре параметров ОткрытьФорму, а в форме объявите одноимённые параметры формы. В ПриСозданииНаСервере значения читаются через Параметры.ИмяПараметра и сразу уходят в список. Не забудьте проверить, что значение заполнено: форму могут открыть и без него.
Через БСП
В типовых конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) принято вызывать общий модуль:
ОбщегоНазначенияКлиентСервер.УстановитьПараметрДинамическогоСписка(
Список, "Склад", Склад, ЗначениеЗаполнено(Склад));
Последний аргумент — признак использования. Удобно, когда пустое значение означает «все склады». Перед тем как полагаться на этот приём, проверьте, как ведёт себя ваш запрос с неиспользуемым параметром: открыть форму с пустым складом и посмотреть результат быстрее, чем гадать.
Отбор из кода
Отбор не требует произвольного запроса. Минимальный вариант:
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Организация;
ЭлементОтбора.Использование = Истина;
В конфигурациях на БСП то же делается одним вызовом, и повторный вызов не плодит дубли, а меняет существующий элемент:
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список, "Организация", Организация, ВидСравненияКомпоновкиДанных.Равно, , ЗначениеЗаполнено(Организация));
Есть и путь без кода: открыть форму списка с параметром Отбор. Структура вида Новый Структура("Отбор", Новый Структура("Владелец", Ссылка)) автоматически накладывается на основной список формы.
Сложные выборки на механизмах СКД
Раз динамический список стоит на СКД, многие задачи решаются настройками, а не переписыванием запроса.
Вложенные условия. Отбор поддерживает группы «И», «ИЛИ», «НЕ». Добавьте элемент типа ГруппаЭлементовОтбораКомпоновкиДанных, задайте ему ТипГруппы и кладите условия внутрь. Так собирается условие «статус Новый ИЛИ (статус В работе И ответственный — текущий пользователь)».
Условное оформление. Подсветка просроченных строк делается через Список.УсловноеОформление.Элементы.Добавить(). В нём есть свой отбор и набор параметров оформления, например ЦветТекста. Работает быстрее, чем расчёт цвета в запросе.
Отбор и параметр вместе. Типичная связка для отчётных форм:
- параметр
&Период— в виртуальной таблице, чтобы остатки считались на нужную дату; - отбор по складу и номенклатуре — поверх, чтобы пользователь сам сужал выборку.
Ограничения запроса. Динамический список не принимает пакетный запрос: временные таблицы через ПОМЕСТИТЬ в нём не работают. Нужна предварительная выборка — вынесите её в соединение с подзапросом или в виртуальную таблицу с условием. Если запрос не помещается в эти рамки, проще построить форму на таблице значений и заполнять её вручную, отказавшись от порционного чтения.
Остатки(&Дата, Склад = &Склад). Отбор сюда не попадёт.ПриСозданииНаСервере, без идентификатора пользовательской настройки.Скорость фильтрации: что тормозит список
Динамический список читает 40–50 строк за раз, но каждая порция — отдельный запрос с вашим отбором и сортировкой. Медленный запрос пользователь ощущает при каждой прокрутке.
Что замедляет работу:
- 🐢 Отбор по полю виртуальной таблицы вместо параметра. Отбор накладывается на результат: СУБД сначала посчитает остатки по всем складам, потом отбросит лишние. Параметр внутри скобок ограничит расчёт сразу.
- 🐢 Отбор через точку, например
Контрагент.ГоловнойКонтрагент. Каждое разыменование — дополнительное соединение. - 🐢
ПОДОБНО "%текст%"и поиск по строке во всех колонках на больших таблицах. Индекс не используется. - 🐢 Сортировка по неиндексированному полю. Порционное чтение требует упорядочивания, без индекса это полный просмотр.
- 🐢 Вычисляемые поля с
ВЫБОРи подзапросами в списке выбора.
Что помогает:
- Укажите
ОсновнаяТаблицаи не отключайте флажокДинамическое считывание данных. - Переносите условия по измерениям регистров в параметры виртуальных таблиц.
- Индексируйте реквизиты, по которым чаще всего фильтруют и сортируют: свойство
Индексироватьу реквизита. - Убирайте из запроса поля, которых нет на форме. Поля с флажком «Использовать всегда» читаются при каждом обращении.
- Не ставьте параметры в
ПриОткрытиина клиенте, если их можно поставить вПриСозданииНаСервере. Иначе список сначала выполнит запрос без значений, а затем повторит его.
Индексирование реквизита меняет структуру базы. Обновление конфигурации базы данных потребует монопольного доступа: пользователей придётся отключить. Делайте это в нерабочее время и после резервной копии.
Ошибки при установке параметров и отборов
&Имя, а значение не передано. Проверьте, что УстановитьЗначениеПараметра вызывается до первого чтения и имя совпадает с запросом без &.Произвольный запрос выключен, либо запрос сохранили, а реквизит формы остался со старым текстом. Откройте настройки списка в конфигураторе и проверьте текст.ПолеКомпоновкиДанных не совпадает с псевдонимом в запросе, либо у элемента не стоит Использование = Истина.Элементы.Добавить(). Перед добавлением ищите существующий элемент или используйте функцию БСП.Новый Граница(Дата, ВидГраницы.Включая) или КонецДня(Дата).Ещё одна тонкость — порядок событий. Пользовательские настройки списка загружаются после ПриСозданииНаСервере. Если пользователь сохранил свой отбор по тому же полю, он может перекрыть ваш. Поэтому обязательные условия (например, «только документы своей организации» по требованиям безопасности) не стоит полагать на отбор. Для разграничения доступа есть RLS — ограничения на уровне записей в ролях. Отбор пользователь может снять, RLS — нет.
Отладка: поставьте точку останова после установки параметров и вычислите в отладчике Список.Параметры.Элементы. Там видно имя, значение и признак использования каждого параметра. Для отборов смотрите Список.Отбор.Элементы. Сам текст запроса, который уходит в СУБД, удобно ловить замером производительности или технологическим журналом.
Частые вопросы
Можно ли установить параметр динамического списка на клиенте?
УстановитьЗначениеПараметра работает в клиентских процедурах. Список перечитается без серверного вызова из вашего кода.Чем `Список.Отбор` отличается от `Список.КомпоновщикНастроек.Настройки.Отбор`?
Список.Отбор — отбор, который задаёт разработчик. В компоновщике настроек лежат ещё и пользовательские настройки. Для программного фиксированного отбора используйте Список.Отбор.Как передать в параметр список значений?
В (&Склады), а в параметр передайте массив или список значений. Пустой массив даст пустой результат, это учитывайте в логике.