Разработка и Конфигурация · 12 мин
Как программно заполнить динамический список в 1С
Как программно настроить динамический список в 1С: произвольный запрос, параметры, отборы, основная таблица и типичные ошибки с примерами кода.
Динамический список в 1С — это элемент формы, который автоматически отображает данные из базы и обновляет их при изменениях. По умолчанию платформа сама строит запрос по указанной основной таблице, но во многих задачах этого недостаточно: нужны соединения нескольких таблиц, виртуальные таблицы регистров, отборы по параметрам или вычисляемые поля. В таких случаях список заполняют программно — через произвольный запрос и настройку свойств элемента формы.
Заполнение динамического списка сводится к трём вещам: тексту запроса, значениям параметров и отборам. Всё это можно задать как в конфигураторе (свойства реквизита формы), так и в коде модуля формы — например, при создании формы на сервере или при изменении условий отбора пользователем. Ниже разобраны оба подхода с примерами на встроенном языке.
Важно понимать ограничение: динамический список нельзя «заполнить» коллекцией значений напрямую, как таблицу значений. Он всегда работает через запрос к базе данных. Если нужно показать произвольные вычисленные данные, не хранящиеся в таблицах, — используйте таблицу значений или дерево значений вместо динамического списка.
Что такое динамический список и когда нужен произвольный запрос
Динамический список — реквизит формы типа «ДинамическийСписок», который платформа использует для отображения списков справочников, документов, регистров. Он построен на механизме компоновки данных: платформа формирует запрос, применяет отборы и сортировку, постранично считывает данные и автоматически обновляет их при записи объектов.
Стандартного режима достаточно, если нужно просто показать таблицу целиком. Произвольный запрос требуется, когда:
- нужно объединить данные нескольких таблиц (например, документы и остатки по ним);
- требуются виртуальные таблицы регистров — остатки, обороты, срезы последних;
- нужны вычисляемые поля, группировки, итоги, условная логика через ВЫБОР;
- список должен показывать данные, отфильтрованные сложным условием, которое не выразить стандартным отбором.
Признак правильного выбора: если данные можно получить одним запросом к базе — динамический список подходит. Если данные рождаются в результате обхода, расчёта или получены извне (HTTP, файлы) — нужен другой элемент.
Настройка произвольного запроса в конфигураторе
Простейший путь — задать запрос статически, в свойствах реквизита формы. Откройте форму в конфигураторе, выделите реквизит типа «ДинамическийСписок» и в палитре свойств установите флаг «Произвольный запрос». После этого станет активной строка «Настройка списка», где открывается конструктор: на вкладке «Запрос» вводится текст, на вкладках «Параметры» и «Отбор» — значения и условия.
Пример запроса, показывающего заказы с остатками по ним:
ВЫБРАТЬ
Заказы.Ссылка КАК Заказ,
Заказы.Контрагент КАК Контрагент,
ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
ИЗ
Документ.ЗаказПокупателя КАК Заказы
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ЗаказыПокупателей.Остатки КАК Остатки
ПО Заказы.Ссылка = Остатки.Заказ
Обратите внимание: поле ссылки на объект (Заказ в примере) обязательно должно присутствовать в выборке, иначе платформа не сможет корректно работать со строками списка — открывать объекты, позиционироваться, обновлять. Для списков с возможностью интерактивного изменения данных также потребуется указать основную таблицу.
Программная установка текста запроса
Когда текст запроса зависит от условий — роли пользователя, выбранного режима, переданных параметров формы — его формируют в коде. Обычно это делают в обработчике «ПриСозданииНаСервере»:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.ПроизвольныйЗапрос = Истина;
Список.ОсновнаяТаблица = "Документ.РеализацияТоваровУслуг";
ТекстЗапроса =
"ВЫБРАТЬ
| Реализация.Ссылка КАК Ссылка,
| Реализация.Контрагент КАК Контрагент,
| Реализация.СуммаДокумента КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Организация = &Организация";
Список.УстановитьТекстЗапроса(ТекстЗапроса);
Список.Параметры.УстановитьЗначениеПараметра("Организация", ТекущаяОрганизация);
КонецПроцедуры
Ключевые моменты этого кода. Свойство «ОсновнаяТаблица» стоит указывать, если список должен поддерживать стандартные команды: создание, копирование, пометку на удаление. Без основной таблицы эти команды будут недоступны или поведут себя неочевидно. Установку параметра выполняют после установки текста запроса — иначе параметр может не найтись.
Менять текст запроса можно и позже, например при переключении закладок формы. После вызова УстановитьТекстЗапроса список перечитывается автоматически, дополнительно вызывать обновление не требуется.
Передача параметров и работа с отборами
Параметры запроса устанавливаются через коллекцию «Параметры» динамического списка. Типичная ошибка — обращение к параметру, которого нет в тексте запроса: платформа выдаст ошибку «Параметр не найден». Поэтому параметр сначала объявляют в тексте (&Имя), затем устанавливают значение.
Список.Параметры.УстановитьЗначениеПараметра("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));
Список.Параметры.УстановитьЗначениеПараметра("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));
Отборы, которые пользователь может менять интерактивно, лучше реализовывать не через ГДЕ в тексте запроса, а через коллекцию отбора списка. Тогда условие добавляется и снимается без изменения запроса:
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = ВыбранныйКонтрагент;
ЭлементОтбора.Использование = Истина;
Правило выбора простое: постоянные, обязательные условия — в текст запроса (они быстрее и надёжнее), изменяемые пользователем — в отбор компоновки. Отбор компоновки платформа добавляет к запросу динамически, и пользователь видит его в настройках списка.
Способы ограничить данные списка
Подходит для постоянных ограничений и условий по виртуальным таблицам. Пользователь не может его отключить, что бывает и плюсом.
Подходит для интерактивных фильтров. Виден пользователю, может сочетаться с быстрым поиском и настройками формы.
Подходит для периодов, организаций и других значений, которые задаёт код. Пользователю не видны без дополнительной настройки.
Динамический список на схеме компоновки данных
Для сложных сценариев — когда нужны и произвольный запрос, и гибкие пользовательские настройки группировок и полей — динамический список строят на схеме компоновки данных (СКД). Схему создают программно или берут из макета, затем передают в список:
Схема = ПолучитьМакет("СхемаСпискаДокументов");
Список.УстановитьСхемуКомпоновкиДанных(Схема);
Список.УстановитьНастройки(Схема.НастройкиПоУмолчанию);
Этот подход оправдан, когда пользователю нужно самостоятельно менять состав колонок, группировки и порядок, а разработчику — контролировать источник данных. Для простого списка с фиксированным набором колонок СКД избыточна: произвольного запроса и отборов достаточно.
Учтите, что при работе через СКД отладка сложнее: итоговый запрос формируется компоновщиком, и ошибки вида «поле не найдено» часто возникают из-за несовпадения имён полей в наборе данных и в настройках.
Как выбрать способ заполнения
Обновление списка и проверка результата
После изменения параметров или отбора в коде список обычно перечитывается сам. Если данные изменились извне (например, фоновое задание записало документы) и список не обновился, вызовите:
Элементы.Список.Обновить();
Проверять результат удобно по нескольким контрольным точкам: открывается ли объект двойным щелчком, работает ли создание нового элемента, совпадает ли число строк с результатом того же запроса в консоли запросов, сохраняется ли отбор после переоткрытия формы. Расхождение числа строк почти всегда означает, что платформа добавила к вашему запросу собственные условия — например, по основной таблице или разделителям данных.
Для диагностики итогового запроса полезно временно вывести его в журнал регистрации или скопировать текст запроса в консоль и выполнить с теми же параметрами. Так видно, какие условия реально ушли на СУБД.
Как проверить результат
Совпадает с результатом того же запроса в консоли
Строк меньше — платформа добавила скрытые условия или отбор
Двойной щелчок открывает нужный объект
Ничего не происходит — в запросе нет поля ссылки или оно не уникально
Кнопки работают и создают объект нужного типа
Команды недоступны — не указана основная таблица
Фильтр применяется и отображается в настройках списка
Отбор «слетает» — условие зашито в текст запроса, а не в отбор компоновки
Типичные ошибки и ограничения
Самая частая ошибка — установка параметра до текста запроса или с опечаткой в имени. Вторая по частоте — попытка использовать динамический список как временное хранилище произвольных данных: в него нельзя «добавить строку», он только читает базу. Третья — тяжёлые запросы без ограничений: список из сотен тысяч строк с соединениями без индексированных условий будет открываться медленно, и виновата будет не платформа, а отсутствие отборов по периоду или организации.
Ещё одно ограничение касается виртуальных таблиц: параметры виртуальной таблицы (период, условие) задаются в её скобках в тексте запроса и должны быть параметрами запроса, а не выражениями. Также помните, что в тонком и веб-клиенте весь код установки запроса выполняется на сервере — директива &НаСервере обязательна.
Наконец, избегайте вызова УстановитьТекстЗапроса в часто срабатывающих обработчиках (например, при активизации строки): каждая установка вызывает полное перечитывание списка и лишнюю нагрузку на СУБД. Меняйте параметры, а не текст, если структура запроса не изменилась.
FAQ
Можно ли заполнить динамический список из таблицы значений?
Нет, напрямую нельзя: динамический список работает только через запрос к базе данных. Обходные варианты — поместить таблицу во временную таблицу запроса и выбрать из неё (через менеджер временных таблиц в СКД), либо заменить элемент формы на обычную таблицу значений, если динамическое обновление не нужно.
Почему список пустой, хотя запрос в консоли возвращает строки?
Чаще всего платформа добавила собственные условия: отбор, оставшийся от настроек пользователя, условие по основной таблице или разделители данных в разделённой информационной базе. Проверьте коллекцию Список.Отбор и пользовательские настройки формы, а также выполните запрос под тем же пользователем.
Как задать параметры виртуальной таблицы регистра в произвольном запросе?
Параметры указываются в скобках виртуальной таблицы в тексте запроса, например: РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ). Значения этим параметрам присваиваются стандартно — через Список.Параметры.УстановитьЗначениеПараметра().
Нужно ли указывать основную таблицу при произвольном запросе?
Не обязательно, но рекомендуется, если список должен поддерживать интерактивные команды: создание, копирование, пометку удаления, открытие объекта. Без основной таблицы список становится фактически отчётным — только для просмотра.
Как программно снять установленный ранее отбор?
Найдите нужный элемент в коллекции Список.Отбор.Элементы и установите ему Использование = Ложь либо удалите методом Удалить(). Если отбор задан условием ГДЕ в тексте запроса, снять его можно только заменой текста запроса.
Что важно запомнить
Динамический список заполняется только запросом к базе: включите ПроизвольныйЗапрос, задайте текст через УстановитьТекстЗапроса(), передайте параметры и вынесите изменяемые фильтры в отбор компоновки. Поле ссылки и основная таблица обеспечивают работу стандартных команд, а тяжёлые запросы без отборов — главный источник проблем с производительностью.